Error envelope
Every non-2xx response from the Guest Talk platform carries the same JSON envelope. The envelope has a stable code, a human-readable message, a request_id that ties the response to the underlying platform log line, and — where relevant — a details array with per-field information. The code is the value your code should branch on; the message is the value you should surface to a human debugging your integration.
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"code": "TG-2004",
"message": "arrival must be strictly before departure",
"request_id": "req_01HYQ8XN2K9AB4CD",
"details": [
{ "field": "arrival", "issue": "2026-08-06 is not before departure 2026-08-06" },
{ "field": "departure", "issue": "must be at least one day after arrival" }
]
} Codes are stable across versions within a major API version. Talkguest never repurposes a code for a different meaning; if a new failure mode emerges we mint a new code. This means a client that parses on code instead of message is safe against copywriting changes on our side.
HTTP status conventions
| Status | Meaning |
|---|---|
| 200 | Read succeeded; body carries the resource |
| 201 | Resource created; body carries the new resource with its id |
| 204 | Write accepted; no body |
| 400 | Malformed request — JSON parse error, missing content type, unknown field with strict parsing |
| 401 | Missing or invalid Bearer token |
| 403 | Token is valid but lacks permission for the resource or the action |
| 404 | Resource does not exist, or exists in a tenant the token cannot see |
| 409 | Conflict — overbooking, rate collision, concurrent update losing the compare-and-swap |
| 422 | Validation failure — the payload is well-formed but semantically invalid |
| 429 | Rate limit tripped — see the rate limits page |
| 500 | Unhandled server error; safe to retry with backoff |
| 503 | Platform degraded or in maintenance; obey Retry-After |
Authentication errors (TG-1xxx)
| Code | HTTP | Meaning | Remediation |
|---|---|---|---|
| TG-1001 | 401 | Bearer token missing or malformed | Send Authorization: Bearer <token> with a token issued from Settings → Integrations → API tokens. |
| TG-1002 | 401 | Token revoked or rotated out | Issue a fresh token; a revoked token is never re-activated. |
| TG-1003 | 403 | Token lacks the permission for the resource or the action | Regenerate the token with the required scope, or ask the tenant admin to grant the scope on the existing token. |
Auth errors are the first ones every new integration hits. If you are seeing a TG-1001, check the header name spelling first — the platform is strict about the exact string Authorization. If you are seeing a TG-1003, the token is valid but has been scoped read-only or scoped away from the resource you are touching; the fix is on the token, not on the request.
Validation errors (TG-2xxx)
| Code | HTTP | Meaning | Remediation |
|---|---|---|---|
| TG-2001 | 400 | Request body is not valid JSON | Fix the JSON syntax; the details array carries the parser position. |
| TG-2002 | 400 | Content-Type is not application/json | Set the header correctly. |
| TG-2003 | 422 | Required field missing | Consult the API reference for the resource shape. |
| TG-2004 | 422 | Arrival is not strictly before departure | Adjust the stay window; same-day arrivals require a minimum one-night stay. |
| TG-2005 | 422 | Rate plan does not belong to the room type | Pick a rate plan attached to the requested room type or attach the plan first. |
| TG-2006 | 422 | Guest document data fails Portuguese AL/SEF format check | Ensure passport / cartão de cidadão / driver's licence numbers match the expected format for the nationality declared. |
| TG-2007 | 422 | Currency mismatch between quote and folio | The folio is denominated in one currency; the quote must match. Convert client-side or open a folio in the target currency. |
| TG-2008 | 422 | Idempotency key reused with a different payload | Use a fresh key or send the exact same payload as the original request. |
| TG-2009 | 422 | Enum value not in the accepted set | The details array lists the accepted set; pick one. |
| TG-2010 | 422 | Reference target does not exist in this tenant | The guest_id, rate_plan_id or room_type_id resolves to nothing; check for typos or cross-tenant confusion. |
Business logic errors (TG-3xxx)
| Code | HTTP | Meaning | Remediation |
|---|---|---|---|
| TG-3001 | 409 | Overbooking — no inventory in the requested room type for one or more nights of the window | Query GET /availability before booking; either shift the window, pick a different room type, or explicitly opt-in to overselling on the tenant settings. |
| TG-3002 | 409 | Rate conflict — the rate quote sent does not match the current rate table | Re-quote against the current table and resubmit; this usually means a rate update landed between quote and book. |
| TG-3003 | 409 | Cancellation attempted after the free-cancellation window closed | Charge the cancellation fee explicitly on the folio and cancel with force=true. |
| TG-3004 | 409 | Check-in attempted on a reservation whose arrival date is not today | Check-in early with an operator override or wait for the correct date. |
| TG-3005 | 409 | Charge posted to a closed folio | Reopen the folio, split the charge into a new folio, or use a post-departure adjustment endpoint. |
Business-logic errors are the hardest to design around because they represent a genuine conflict between the request and the state of the property. The pattern that works in production is to treat every 3xxx as an operator-visible signal: surface the code and the message to the operator UI, let them make the decision, then retry with the flag or the adjusted payload they chose.
Integration errors (TG-4xxx)
| Code | HTTP | Meaning | Remediation |
|---|---|---|---|
| TG-4001 | 502 | OTA channel unreachable | Transient; the internal retry loop will pick it up. If it persists, the OTA is having an incident. |
| TG-4002 | 502 | OTA rejected the payload as invalid | Check the channel mapping under Settings → Channels; a rate code or a room type has drifted between our side and the OTA. |
| TG-4003 | 409 | OTA already knows about a reservation with the same external id | The reservation exists on both sides; reconcile by pulling the OTA record instead of re-creating. |
| TG-4004 | 422 | Rate plan not mapped to the requested channel | Add a channel mapping to the rate plan, or send to a channel the plan is mapped to. |
| TG-4005 | 502 | Payment provider timeout | Retry the charge with the same idempotency key; the platform will resolve the outcome once the provider responds. |
| TG-4006 | 402 | Payment provider rejected the charge | The provider's decline reason is in details.provider_reason; surface it to the guest. |
| TG-4007 | 502 | SEF/AL submission endpoint unreachable | Transient; the platform queues and retries. The reservation itself is not blocked. |
| TG-4008 | 422 | Lock system rejected key issuance | Room number is not present in the lock system's mapping; add the mapping under Settings → Integrations → Locks. |
Rate limit errors (TG-5xxx)
| Code | HTTP | Meaning | Remediation |
|---|---|---|---|
| TG-5001 | 429 | Per-endpoint sub-cap tripped | Obey Retry-After; consider pacing on X-RateLimit-Remaining. |
| TG-5002 | 429 | Per-tenant global 600/min tripped | Obey Retry-After; if this happens routinely, arrange an Enterprise ceiling raise — see the rate limits page. |
Server errors (TG-9xxx)
| Code | HTTP | Meaning | Remediation |
|---|---|---|---|
| TG-9001 | 500 | Unhandled server error | Retry with exponential backoff; if it persists, include the request_id in a support ticket. |
| TG-9002 | 503 | Platform in scheduled maintenance | Obey Retry-After; maintenance windows are announced on the status page 72 hours in advance. |
| TG-9003 | 503 | Regional failover in progress | Transient — typically clears within two minutes; the platform is promoting the secondary EU region. |
Server errors are the ones where the platform itself is at fault. The correct client behaviour on TG-9001 is to retry the same request with backoff — the underlying operation may have succeeded, may have failed, or may not have reached the persistence layer. Idempotency keys on writes make this safe: the retry with the same key either returns the original result or completes the operation for the first time.
Getting help
Every error envelope carries a request_id. When a specific request confuses you, the fastest path to a resolution is a support ticket that quotes the request_id, the endpoint, the payload (with any secrets redacted) and the error code. With the request_id our on-call engineer can go straight to the underlying platform log line without needing to reproduce the call. Without it, we spend the first hour of the ticket asking you to reproduce.
Next steps
Cross-check the resource shapes on the API reference so validation errors go away before they happen. Read the rate limits page so you avoid TG-5001 and TG-5002 in the first place. Read the webhooks page if you would rather subscribe to events than poll and parse errors on the read path. For anything else, reach the integrations team through the contact page or request access.