Skip to main content

Webhooks

Inbound HMAC-verified receivers.

POST /v1/india/webhooks/glomopay

Ledger-side receiver for GlomoPay order/payment lifecycle events. Schedules a per-customer sync on money-moving events.

Headers

  • X-Glomopay-Signature: sha256=<hex> — constant-time HMAC-SHA256 over the raw request body using GLOMOPAY_WEBHOOK_SECRET.

Request body

{
"entity_type": "orders" | "payment" | "payment_link",
"event_type": "paid" | "funds_available" | "success" | "failed" | "action_required" | ...,
"data": {
"id": "order_...",
"customer_id": "cust_...",
"payin_id": "...",
"status": "...",
"amount": 100000,
...
}
}

Response — 200

{
"received_at": "2026-07-01T...",
"entity_type": "orders",
"event_type": "paid",
"glomo_customer_id": "cust_x",
"order_id": "order_y",
"triggered_sync": true,
"reason": "sync scheduled in background for cust_x"
}

Status codes

  • 200 — verified, classified, ACK returned.
  • 400 — malformed JSON body.
  • 401 — bad or missing signature.
  • 503GLOMOPAY_WEBHOOK_SECRET not configured (refuses to accept unsigned payloads).

Sync-trigger predicate

def _triggers_sync(entity_type, event_type) -> bool:
if entity_type == "orders":
return event_type == "paid"
if entity_type in ("payment", "payments", "payment_link"):
return event_type in ("funds_available", "success")
return False

Only events that MOVE MONEY trigger a re-sync. Everything else is logged and gets triggered_sync=false.

The background dispatch

When the trigger fires:

  • asyncio.create_task(_run_background_sync(cust_id)) — held in a strong-ref set so the event loop doesn't GC it.
  • Runs on its OWN session under the cluster india_sync_lock.
  • The webhook ACKs immediately (fast, no sender timeout risk).

Verification checklist

  • 503 when the secret isn't configured
  • 401 on a bad signature
  • 200 on a good HMAC + triggered_sync: true when the event moves money
  • 200 on a good HMAC + triggered_sync: false otherwise

Cross-team

In prod, api-global is the public-facing receiver; it verifies the sender's signature and relays to this ledger endpoint. Both sides need a matched GLOMOPAY_WEBHOOK_SECRET.