Events
Webhook Events Guide
Audience: partners integrating with our push notification service.
Scope: all webhook events across payment requests, payments, onboarding, and more
Version: 1.0
1. Overview
Hubpay emits webhook events to inform your system about real-time changes to resources such as payment requests, payments and onboarding.
You can subscribe to events by registering a webhook endpoint. Once subscribed, we’ll send signed HTTPS POST requests
to your server with the relevant event data
so your system can react in real‑time (update UI, trigger fulfilment, etc.).
2. Event catalogue
The events you can subscribe to depend on your account type. Account owners receive collection events for payment requests, payments and payouts. Partner accounts receive onboarding events for accounts and documents they manage.
Collection events (account owners)
| Event | When it triggers |
|---|---|
v1.collection.payment_request.created | The payment request is first generated |
v1.collection.payment_request.part_paid | A partial payment is captured but the payable balance > 0 |
v1.collection.payment_request.paid | The request balance reaches 0 |
v1.collection.payment_request.cancelled | The request is unpaid and is cancelled |
v1.collection.payment_request.payment.created | Reserved for future use. Intended to represent an initial state |
v1.collection.payment_request.payment.pending | Authorised (for card payments), pending confirmation (for crypto), or reported as sent by the customer |
v1.collection.payment_request.payment.received | Funds received on blockchain, card network, or bank |
v1.collection.payment_request.payment.completed | Final payout made; funds credited to wallet |
v1.collection.payment_request.payment.failed | Payment failed due to error or rejection |
v1.collection.payment_request.payment.reversed | Reserved for future use. Intended to represent a post-completion reversal |
v1.collection.payment_request.payment.payout.pending_approval | Payout is awaiting approval |
v1.collection.payment_request.payment.payout.initiated | Payout has been initiated |
v1.collection.payment_request.payment.payout.paid | Payout has been paid |
v1.collection.payment_request.payment.payout.failed | Payout has failed |
For details: Payment request | Payments | Payouts
Onboarding events (partners only)
| Event | When it triggers |
|---|---|
v1.onboarding.account.created | On successful creation of new account |
v1.onboarding.account.signed_up | On acceptance of account sign-up details |
v1.onboarding.account.submitted | On submission of account sign-up details (incl. documentation) for review and decision |
v1.onboarding.account.approved | On approval of account sign-up details (incl. documentation) |
v1.onboarding.account.rejected | On rejection of account sign-up details or documentation |
v1.onboarding.account.onboarded | The account is fully onboarded and able to transact |
v1.onboarding.document.approved | Document has been reviewed and accepted |
v1.onboarding.document.declined | Document has been reviewed and not accepted |
v1.onboarding.document.validation_warnings | Automated validation flagged concerns |
For details: Account onboarding | Document
3. Ordering and delivery guarantees
Hubpay dispatches events in logical lifecycle order — for example, payment.pending is always sent before payment.received, which is always sent before payment.completed. Events are queued in order and delivered sequentially.
However, delivery order to your endpoint is not strictly guaranteed. Network conditions, retry timing, and concurrent delivery can cause events to arrive out of sequence. Your integration should be designed to handle this.
Best practices
- Use
createdAtfor ordering. Every event includes acreatedAttimestamp set at the time the event was produced. Use this to determine the true sequence, not the order events arrive at your endpoint. - Always fetch the latest state. Events are thin notifications — they tell you something changed, not what the current state is. When you receive an event, call the relevant API (e.g. Get Payment Request) to retrieve the authoritative, up-to-date resource state before taking action.
- Don't hard-code lifecycle assumptions. Your handler may receive
payment.completedbeforepayment.receivedhas arrived. If you query the API on receipt ofpayment.completed, you'll see the resource is already in its final state — the earlier event becomes informational. - Design for idempotency. The same event may be delivered more than once (see Retry strategy). Use the event
idto deduplicate and ensure processing an event twice has no adverse effect.
Webhooks tell you "something happened" — they are a prompt to check the latest state via the API. The API is always the source of truth.
4. Event format
Hubpay uses thin events — minimal, lightweight webhook messages designed for stability, safety, and forward compatibility.
What are thin events?
Thin events are compact and granularly scoped. Instead of sending large payloads each event includes:
- Stable identifiers (e.g. paymentRequestId) and resource type
- A minimal data object (often optional)
- No embedded resource bodies
Each webhook is an HTTPS POST with a small, JSON payload:
{
"id": "<event-uuid>",
"event": "v1.collection.payment_request.created",
"createdAt": "2025-06-25T13:04:11Z",
"accountId": "<your-account-uuid>",
"relatedObject": {
"id": "<resource-uuid>",
"type": "collection.payment_request",
"url": "v1/collections/payment-requests/<id>"
},
"data": {
// Optional — varies by event
}
}
Every message is signed for verification (see Verifying webhook signatures) and automatically retried on failure (see Retry strategy).
5. Receiving events
To start receiving and handling webhooks:
-
Register your webhook URL
CallPOST /v1/webhookswith your callback URL and secret key. -
Listen for signed webhook events
We will send HTTPSPOSTrequests to your registered endpoint for every relevant event. See our detailed callbacks API for the expected payload/request. -
Verify the signature
See Verifying webhook signatures -
Process the event
- Inspect the
eventfield (e.g.v1.collection.payment_request.created) - Take appropriate action in your system (e.g. update UI, trigger fulfilment, notify user)
- See the event catalogue for supported values
- Inspect the
-
Return
HTTP 2xx
A2xxresponse acknowledges successful receipt. Any other response triggers automatic retries with exponential backoff (see Retry strategy).