Skip to main content

Webhook event catalogue

Hubpay webhook events cover payment requests, payments, onboarding, RFI cases and app connections. Subscribe only to the event families required by your integration.

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.).


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)

EventWhen it triggers
v1.collection.payment_request.createdThe payment request is first generated
v1.collection.payment_request.part_paidA partial payment is captured but the payable balance > 0
v1.collection.payment_request.paidThe request balance reaches 0
v1.collection.payment_request.cancelledThe request is cancelled by the user or after a payment is rejected
v1.collection.payment_request.payment.createdReserved for future use. Intended to represent an initial state
v1.collection.payment_request.payment.pendingPayment processing started; for crypto this is queued immediately before received on confirmation
v1.collection.payment_request.payment.receivedCrypto confirmed on-chain, card captured, or bank funds received; crypto compliance may still be in progress
v1.collection.payment_request.payment.completedPayment completed and funds credited to the Hubpay wallet; applicable crypto compliance gates cleared
v1.collection.payment_request.payment.failedPayment failed due to error or rejection
v1.collection.payment_request.payment.reversedReserved for future use. Intended to represent a post-completion reversal
v1.collection.payment_request.payment.payout.pending_approvalPayout is awaiting approval
v1.collection.payment_request.payment.payout.initiatedPayout has been initiated
v1.collection.payment_request.payment.payout.paidPayout has been paid
v1.collection.payment_request.payment.payout.failedPayout has failed

For event timing and the recommended crypto confirmation signal, see Payment lifecycle and webhooks. Payload details: Payment request | Payments | Payouts

Onboarding events (partners only)

EventWhen it triggers
v1.onboarding.account.createdOn successful creation of new account
v1.onboarding.account.signed_upOn acceptance of account sign-up details
v1.onboarding.account.submittedOn submission of account sign-up details (incl. documentation) for review and decision
v1.onboarding.account.approvedOn approval of account sign-up details (incl. documentation)
v1.onboarding.account.rejectedOn rejection of account sign-up details or documentation
v1.onboarding.account.onboardedThe account is fully onboarded and able to transact
v1.onboarding.document.approvedDocument has been reviewed and accepted 1
v1.onboarding.document.declinedDocument has been reviewed and not accepted 1
v1.onboarding.document.validation_warningsAutomated validation flagged concerns 1

For details: Account onboarding | Document

RFI events (partners only)

Lifecycle events on RFI cases and per-document decisions on files attached to those cases. The two families are independent: subscribe to whichever you need.

EventWhen it triggers
v1.rfi.case.openedA new RFI case has been raised against the customer
v1.rfi.case.closedAll items resolved; ops closed the case
v1.rfi.case.cancelledOps cancelled the case (no further customer action required)
v1.rfi.document.approvedA file attached to an RFI document request has been approved 1
v1.rfi.document.declinedA file attached to an RFI document request has been declined 1
v1.rfi.document.validation_warningsAutomated validation flagged concerns on an RFI-attached file 1

For details: RFI case | RFI document

Connection events (partners only)

Lifecycle events on partner app connections: fired when a customer accepts or declines a connection the partner requested, or when an active connection is revoked.

EventWhen it triggers
v1.connection.acceptedThe customer approved the connection in the Hubpay Business app. It is now ACTIVE and the partner can make scoped on-behalf-of calls.
v1.connection.declinedThe customer declined the connection request. It will not become active.
v1.connection.revokedThe connection was ended by the partner or the customer. On-behalf-of access has stopped.

For details: Connection


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 createdAt for ordering. Every event includes a createdAt timestamp 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 (for example, Get payment request) to retrieve the authoritative resource state before taking action.
  • Don't hard-code lifecycle assumptions. Your handler may receive payment.completed before payment.received has arrived. If you query the API on receipt of payment.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 id to deduplicate and ensure processing an event twice has no adverse effect.
Think of webhooks as notifications, not commands

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.


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).


Receiving events

To start receiving and handling webhooks:

  1. Register your webhook URL
    Call POST /v1/webhooks with your callback URL and secret key.

  2. Listen for signed webhook events
    We will send HTTPS POST requests to your registered endpoint for every relevant event. See our webhook registration reference API for the expected payload/request.

  3. Verify the signature
    See Verifying webhook signatures

  4. Process the event

    • Inspect the event field (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
  5. Return HTTP 2xx
    A 2xx response acknowledges successful receipt. Any other response triggers automatic retries with exponential backoff (see Retry strategy).


Footnotes

  1. v1.onboarding.document.* covers files uploaded during initial KYB onboarding. v1.rfi.document.* covers files attached to an RFI document request. The two families are routed independently: subscribe to both if you need to receive per-doc decisions across both paths. 2 3 4 5 6