Webhooks

Messaging API - Webhooks

Webhook contract

Agoda sends one new-message notification to the configured HTTPS destination when an eligible message is available for the recipient Channel Manager.

Delivery is at-least-once. The same metadata.uuid and body are reused on a retry. Receivers MUST perform durable deduplication on metadata.uuid. Gaps are possible: sustained delivery failure may leave a notification undelivered, and there is no public webhook history, replay endpoint, or dead-letter access.

Operational delivery settings are confirmed at certification. They are not part of this contract. Receivers must tolerate redelivery at any operational pacing Agoda applies.

Agoda configures the destination during certification. There is no public API for webhook registration or destination changes.

Callback authentication. Callbacks use OAuth 2.0 client credentials. Agoda obtains a token from the Channel Manager token endpoint and sends Authorization: Bearer on the callback POST, including retries.

Transport

ItemRequirement
MethodHTTPS POST.
HeaderContent-Type: application/json. Authorization: Bearer from OAuth 2.0 client credentials.
RedirectsNot followed.
Receiver URLMust use a publicly reachable hostname with a valid TLS certificate. Loopback, link-local, metadata-service, private-network, and non-public destinations are rejected.
Callback credentialsOAuth 2.0 client credentials. Agoda obtains a token from the Channel Manager token endpoint and sends Authorization: Bearer on the callback POST, including retries.

HTTPS and TLS protect transport. Restrict your receiver to the required public HTTPS shape, validate the payload, and maintain durable deduplication.

The webhook body has no data wrapper. It is {metadata, payload} only. It is not the four-field REST envelope.

Treat each notification as a hint. Confirm against GET /properties/{property_id}/conversations/{conversation_id} before acting or showing content to hotel staff. Notification order is not guaranteed, including within one recipient and across retries. message_id from a read is the ordering authority.

Payload schema and example

{
  "metadata": {
    "uuid": "2ed6657d-e927-568b-95e1-2665a8aea6a2",
    "type": "MESSAGING_API_NEW_MESSAGE",
    "payload_version": "1.0"
  },
  "payload": {
    "message_id": "918273644",
    "message_type": "free_text",
    "timestamp": "2026-07-23T07:15:30.123Z",
    "content": "Can we check in early?",
    "attributes": {},
    "attachment_ids": [],
    "sender": {
      "participant_type": "guest"
    },
    "conversation": {
      "property_id": "1042",
      "conversation_id": "418092345",
      "conversation_reference": "9384756102",
      "conversation_type": "reservation"
    }
  }
}

The webhook payload has no status, no read_by, and no reply_to. Read state is obtained from a confirming GET via the participant unread counter. Metadata uses snake_case payload_version. payload.attachment_ids is always present ([] when none). The body has no file bytes.

FieldTypeRequiredMeaning
metadata.uuidstring (UUID)YesStable recipient-specific UUID. Deduplicate durably on this exact value. Unchanged when Agoda retries the same notification.
metadata.typestringYesMESSAGING_API_NEW_MESSAGE.
metadata.payload_versionstringYes1.0. snake_case, not payloadVersion.
payload.message_idstringYesMessage ID (positive signed-64 decimal string).
payload.message_typestringYesDocumented example free_text. Ordinary text messages appear as free_text. Other stored types are returned as-is; ignore unknown values.
payload.timestampstring (date-time)YesRFC 3339 UTC timestamp.
payload.contentstringYesFull partner-safe message text.
payload.attributesobjectYesObject; empty unless a documented safe attribute applies.
payload.attachment_idsarray of stringYesAttachment IDs on this message. Always present. Empty array when none. Ids only; use download for file bytes.
payload.sender.participant_typestringYesproperty, guest, or agoda.
payload.conversation.property_idstringYesAuthorized Agoda property ID for the recipient Channel Manager.
payload.conversation.conversation_idstringYesConversation ID (positive signed-64 decimal string).
payload.conversation.conversation_referencestringYesAgoda booking ID.
payload.conversation.conversation_typestringYesreservation.

metadata.payload_version versions the webhook body independently of the REST path. The current value is "1.0". Additive payload fields are compatible. Receivers MUST ignore unknown payload fields.

Receiver requirements

  • MUST parse and validate the exact versioned body.
  • MUST deduplicate durably by metadata.uuid.
  • MUST persist accepted work before returning a 2xx response.
  • SHOULD return quickly and process downstream work asynchronously.
  • MUST treat any 2xx response as transport acknowledgement only, not as a human-read acknowledgement.
  • MUST confirm against a conversation-detail GET before acting on content.

Retry and recovery

Agoda retries the same metadata.uuid and body after a network failure or any non-2xx response. A timeout or crash after your receiver returns 2xx can still result in redelivery, so durable deduplication on metadata.uuid is required.

Sustained delivery failure may leave a notification gap. There is no public webhook history, replay endpoint, or dead-letter access. After downtime, catch up with the REST conversation list and conversation-detail GET. Deduplicate deliveries with metadata.uuid. When reconciling messages, use message_id as ordering and identity.

Retain your own delivery and dedupe state.

Ordering is not guaranteed, including within one recipient and across retries. message_id from a read is the ordering authority. A failed callback for one recipient does not block others. Agoda confirms delivery settings during certification.


Did this page help you?