Price a booking before it is made
The price of a composition BEFORE booking, exactly what POST /api/v1/orders would charge for the same
serviceIds, variant, optionAnswers, voucherCode and scheduledStart, computed by the same pricing as
the studio's own booking page. Use it instead of calculating prices on your side. Nothing is written or
reserved. Also callable with a publishable key (shyni_pk_...).
scheduledStart is optional. With it, the answer carries available, scheduledEnd and pickupAt and
any day policy of that date is priced in; without it you get an undated price (no day policy, no times,
available: null). Take scheduledStart from GET /api/v1/availability/starts.
A voucherCode that cannot be applied is NOT an error: the answer is 200 with the undiscounted price and
codeError (INVALID, EXPIRED, EXHAUSTED or USED, plus an English sentence). A valid code fills
discountCode (a studio discount code: lowers totalPrice) or giftVoucher (pays the total, only lowers
depositAmount). Money is minor units of currency. depositHoldMinutes says how long an unpaid deposit
holds the slot once you book.
Services the studio prices by hand (from-price, on request) cannot be quoted or booked: 400 INVALID_INPUT
with field serviceIds. A studio that paused online bookings answers 400 INVALID_INPUT; an unpublished
studio 409 STUDIO_NOT_PUBLISHED. Requires the orders:write scope (the verb is POST because of the body;
nothing is changed). There is no Idempotency-Key - a quote is always computed fresh. Rate limited like the
studio's public price preview, per IP and per studio.
ApiKeyAuth orders: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: orders:write
Shyni-Customer-IP?stringPOST /orders, POST /quotes, POST /quotes/batch and POST /gift-vouchers/purchases with a secret key only: the end customer's IPv4 or IPv6 address as your server
saw it. When present, the storefront's per-IP and per-studio booking (quotes: price preview; gift voucher purchases: purchase) budgets apply to that address
(shared with the studio's booking page); an invalid value is 400 INVALID_INPUT. Ignored with a
publishable key (the browser's address is used) and on every other endpoint.
application/json- body
The pricing fields of OrderCreateRequest, same names and shapes. Unknown fields are 400 UNKNOWN_FIELD
(subject and the customer are not part of a price).
serviceIds*array<string>Service and/or package ids from GET /api/v1/services.
variant*|Code of the variant the price is for (see POST /orders). Required.
optionAnswers?array<>Configurator answers, as on POST /orders.
voucherCode?|A gift voucher or discount code; one that cannot be applied comes back as codeError.
scheduledStart?|Optional start of the window. Absent = an undated price.
date-timewaiveDayAdjustment?booleanSecret key only (publishable + true is 403 FORBIDDEN, field waiveDayAdjustment). Prices as POST /orders does with the same flag: no surcharge day policy, waivedDayAdjustment set.
falseskipDeposit?booleanSecret key only (publishable + true is 403 FORBIDDEN, field skipDeposit). Prices as POST /orders does with the same flag: depositAmount 0.
falseThe price.
application/json- response
Money fields are minor units of currency. totalPrice and depositAmount equal what POST /orders charges
for the same fields. available, scheduledStart, scheduledEnd and pickupAt are null for an undated quote.
available*|Whether the window is free (place and team capacity); null for an undated quote.
scheduledStart*|date-timescheduledEnd*|End of the work; null when undated or when the studio cannot work then (closed day, lead time).
date-timepickupAt*|When the customer can collect (work end plus any curing time).
date-timecurrency*stringtotalPrice*integerint64depositAmount*integerint64durationMinutes*integersurcharges*array<>One row per chosen configurator option, in line order.
dayPolicy*|nulldiscountCode*|nullgiftVoucher*|nullcodeError*|nullwaivedDayAdjustment?|Day-policy surcharge waived by waiveDayAdjustment (minor units); null/absent when nothing was waived. Then dayPolicy is null.
int64depositWaivedReason*|"KNOWN_CAR"nulldepositHoldMinutes*|Minutes an unpaid deposit holds the slot after booking; null when no deposit is due.
curl -X POST 'https://api.shyni.io/api/v1/quotes' \ -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY' \ -H 'Content-Type: application/json' \ -d '{ "serviceIds": [ "3b7e9c52-81d4-4f6a-a0c3-2d9e5b8f1a47" ], "variant": "MEDIUM", "scheduledStart": "2026-11-03T08:00:00Z", "voucherCode": "SPRING10"}'Response 200
The price.
{ "available": true, "scheduledStart": "2026-11-03T08:00:00Z", "scheduledEnd": "2026-11-03T09:30:00Z", "pickupAt": "2026-11-03T09:30:00Z", "currency": "CZK", "totalPrice": 75780, "depositAmount": 50000, "durationMinutes": 90, "surcharges": [], "dayPolicy": null, "discountCode": { "code": "SPRING10", "type": "PERCENT", "value": 10, "discount": 8420, "depositWaived": false }, "giftVoucher": null, "codeError": null, "depositWaivedReason": null, "depositHoldMinutes": 30}Response 400
A required field is missing or a value is invalid, or the studio is not taking online bookings right now. field names the offending input when there is one.
{ "code": "INVALID_INPUT", "message": "Field variant is required.", "field": "variant"}{ "code": "INVALID_INPUT", "message": "The studio quotes this service individually. Send an inquiry instead of a booking.", "field": "serviceIds"}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
STUDIO_NOT_PUBLISHED - the studio is not published (a test studio always is bookable).
{ "code": "STUDIO_NOT_PUBLISHED", "message": "The studio is not published; it cannot take bookings."}Response 429
Burst rate limit exceeded.
{ "code": "RATE_LIMITED", "message": "Too many requests. Retry after the time given in the Retry-After header."}