Studios

Create a studio for a client

POST
/api/v1/studios

Creates a studio for your client: a normal Shyni studio (administration, storefront, its own subscription later) that the calling organization owns until the client's owner takes it over. It has no owner person yet, records no contract and sends no e-mail. Until the hand-over the studio stands on the organization's plan, so you can set it up with the same key and the header Shyni-Business: <studio id> (every studio endpoint, e.g. POST /workers, PUT /studio). Invite the owner with POST /studios/{id}/owner-invite. The organization keeps access to the studio after the hand-over; from then on the studio's own plan applies and API access needs the Pro subscription. name is required; timezone defaults to Europe/Prague and currency to CZK (fixed once the studio has orders). Needs a live organization key (409 CONFLICT with a test key). Audited with the API key as the actor. Org-level: send no Shyni-Business header. Requires the businesses:manage scope and an Idempotency-Key header.

Authorization

ApiKeyAuth businesses:manage
headerAuthorizationBearer <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: businesses:manage

Header Parameters

Idempotency-Key*string

Caller-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.

Lengthlength <= 64

Request Body

application/json
  1. body
name*string
Lengthlength <= 255
timezone?string
Default"Europe/Prague"
currency?string

ISO 4217 code in upper case. Fixed once the studio has orders.

Default"CZK"

Response Body

The new studio.

application/json
  1. response
id*string

Send it as Shyni-Business to act on this studio.

name*string
slug*string
createdAt*string
Formatdate-time
handedOver*boolean

true once the owner took the studio over (or the organization only has access to it); the studio's own plan applies from then on.

ownerInvite*|

The pending owner invitation; null before the first invitation and after the hand-over.

Example Request
curl -X POST 'https://api.shyni.io/api/v1/studios' \  -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY' \  -H 'Idempotency-Key: 7f3c9a52-1d4e-4b86-a0c7-5e2b9d8f6a13' \  -H 'Content-Type: application/json' \  -d '{  "name": "string"}'

Response 201

The new studio.

{  "id": "string",  "name": "string",  "slug": "string",  "createdAt": "2019-08-24T14:15:22Z",  "handedOver": true,  "ownerInvite": {    "email": "string",    "sentAt": "2019-08-24T14:15:22Z"  }}

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 409

The request is well-formed but the studio's current state forbids it.

{  "code": "CONFLICT",  "message": "The voucher cannot be deactivated because it is not active."}

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."}