Record how a booking link reached the customer
Stores the channel the link was handed over by. EMAIL also sends the customer the link mail, to the
address stored on the link (400 when it has none; 429 when the link was mailed too often in the last
hour); SHARE and COPY only record it. A completed, cancelled or expired link is 409 CONFLICT. 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
channel*stringEMAIL = Shyni mails it; SHARE = the owner sent it from their own phone; COPY = the owner copied the URL.
"EMAIL""SHARE""COPY"The link, with its delivery set.
application/json- response
A booking link as the studio sees it. url is the customer's page for the link and carries its token:
hand it only to the customer. Money is minor units of currency.
id?stringstatus?string"PENDING""COMPLETED""EXPIRED""CANCELLED"url?stringcurrency?stringserviceIds?array<string>serviceNames?array<string>Names against the published catalog, in the order of serviceIds.
optionAnswers?array<>scheduledStart?|Null = open term.
date-timescheduledEnd?|date-timepickupAt?|date-timecustomer?adminNote?string|nullcustomerMessage?string|nullvariant?string|nullsubject?|The owner's prefill of what the customer brings; null when none was given.
agreedPrice?|int64depositOverride?|int64customLines?array<>waiveDayAdjustment?booleanThe order made from this link does not pay the day-policy surcharge.
falseskipDeposit?booleanThe order made from this link requires no deposit.
falseinspectionOrderId?string|nullexpiresAt?stringdate-timecreatedAt?stringdate-timefirstOpenedAt?|date-timeopenCount?integerdelivery?|nullcompletedOrderId?|The order the customer made out of the link.
completedAt?|date-timecancelledAt?|date-timerevision?integerRaised by every real edit (PATCH /booking-links/{id}); the customer's completion is refused when the page they saw is older.
curl -X POST 'https://api.shyni.io/api/v1/booking-links/string/deliver' \ -H 'Authorization: Bearer shyni_sk_test_YOUR_KEY' \ -H 'Idempotency-Key: 7f3c9a52-1d4e-4b86-a0c7-5e2b9d8f6a13' \ -H 'Content-Type: application/json' \ -d '{ "channel": "EMAIL"}'Response 200
The link, with its delivery set.
{ "id": "string", "status": "PENDING", "url": "string", "currency": "string", "serviceIds": [ "string" ], "serviceNames": [ "string" ], "optionAnswers": [ { "questionId": "string", "optionId": "string" } ], "scheduledStart": "2019-08-24T14:15:22Z", "scheduledEnd": "2019-08-24T14:15:22Z", "pickupAt": "2019-08-24T14:15:22Z", "customer": { "name": "string", "email": "string", "phone": "string" }, "adminNote": "string", "customerMessage": "string", "variant": "string", "subject": { "type": "string", "attributes": { "property1": "string", "property2": "string" } }, "agreedPrice": 0, "depositOverride": 0, "customLines": [ { "name": "string", "price": 0, "durationMinutes": 0 } ], "waiveDayAdjustment": false, "skipDeposit": false, "inspectionOrderId": "string", "expiresAt": "2019-08-24T14:15:22Z", "createdAt": "2019-08-24T14:15:22Z", "firstOpenedAt": "2019-08-24T14:15:22Z", "openCount": 0, "delivery": { "channel": "EMAIL", "at": "2019-08-24T14:15:22Z", "to": "string" }, "completedOrderId": "string", "completedAt": "2019-08-24T14:15:22Z", "cancelledAt": "2019-08-24T14:15:22Z", "revision": 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 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."}