Overview

Ananas GDS can push event notifications to any HTTPS endpoint you register. When a matching event occurs — a stop sale changes, an invoice is sent, a property updates — Ananas GDS immediately dispatches a signed POST request to all subscribed endpoints. This eliminates the need for polling and allows your systems to react in real time.

Registering a Webhook

1
Go to Developer Tools → Webhooks in the dashboard.
2
Click Add Endpoint . Enter a name, the HTTPS URL, and select the events to subscribe to.
3
Ananas GDS generates a signing secret. Copy it — it is shown once.
4
Send a test ping to verify your endpoint is reachable and your signature verification code is correct.

HTTPS required

Webhook endpoints must use HTTPS. HTTP endpoints are rejected at registration time. Your server must present a valid TLS certificate.

Payload Structure

Every webhook delivery is a JSON POST body with a consistent envelope:

Webhook Payload Envelope
{
  "event": "stopsale.created",
  "timestamp": "2026-05-11T14:32:00Z",
  "delivery_id": "del_a1b2c3d4e5f6",
  "data": {
    // Event-specific data object
  }
}

Event Data Objects

Event Data Object
property.updated Full property object with changed fields highlighted.
stopsale.created Stop sale event: property_id, date, status, allotment, room_type, source.
stopsale.updated Same as created, with previous values included.
stopsale.cancelled Stop sale event ID and property_id.
invoice.sent Invoice summary: id, invoice_number, from, to, amount, currency, due_date.
invoice.paid Invoice summary plus paid_at timestamp and payment reference.
invoice.disputed Invoice summary plus dispute note text.
invoice.cancelled Invoice ID, invoice_number, cancellation timestamp.
availability.updated Property ID, affected date range, allotment values.

Signature Verification

Every delivery includes an X-Ananas-Signature header. This is an HMAC-SHA256 digest of the raw request body, keyed with the endpoint's signing secret. Always verify this signature before processing the payload.

Signature Header
X-Ananas-Signature: sha256=a1b2c3d4e5f6...
Python Verification Example
import hmac
import hashlib

def verify_signature(payload_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    received = signature_header.replace("sha256=", "")
    return hmac.compare_digest(expected, received)

Use constant-time comparison

Always use hmac.compare_digest() (or your language's equivalent) rather than == for comparing signatures. This prevents timing-based attacks.

Retry Policy

A delivery is considered successful when your endpoint responds with any 2xx HTTP status code within 30 seconds. If delivery fails (non-2xx, timeout, or connection error), Ananas GDS retries with exponential backoff:

Attempt Delay
1st retry 5 minutes
2nd retry 30 minutes
3rd retry 2 hours
4th retry 8 hours
5th retry (final) 24 hours

After 5 failed attempts the delivery is marked failed and no further retries are attempted. You can manually retry from the delivery log in the dashboard.

Delivery Log

Every delivery attempt is recorded in WebhookDelivery with the response code, response body, attempt count, and next retry timestamp. Access the log for any endpoint from Developer Tools → Webhooks → Deliveries , or via the API:

List Deliveries
GET /api/dev/integrations/webhooks/{id}/deliveries/
Authorization: Token <token>
Manually Retry a Delivery
POST /api/dev/integrations/webhooks/deliveries/{delivery_id}/retry/
Authorization: Token <token>

Test Ping

Send a synthetic test event to verify your endpoint without waiting for a real event to occur:

Test Ping
POST /api/dev/integrations/webhooks/{id}/test/
Authorization: Token <token>

The test payload uses the event type test.ping with a minimal data object. Inspect the delivery log to confirm receipt.

Idempotency

Each delivery has a unique delivery_id in the envelope. If your endpoint receives the same delivery_id twice (e.g. after a retry following a timeout where your server actually processed the request), treat the second as a duplicate and return 2xx without re-processing. Store processed delivery IDs for at least 24 hours.