Reorder the services of a category
ids must list exactly the active services of one category, in the new order (sortOrder becomes the index).
The category is the one of the first id, or categoryId when given. A missing, extra, duplicate or foreign
id is 400 (an unknown first id is 404 with field: ids). The answer lists that category's services in the
new order. Draft; the public order moves with POST /catalog/publish. Audited with the API key as the actor.
Requires the catalog:write scope and an Idempotency-Key header.
ApiKeyAuth catalog:writeAuthorizationBearer <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:write
Idempotency-Key*stringCaller-chosen idempotency token for this write. A retry under the SAME key with
the SAME body replays the first response; the SAME key with a DIFFERENT body is
422 IDEMPOTENCY_KEY_MISMATCH. See Idempotency above.
length <= 64application/json- body
ids*array<string>The ids of the category's active services in the new order.
categoryId?stringDefaults to the category of the first id.
The reordered draft services of the category.
application/json- response
data*array<>meta*curl -X PUT 'https://api.shyni.io/api/v1/services/order' \ -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY' \ -H 'Idempotency-Key: 7f3c9a52-1d4e-4b86-a0c7-5e2b9d8f6a13' \ -H 'Content-Type: application/json' \ -d '{ "ids": [ "string" ]}'Response 200
The reordered draft services of the category.
{ "data": [ { "id": "string", "slug": "string", "name": "string", "description": { "plain": "string", "html": "string", "json": { "v": 0, "doc": {} } }, "scope": "PRIMARY", "basePrice": 0, "currency": "string", "durationMinutes": 0, "employeesRequired": 0, "postWorkStrategy": "NONE", "postWorkMinutes": 0, "variants": [ { "code": "string", "priceMultiplier": 0, "extraMinutes": 0 } ], "discountPercent": 0, "pricingMode": "EXACT", "minAdvanceDays": 0, "renewalIntervalMonths": 0, "multiDay": true, "storefrontVisible": true, "sortOrder": 0, "categoryId": "string", "highlight": "NONE", "active": true, "imageId": "string", "includes": [ "string" ], "forWhom": "string", "recommendedAddonIds": [ "string" ], "orderAudience": "ALL", "soldOnlyWithServiceIds": [ "string" ] } ], "meta": { "page": 0, "perPage": 0, "total": 0 }}Response 400
A parameter, header or request body is missing, malformed, or out of range. A request body property the endpoint does not define answers UNKNOWN_FIELD instead, with field naming it.
{ "code": "INVALID_INPUT", "message": "Parameter perPage must be between 1 and 100."}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 404
The resource does not exist, or belongs to a different studio.
{ "code": "NOT_FOUND", "message": "Order not found."}Response 422
The same Idempotency-Key was already used for a request with a different body, use a new key (see Idempotency above).
{ "code": "IDEMPOTENCY_KEY_MISMATCH", "message": "This Idempotency-Key was already used for a different request. Use a new key."}Response 429
Burst rate limit exceeded.
{ "code": "RATE_LIMITED", "message": "Too many requests. Retry after the time given in the Retry-After header."}