Change the agreed price of an order
Changes the amount of the line that carries the order's agreed price (an order completed from a booking
link with a price the studio agreed). An order without an agreed price is refused with 400. The
deposit is not touched and nothing is sent to the customer; totalPrice moves by the difference. The
same price again changes nothing. Minor units of the studio currency, whole crowns. Not tier-gated.
Requires the orders:manage scope and an Idempotency-Key header.
ApiKeyAuth orders:manageAuthorizationBearer <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:manage
id*stringIdempotency-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
price*integerThe new amount in minor units of the studio currency, a whole number of crowns, not negative.
int64The order with its new total.
application/json- response
id*stringInternal order id, use this for GET /api/v1/orders/{id}.
publicId*stringDisplay/reference id shown to the customer, a random 8-digit number without a leading zero (e.g. 48291375), unique per studio; it is also the payment variable symbol. Look an order up by it with GET /api/v1/orders/by-public-id/{publicId}.
state*OrderState"CREATED""CONFIRMED""IN_PROGRESS""DONE""CANCELLED"kind?OrderKindORDER: an ordinary booking. INSPECTION: the studio's free inspection (price 0, no deposit), booked with inspection: true in POST /orders; finish it with POST /orders/{id}/inspection/complete.
"ORDER""INSPECTION"depositState*DepositStatePENDING: a deposit above zero is owed and unpaid on a live order. PAID: the deposit was received. REFUNDED: it was given back. NOT_REQUIRED: no deposit is owed, either because the order never had one (deposit 0, free inspection) or because the order was cancelled before the deposit was paid. A cancelled order whose deposit was already PAID or REFUNDED keeps that state, so depositState=PENDING lists only deposits that still have to be collected.
"PENDING""PAID""REFUNDED""NOT_REQUIRED"currency*stringISO 4217 code of the studio currency every amount on this order (lines, payments, discount included) is denominated in.
depositAmount*integerAmount in minor units of currency (hellers for CZK).
int64depositPaidAt?|date-timescheduledStart*stringdate-timescheduledEnd*stringdate-timepickupAt*stringdate-timecreatedAt*stringdate-timeupdatedAt*stringWhen the order last changed, state, time, price, lines, payments, assignment. Poll key for GET /api/v1/orders?updatedSince=; of two snapshots of the same order (two webhook deliveries, or a delivery and a read) the one with the later updatedAt is the newer.
date-timeexternalRef*|Your own id of the order (set by externalRef on POST /orders), unique per studio; find the order with GET /orders?externalRef=. Null when none.
readyAt?|date-timecustomer*GDPR erasure sentinel values (e.g. redacted placeholders) pass through as-is post-erasure, v1 does not otherwise redact this data.
variant*stringCode of the variant the order was priced as (for detailing, the vehicle size, e.g. MEDIUM).
subject*|The subject the order is for; null when the order carries no data about it.
serviceLines*array<>totalPrice*integerAmount in minor units of currency (hellers for CZK).
int64paidTotal*integerAmount in minor units of currency (hellers for CZK).
int64balanceDue*integerAmount in minor units of currency (hellers for CZK). Negative on overpayment.
int64payments*array<>appliedDiscountCode?|nullnote?string|nullcancellationReason?|Free text given on cancel, or NO_SHOW when the order was cancelled through POST /orders/{id}/no-show.
sourceChannel*stringWhere the order came from. STOREFRONT, EMBED and QR are claimed by the customer's browser; BOOKING_LINK, RETURN_REMINDER, ADMIN and API are decided by the server.
"STOREFRONT""EMBED""QR""BOOKING_LINK""RETURN_REMINDER""ADMIN""API"sourceLabel?|Sanitized campaign or integration label ([a-z0-9-], max 40).
utmSource?string|nullutmMedium?string|nullutmCampaign?string|nullreferrerDomain?|Host name of the page that referred the customer, never a full URL.
attribution*The attribution stored on the order. Every field is null when it was not sent (all orders before this field existed, and orders from the booking page for the click ids and utmTerm / utmContent).
metadata*The flat string map sent as metadata when the order was created through POST /api/v1/orders; {} when none. Free-form keys, see the request schema for the caps.
billing*|The company billing details sent as billing when the order was created through POST /api/v1/orders; null when none were sent, and after the customer's data was erased.
cancelledBy?|Who cancelled the order; HOLD_EXPIRY = the deposit hold elapsed. Null while the order is not cancelled.
"STUDIO""CUSTOMER""HOLD_EXPIRY"nullassignedWorkerId?|Id of the team member the order is assigned to; null when nobody is.
acceptedTermsVersion?integerThe studio terms version sent as acceptedTermsVersion when the order was created; absent when none was sent.
waivedDayAdjustment?integerDay-policy surcharge the studio waived on this order (minor units, waiveDayAdjustment on create); absent when nothing was waived.
int64pendingReschedule?|The customer's open request to move the order, null when there is none. Its id is the {requestId}
of POST /api/v1/orders/{id}/reschedule-requests/{requestId}/approve and .../reject.
rejectedReschedule?|The customer's newest reschedule request when the studio rejected it (the order never moved), null otherwise;
a newer request, an approval or a cancellation replaces it. The window the customer asked for stays readable
here, so an integration can tell the customer which time was declined (webhook order.reschedule_rejected).
inspection?|The studio's verdict on a free inspection (kind INSPECTION); null for an ordinary order. Its
reply stays null until the studio answers (POST /api/v1/orders/{id}/inspection/reply).
curl -X PUT 'https://api.shyni.io/api/v1/orders/string/agreed-price' \ -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY' \ -H 'Idempotency-Key: 7f3c9a52-1d4e-4b86-a0c7-5e2b9d8f6a13' \ -H 'Content-Type: application/json' \ -d '{ "price": 0}'Response 200
The order with its new total.
{ "id": "string", "publicId": "string", "state": "CREATED", "kind": "ORDER", "depositState": "PENDING", "currency": "string", "depositAmount": 0, "depositPaidAt": "2019-08-24T14:15:22Z", "scheduledStart": "2019-08-24T14:15:22Z", "scheduledEnd": "2019-08-24T14:15:22Z", "pickupAt": "2019-08-24T14:15:22Z", "createdAt": "2019-08-24T14:15:22Z", "updatedAt": "2019-08-24T14:15:22Z", "externalRef": "string", "readyAt": "2019-08-24T14:15:22Z", "customer": { "id": "string", "name": "string", "email": "user@example.com", "phone": "string", "externalRef": "string" }, "variant": "string", "subject": { "id": "string", "type": "string", "attributes": { "property1": "string", "property2": "string" }, "summary": "string", "externalRef": "string" }, "serviceLines": [ { "id": "string", "name": "string", "price": 0, "durationMinutes": 0, "packageHead": true, "custom": true, "serviceId": "string", "packageId": "string", "optionAnswers": [ { "questionId": "string", "optionId": "string" } ] } ], "totalPrice": 0, "paidTotal": 0, "balanceDue": 0, "payments": [ { "id": "string", "amount": 0, "method": "string", "recordedAt": "2019-08-24T14:15:22Z", "reference": "string" } ], "appliedDiscountCode": { "code": "string", "type": "string", "discount": 0 }, "note": "string", "cancellationReason": "string", "sourceChannel": "STOREFRONT", "sourceLabel": "string", "utmSource": "string", "utmMedium": "string", "utmCampaign": "string", "referrerDomain": "string", "attribution": { "utmSource": "string", "utmMedium": "string", "utmCampaign": "string", "utmTerm": "string", "utmContent": "string", "referrer": "string", "gclid": "string", "gbraid": "string", "wbraid": "string", "fbclid": "string" }, "metadata": { "property1": "string", "property2": "string" }, "billing": { "company": "string", "ico": "string", "dic": "string", "address": "string" }, "cancelledBy": "STUDIO", "assignedWorkerId": "string", "acceptedTermsVersion": 0, "waivedDayAdjustment": 0, "pendingReschedule": { "id": "string", "requestedStart": "2019-08-24T14:15:22Z", "requestedEnd": "2019-08-24T14:15:22Z", "createdAt": "2019-08-24T14:15:22Z" }, "rejectedReschedule": { "id": "string", "requestedStart": "2019-08-24T14:15:22Z", "requestedEnd": "2019-08-24T14:15:22Z", "reason": "string", "rejectedAt": "2019-08-24T14:15:22Z" }, "inspection": { "reply": "COME", "text": "string", "repliedAt": "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 404
The resource does not exist, or belongs to a different studio.
{ "code": "NOT_FOUND", "message": "Order not found."}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."}