List services
The studio's published catalog, categories, services, and packages.
Also callable with a publishable key (shyni_pk_...).
Always reads the studio's PUBLISHED catalog, never DRAFT, safe to call before
the studio has gone live (no visibility guard: a key reads its own catalog even
pre-launch, so integrations can be built ahead of go-live). packages is empty
for studios whose plan doesn't include packages.
ApiKeyAuth catalog:readAuthorizationBearer <shyni_sk_live_*>An API key, issued once and never retrievable again: an organization key in the developer
portal, or a studio key in the studio's admin (Moje studio → API). Send as Authorization: Bearer shyni_sk_live_....
Scope: catalog:read
The full catalog, wrapped in the list envelope
({"data": {categories, services, packages}}; not paged, so no meta).
application/json- response
data*curl -X GET 'https://api.shyni.io/api/v1/services' \ -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY'Response 200
The full catalog, wrapped in the list envelope
({"data": {categories, services, packages}}; not paged, so no meta).
{ "data": { "categories": [ { "id": "string", "name": "string", "slug": "string", "sortOrder": 0 } ], "services": [ { "id": "string", "slug": "string", "name": "string", "description": { "plain": "string", "html": "string", "json": { "v": 0, "doc": {} } }, "scope": "PRIMARY", "basePrice": 0, "currency": "string", "durationMinutes": 0, "variants": [ { "code": "string", "priceMultiplier": 0, "extraMinutes": 0 } ], "discountPercent": 0, "sortOrder": 0, "categoryId": "string", "highlight": "NONE", "questions": [ { "id": "string", "name": "string", "required": true, "options": [ { "id": "string", "name": "string", "surcharge": 0, "scalesWithSize": true, "extraMinutes": 0, "isDefault": true } ] } ], "pricingMode": "EXACT", "minAdvanceDays": 0, "multiDay": true, "includes": [ "string" ], "storefrontVisible": true, "orderAudience": "ALL", "soldOnlyWithServiceIds": [ "string" ], "image": { "id": "string", "alt": "string", "width": 0, "height": 0, "variants": [ { "key": "string", "url": "string", "width": 0, "height": 0 } ] } } ], "packages": [ { "id": "string", "slug": "string", "name": "string", "description": { "plain": "string", "html": "string", "json": { "v": 0, "doc": {} } }, "basePrice": 0, "currency": "string", "durationMinutes": 0, "components": [ { "id": "string", "service": { "id": "string", "slug": "string", "name": "string", "description": { "plain": "string", "html": "string", "json": { "v": 0, "doc": {} } }, "scope": "PRIMARY", "basePrice": 0, "currency": "string", "durationMinutes": 0, "variants": [ { "code": "string", "priceMultiplier": 0, "extraMinutes": 0 } ], "discountPercent": 0, "sortOrder": 0, "categoryId": "string", "highlight": "NONE", "questions": [ { "id": "string", "name": "string", "required": true, "options": [ { "id": "string", "name": "string", "surcharge": 0, "scalesWithSize": true, "extraMinutes": 0, "isDefault": true } ] } ], "pricingMode": "EXACT", "minAdvanceDays": 0, "multiDay": true, "includes": [ "string" ], "storefrontVisible": true, "orderAudience": "ALL", "soldOnlyWithServiceIds": [ "string" ], "image": { "id": "string", "alt": "string", "width": 0, "height": 0, "variants": [ { "key": "string", "url": "string", "width": 0, "height": 0 } ] } }, "quantity": 0, "sortOrder": 0 } ], "highlight": "NONE" } ] }}Response 401
Missing, malformed, unknown, or revoked API key (INVALID_API_KEY).
{ "code": "INVALID_API_KEY", "message": "Missing or invalid API key."}Response 403
The key is valid but the request is refused. Branch on code: INSUFFICIENT_SCOPE (the key lacks the
permission this endpoint requires), PLAN_REQUIRED (the studio is not on a plan that includes API keys,
Pro and above), ORIGIN_NOT_ALLOWED, SECRET_KEY_IN_BROWSER, or DEMO_STUDIO on a write to the demo studio.
See Authentication and Scopes above.
{ "code": "INSUFFICIENT_SCOPE", "message": "This API key does not have the permission this endpoint requires."}Response 429
Burst rate limit exceeded.
{ "code": "RATE_LIMITED", "message": "Too many requests. Retry after the time given in the Retry-After header."}