{"openapi":"3.1.0","info":{"title":"GuestMaker Website & Booking-Engine Events","version":"1.0.0","summary":"Tell GuestMaker what visitors do on a website or booking engine, so a journey can follow up.","description":"Send events such as `cart.abandoned` from your server, your booking engine's webhook or a browser, and start journeys from them.\n\nLimits: 64 KB per request (256 KB for a webhook), 50 events per batch, occurred_at within 7 days.\n\nConsent is evidence or it is ignored: `consent.email_marketing: true` is honoured only with the exact `text` and a fresh `captured_at`, and no event can re-subscribe a guest who opted out.\n\nGuide: https://www.guestmaker.ai/developers/events","contact":{"name":"GuestMaker developers","email":"developers@guestmaker.ai","url":"https://www.guestmaker.ai/developers/events"}},"servers":[{"url":"https://www.guestmaker.ai"}],"tags":[{"name":"Events","description":"Send events."},{"name":"Webhook","description":"Receive a booking engine's own payload and map it onto an event."}],"paths":{"/api/v1/website-events":{"post":{"tags":["Events"],"operationId":"sendWebsiteEvents","summary":"Send one event, or a batch of up to 50","description":"Authenticate with a source key: `Authorization: Bearer gme_sk_…` from a server, or a public `gme_pk_…` key from a browser (in `X-GM-Key`, or `?key=` because `navigator.sendBeacon` cannot set headers). A browser key only works from the origins allowed on the source. In a batch every event is judged on its own: the request succeeds and each event carries its own result.","security":[{"ServerKey":[]},{"BrowserKeyHeader":[]},{"BrowserKeyQuery":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Event"},{"$ref":"#/components/schemas/Batch"}]},"examples":{"cartAbandoned":{"summary":"A guest left at the payment step","value":{"event":"cart.abandoned","idempotency_key":"cart_8841","contact":{"email":"ana@example.com","first_name":"Ana","language":"es"},"consent":{"email_marketing":true,"text":"I agree to receive offers from this hotel by email","captured_at":"2026-09-30T10:11:58Z","language":"en","form_id":"checkout-details"},"context":{"hotel_code":"HD-MAD","stage":"payment","check_in":"2026-11-20","check_out":"2026-11-23","adults":2,"room_name":"Deluxe","value":612.4,"currency":"EUR","cart_id":"8841","resume_url":"https://book.example.com/resume?cart=8841"}}}}},"text/plain":{"schema":{"type":"string","description":"The same JSON, sent as text/plain so a browser request needs no CORS preflight."}}}},"responses":{"202":{"description":"Received. Each event has its own result: accepted, duplicate, or rejected (with `issues`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"400":{"description":"**invalid_json** — The body is not valid JSON. Send a JSON body with Content-Type: application/json (or text/plain from navigator.sendBeacon). ([details](https://www.guestmaker.ai/developers/events#error-invalid-json))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"invalid_json","message":"The body is not valid JSON","fix":"Send a JSON body with Content-Type: application/json (or text/plain from navigator.sendBeacon).","docs":"/developers/events#error-invalid-json"}}}}},"401":{"description":"**unauthorized** — Missing or invalid credential. Send the source's key as `Authorization: Bearer <key>` (server), in the webhook URL (webhook), or as `X-GM-Key` or a `?key=` query parameter (browser key only: `navigator.sendBeacon` cannot set headers). Check the key in Settings → Integrations → Website & booking-engine events. ([details](https://www.guestmaker.ai/developers/events#error-unauthorized))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unauthorized","message":"Missing or invalid credential","fix":"Send the source's key as `Authorization: Bearer <key>` (server), in the webhook URL (webhook), or as `X-GM-Key` or a `?key=` query parameter (browser key only: `navigator.sendBeacon` cannot set headers). Check the key in Settings → Integrations → Website & booking-engine events.","docs":"/developers/events#error-unauthorized"}}}}},"403":{"description":"**source_disabled** — This source is disabled. Re-enable the source in Settings, or use another one. ([details](https://www.guestmaker.ai/developers/events#error-source-disabled))\n\n**feature_disabled** — Website events are not enabled for this account. Ask your GuestMaker contact to enable Website & booking engine events. ([details](https://www.guestmaker.ai/developers/events#error-feature-disabled))\n\n**origin_not_allowed** — This origin is not allowed for this key. Add the site's origin (for example https://www.example.com) to the source's allowed origins. ([details](https://www.guestmaker.ai/developers/events#error-origin-not-allowed))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"source_disabled","message":"This source is disabled","fix":"Re-enable the source in Settings, or use another one.","docs":"/developers/events#error-source-disabled"}}}}},"413":{"description":"**body_too_large** — The body is too large. Send fewer events per request, or trim `properties`. ([details](https://www.guestmaker.ai/developers/events#error-body-too-large))\n\n**batch_too_large** — Too many events in one request. Split the batch into requests of at most 50 events. ([details](https://www.guestmaker.ai/developers/events#error-batch-too-large))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"body_too_large","message":"The body is too large","fix":"Send fewer events per request, or trim `properties`.","docs":"/developers/events#error-body-too-large"}}}}},"422":{"description":"A single event that does not match the contract is refused with 422 and its `results[0].issues`; the same event in a batch is reported inside a 202.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}}},"429":{"description":"**rate_limited** — Too many requests. Retry after the number of seconds in the Retry-After header; batch events instead of sending one request each. ([details](https://www.guestmaker.ai/developers/events#error-rate-limited))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"rate_limited","message":"Too many requests","fix":"Retry after the number of seconds in the Retry-After header; batch events instead of sending one request each.","docs":"/developers/events#error-rate-limited"}}}}},"500":{"description":"**internal_error** — Something went wrong on our side. Retry with the same idempotency_key; the event will not be duplicated. ([details](https://www.guestmaker.ai/developers/events#error-internal-error))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"internal_error","message":"Something went wrong on our side","fix":"Retry with the same idempotency_key; the event will not be duplicated.","docs":"/developers/events#error-internal-error"}}}}}}},"options":{"tags":["Events"],"operationId":"preflightWebsiteEvents","summary":"CORS preflight for the browser SDK","description":"Carries no credential. The POST decides whether the page's origin is allowed.","security":[],"responses":{"204":{"description":"Preflight answered."}}}},"/api/v1/website-events/hooks/{token}":{"get":{"tags":["Webhook"],"operationId":"checkWebhookUrl","summary":"Check that a webhook URL is live","description":"Many webhook tools check a URL with a GET before saving it. Answers 200 when a POST would be accepted (and whether a signature is required), and otherwise the same 401/403 a POST would get, so a paused source is told apart from a mistyped token. It takes no event.","security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","pattern":"^gme_wh_[A-Za-z0-9]+$"},"description":"The webhook token, `gme_wh_…`."}],"responses":{"200":{"description":"The URL is live.","content":{"application/json":{"schema":{"type":"object","required":["ready","signature_required"],"properties":{"ready":{"type":"boolean","const":true},"accepts":{"type":"string"},"signature_required":{"type":"boolean"},"test":{"type":"string"},"docs":{"type":"string"}}}}}},"401":{"description":"**unauthorized** — Missing or invalid credential. Send the source's key as `Authorization: Bearer <key>` (server), in the webhook URL (webhook), or as `X-GM-Key` or a `?key=` query parameter (browser key only: `navigator.sendBeacon` cannot set headers). Check the key in Settings → Integrations → Website & booking-engine events. ([details](https://www.guestmaker.ai/developers/events#error-unauthorized))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unauthorized","message":"Missing or invalid credential","fix":"Send the source's key as `Authorization: Bearer <key>` (server), in the webhook URL (webhook), or as `X-GM-Key` or a `?key=` query parameter (browser key only: `navigator.sendBeacon` cannot set headers). Check the key in Settings → Integrations → Website & booking-engine events.","docs":"/developers/events#error-unauthorized"}}}}},"403":{"description":"**source_disabled** — This source is disabled. Re-enable the source in Settings, or use another one. ([details](https://www.guestmaker.ai/developers/events#error-source-disabled))\n\n**feature_disabled** — Website events are not enabled for this account. Ask your GuestMaker contact to enable Website & booking engine events. ([details](https://www.guestmaker.ai/developers/events#error-feature-disabled))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"source_disabled","message":"This source is disabled","fix":"Re-enable the source in Settings, or use another one.","docs":"/developers/events#error-source-disabled"}}}}}}},"post":{"tags":["Webhook"],"operationId":"receiveWebhook","summary":"Receive a booking engine's own payload","description":"The token in the path is the credential. The body is whatever the booking engine sends; the source's field mapping (Settings → Integrations → Website events) turns it into a website event, which is then validated exactly like any other. Add `?test=1` to mark every event as a test. If the source has a signing secret, every request must carry `X-GM-Signature`.","security":[],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","pattern":"^gme_wh_[A-Za-z0-9]+$"},"description":"The webhook token, `gme_wh_…`."},{"name":"test","in":"query","required":false,"schema":{"type":"string","enum":["1"]},"description":"Log and validate, but start no journey and write no contact."},{"name":"X-GM-Signature","in":"header","required":false,"schema":{"type":"string","example":"t=1767225600,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"},"description":"Required when the source has a signing secret: `t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\">`. More than one `v1` may be present while a secret is rotated. The timestamp must be within 5 minutes."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Any JSON object, up to 256 KB."},"examples":{"vendorPayload":{"value":{"type":"CartAbandoned","step":"PAYMENT","user":{"mail":"ana@example.com","name":"Ana"},"cart":{"id":8841,"total":"612,40","currency":"eur"},"stay":{"in":"20/11/2026","out":"23/11/2026"}}}}}}},"responses":{"202":{"description":"Received. Same body as the events endpoint, plus `mapping_warnings` per result: the mapped fields whose path was not found in this payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HookResult"}}}},"400":{"description":"**invalid_json** — The body is not valid JSON. Send a JSON body with Content-Type: application/json (or text/plain from navigator.sendBeacon). ([details](https://www.guestmaker.ai/developers/events#error-invalid-json))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"invalid_json","message":"The body is not valid JSON","fix":"Send a JSON body with Content-Type: application/json (or text/plain from navigator.sendBeacon).","docs":"/developers/events#error-invalid-json"}}}}},"401":{"description":"**unauthorized** — Missing or invalid credential. Send the source's key as `Authorization: Bearer <key>` (server), in the webhook URL (webhook), or as `X-GM-Key` or a `?key=` query parameter (browser key only: `navigator.sendBeacon` cannot set headers). Check the key in Settings → Integrations → Website & booking-engine events. ([details](https://www.guestmaker.ai/developers/events#error-unauthorized))\n\n**signature_missing** — The webhook signature is missing. Sign the request: X-GM-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\">. ([details](https://www.guestmaker.ai/developers/events#error-signature-missing))\n\n**signature_invalid** — The webhook signature does not match. Sign the exact raw body bytes with the source's signing secret; do not re-serialise the JSON before signing. ([details](https://www.guestmaker.ai/developers/events#error-signature-invalid))\n\n**signature_expired** — The webhook signature is too old. Sign with the current time and check the sender's clock. ([details](https://www.guestmaker.ai/developers/events#error-signature-expired))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unauthorized","message":"Missing or invalid credential","fix":"Send the source's key as `Authorization: Bearer <key>` (server), in the webhook URL (webhook), or as `X-GM-Key` or a `?key=` query parameter (browser key only: `navigator.sendBeacon` cannot set headers). Check the key in Settings → Integrations → Website & booking-engine events.","docs":"/developers/events#error-unauthorized"}}}}},"403":{"description":"**source_disabled** — This source is disabled. Re-enable the source in Settings, or use another one. ([details](https://www.guestmaker.ai/developers/events#error-source-disabled))\n\n**feature_disabled** — Website events are not enabled for this account. Ask your GuestMaker contact to enable Website & booking engine events. ([details](https://www.guestmaker.ai/developers/events#error-feature-disabled))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"source_disabled","message":"This source is disabled","fix":"Re-enable the source in Settings, or use another one.","docs":"/developers/events#error-source-disabled"}}}}},"413":{"description":"**body_too_large** — The body is too large. Send fewer events per request, or trim `properties`. ([details](https://www.guestmaker.ai/developers/events#error-body-too-large))\n\n**batch_too_large** — Too many events in one request. Split the batch into requests of at most 50 events. ([details](https://www.guestmaker.ai/developers/events#error-batch-too-large))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"body_too_large","message":"The body is too large","fix":"Send fewer events per request, or trim `properties`.","docs":"/developers/events#error-body-too-large"}}}}},"422":{"description":"One mapped event that does not match the contract, with its `results[0].issues` and `mapping_warnings`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HookResult"}}}},"429":{"description":"**rate_limited** — Too many requests. Retry after the number of seconds in the Retry-After header; batch events instead of sending one request each. ([details](https://www.guestmaker.ai/developers/events#error-rate-limited))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"rate_limited","message":"Too many requests","fix":"Retry after the number of seconds in the Retry-After header; batch events instead of sending one request each.","docs":"/developers/events#error-rate-limited"}}}}},"500":{"description":"**internal_error** — Something went wrong on our side. Retry with the same idempotency_key; the event will not be duplicated. ([details](https://www.guestmaker.ai/developers/events#error-internal-error))","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"internal_error","message":"Something went wrong on our side","fix":"Retry with the same idempotency_key; the event will not be duplicated.","docs":"/developers/events#error-internal-error"}}}}}}}}},"components":{"securitySchemes":{"ServerKey":{"type":"http","scheme":"bearer","description":"A secret source key, `gme_sk_…`. Keep it on your server."},"BrowserKeyHeader":{"type":"apiKey","in":"header","name":"X-GM-Key","description":"A public browser key, `gme_pk_…`. Works only from the source's allowed origins."},"BrowserKeyQuery":{"type":"apiKey","in":"query","name":"key","description":"The same public browser key, for `navigator.sendBeacon`, which cannot set headers. Never use a secret key here: URLs are logged."}},"schemas":{"Event":{"type":"object","properties":{"event":{"type":"string","maxLength":64,"pattern":"^[a-z][a-z0-9_]{0,31}(\\.[a-z][a-z0-9_]{0,31}){0,3}$"},"occurred_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"idempotency_key":{"type":"string","minLength":1,"maxLength":200},"contact":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","pattern":"^\\+?[0-9][0-9 ().-]{5,30}$"},"first_name":{"type":"string","minLength":1,"maxLength":100},"last_name":{"type":"string","minLength":1,"maxLength":100},"language":{"type":"string","pattern":"^[a-zA-Z]{2}([-_][a-zA-Z]{2})?$"}},"additionalProperties":false},"consent":{"type":"object","properties":{"email_marketing":{"type":"boolean"},"text":{"type":"string","maxLength":2000},"captured_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"language":{"type":"string","maxLength":10},"form_id":{"type":"string","maxLength":100}},"required":["email_marketing"],"additionalProperties":false},"context":{"type":"object","properties":{"hotel_id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"hotel_code":{"type":"string","minLength":1,"maxLength":50},"hotel_name":{"type":"string","minLength":1,"maxLength":200},"stage":{"type":"string","enum":["dates","room","extras","details","payment"]},"check_in":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"check_out":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"adults":{"type":"integer","minimum":0,"maximum":30},"children":{"type":"integer","minimum":0,"maximum":30},"rooms":{"type":"integer","minimum":1,"maximum":20},"room_name":{"type":"string","minLength":1,"maxLength":200},"rate_name":{"type":"string","minLength":1,"maxLength":200},"value":{"type":"number","minimum":0,"maximum":10000000},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"cart_id":{"type":"string","minLength":1,"maxLength":200},"session_id":{"type":"string","minLength":1,"maxLength":200},"resume_url":{"type":"string","maxLength":2048},"page_url":{"type":"string","maxLength":2048},"referrer":{"type":"string","maxLength":2048}},"additionalProperties":false},"properties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":500},{"type":"number"},{"type":"boolean"}]}},"test":{"type":"boolean"}},"required":["event"],"additionalProperties":false,"title":"Event","description":"One event. Unknown keys are refused."},"Batch":{"type":"object","title":"Batch","additionalProperties":false,"required":["events"],"properties":{"events":{"type":"array","minItems":1,"maxItems":50,"items":{"$ref":"#/components/schemas/Event"}}},"description":"Up to 50 events. Each is judged on its own."},"Contact":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","pattern":"^\\+?[0-9][0-9 ().-]{5,30}$"},"first_name":{"type":"string","minLength":1,"maxLength":100},"last_name":{"type":"string","minLength":1,"maxLength":100},"language":{"type":"string","pattern":"^[a-zA-Z]{2}([-_][a-zA-Z]{2})?$"}},"additionalProperties":false,"title":"Contact"},"Consent":{"type":"object","properties":{"email_marketing":{"type":"boolean"},"text":{"type":"string","maxLength":2000},"captured_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"language":{"type":"string","maxLength":10},"form_id":{"type":"string","maxLength":100}},"required":["email_marketing"],"additionalProperties":false,"title":"Consent"},"Context":{"type":"object","properties":{"hotel_id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"hotel_code":{"type":"string","minLength":1,"maxLength":50},"hotel_name":{"type":"string","minLength":1,"maxLength":200},"stage":{"type":"string","enum":["dates","room","extras","details","payment"]},"check_in":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"check_out":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"adults":{"type":"integer","minimum":0,"maximum":30},"children":{"type":"integer","minimum":0,"maximum":30},"rooms":{"type":"integer","minimum":1,"maximum":20},"room_name":{"type":"string","minLength":1,"maxLength":200},"rate_name":{"type":"string","minLength":1,"maxLength":200},"value":{"type":"number","minimum":0,"maximum":10000000},"currency":{"type":"string","pattern":"^[A-Z]{3}$"},"cart_id":{"type":"string","minLength":1,"maxLength":200},"session_id":{"type":"string","minLength":1,"maxLength":200},"resume_url":{"type":"string","maxLength":2048},"page_url":{"type":"string","maxLength":2048},"referrer":{"type":"string","maxLength":2048}},"additionalProperties":false,"title":"Context"},"Properties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string","maxLength":500},{"type":"number"},{"type":"boolean"}]},"title":"Properties"},"Result":{"type":"object","title":"Result","required":["received","accepted","duplicate","rejected","results"],"properties":{"received":{"type":"integer"},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"rejected":{"type":"integer"},"results":{"type":"array","items":{"type":"object","required":["index","status","code","message","contact","warnings"],"properties":{"index":{"type":"integer"},"status":{"type":"string","enum":["accepted","duplicate","rejected"]},"code":{"type":"string","enum":["invalid_json","invalid_body","body_too_large","batch_too_large","batch_empty","unauthorized","source_disabled","feature_disabled","origin_not_allowed","signature_missing","signature_invalid","signature_expired","rate_limited","internal_error","invalid_event","event_not_allowed","hotel_not_allowed","hotel_unknown","occurred_at_too_old","occurred_at_in_future","consent_evidence_missing","consent_ignored_opted_out","consent_evidence_stale","consent_source_ignores","no_contact","accepted","duplicate","test_event","refused_not_person"]},"message":{"type":"string"},"event_id":{"type":["string","null"]},"contact":{"type":"string","enum":["matched","created","none"]},"warnings":{"type":"array","items":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_json","invalid_body","body_too_large","batch_too_large","batch_empty","unauthorized","source_disabled","feature_disabled","origin_not_allowed","signature_missing","signature_invalid","signature_expired","rate_limited","internal_error","invalid_event","event_not_allowed","hotel_not_allowed","hotel_unknown","occurred_at_too_old","occurred_at_in_future","consent_evidence_missing","consent_ignored_opted_out","consent_evidence_stale","consent_source_ignores","no_contact","accepted","duplicate","test_event","refused_not_person"]},"message":{"type":"string"}}}},"issues":{"type":"array","items":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}},"HookResult":{"title":"HookResult","allOf":[{"$ref":"#/components/schemas/Result"},{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"mapping_warnings":{"type":"array","items":{"type":"object","required":["target","reason"],"properties":{"target":{"type":"string","description":"The contract field the mapping row was for, e.g. contact.email."},"reason":{"type":"string","enum":["path_not_found","transform_failed","unsupported_value","unsafe_path"]},"detail":{"type":"string"}}}}}}}}}]},"Error":{"type":"object","title":"Error","required":["error"],"properties":{"error":{"type":"object","required":["code","message","fix","docs"],"properties":{"code":{"type":"string","enum":["invalid_json","invalid_body","body_too_large","batch_too_large","batch_empty","unauthorized","source_disabled","feature_disabled","origin_not_allowed","signature_missing","signature_invalid","signature_expired","rate_limited","internal_error"]},"message":{"type":"string"},"detail":{"type":"string"},"fix":{"type":"string"},"docs":{"type":"string","description":"A link to this code's entry in the error reference."}}}}}}},"x-standard-events":[{"name":"cart.abandoned","label":"Cart abandoned","description":"A visitor left mid-booking without completing. `context.stage` says where: dates, room, extras, details or payment.","exit":false},{"name":"lead.captured","label":"Lead captured","description":"A visitor left their email or phone (a form, a price alert, a callback request).","exit":false},{"name":"search.performed","label":"Search performed","description":"A visitor searched availability for dates.","exit":false},{"name":"room.selected","label":"Room selected","description":"A visitor picked a room or rate.","exit":false},{"name":"checkout.started","label":"Checkout started","description":"A visitor reached the guest-details step. Pair it with a Wait and an exit on `checkout.completed` to build an abandoned-cart flow without the vendor timing anything.","exit":false},{"name":"payment.failed","label":"Payment failed","description":"A payment attempt failed and the booking was not completed.","exit":false},{"name":"checkout.completed","label":"Checkout completed","description":"The visitor completed the booking. Stops any journey waiting on this visitor's cart.","exit":true}]}