Merchant Webhooks
Merchant webhooks receive business event notifications sent by FuturePay UCard.
Integration Steps
- Sign in to the FuturePay merchant console, enter your Webhook URL in UCard's Tenant Callback Configuration, and enable it. Only one callback URL can be enabled per merchant at a time.
- Expose a publicly accessible HTTP endpoint at that URL to receive
POST application/jsonrequests from FuturePay. - Verify the platform signature using the request headers and the unmodified raw request body.
- Read
eventTypein the payload and dispatch to the appropriate business handler. - Use
eventNofor idempotency and return HTTP 2xx after successful receipt.
All supported UCard events are sent to the same enabled Webhook URL. Do not configure separate URLs for individual events; dispatch by eventType in your receiving service.
Legacy Event Compatibility
New events use schemaVersion: 2, and eventType identifies only the business scenario. To preserve the original request body, signature, and replay idempotency, replays of historical PENDING/DEAD events may still contain status-based eventType values; legacy card withdrawal events may omit eventType. Continue to use eventNo for idempotency and retain parsing support for historical formats.
Callback Request
FuturePay sends requests as follows:
| Item | Description |
|---|---|
| HTTP method | POST |
| Content-Type | application/json |
| Request URL | The enabled Webhook URL in the merchant console |
| Request timeout | 10 seconds |
| Successful response | Any HTTP 2xx |
HTTP 3xx, 4xx, and 5xx responses, connection errors, and timeouts are treated as delivery failures. Use HTTPS where possible, and verify the signature and reliably persist the event within 10 seconds. Lengthy business processing can run asynchronously after persistence.
Signature Headers
Each webhook request includes these headers:
| Header | Description |
|---|---|
X-FP-Timestamp | Millisecond timestamp when FuturePay generated the signature. |
X-FP-Api-Key | FuturePay Ed25519 public key in hex. |
X-FP-Signature | FuturePay signature in hex. |
X-FP-Body-Hash | SHA-256 hash of the raw request body in hex. |
The signing string is:
X-FP-Timestamp|RAW_CALLBACK_BODYUse the raw request body as received for verification. Do not parse and reserialize the JSON first. See Signing and Authentication for the full algorithm and key details.
Common Fields
| Field | Type | Description |
|---|---|---|
schemaVersion | integer | Payload schema version. Always 2 for new events. |
eventNo | string | Unique webhook event number and merchant idempotency key. Unchanged by automatic retries or manual replays. |
eventType | string | Business scenario used to select the appropriate handler; does not encode success or failure. |
status | string | Business status for the current scenario. Its meaning depends on the event. |
failCode | string | Failure code; empty when no failure information is available. |
failMessage | string | Failure reason; empty when no failure information is available. |
occurredTime | string | Event time in yyyy-MM-dd HH:mm:ss format. |
Events carry their own business fields. Identify the event type before parsing its structure; do not assume all event payloads have the same fields.
Event Types
eventType | Description |
|---|---|
CARD_OPENING | Card issuance; use status to determine success or failure. |
CARD_RECHARGE | Card recharge; use status to determine success or failure. |
CARD_WITHDRAWAL | Card withdrawal; use status to determine success or failure. |
CARD_CONSUMPTION | Card purchase; use status, feeCharged, and failure fields to determine transaction and fee outcomes. |
CARD_MONTHLY | Monthly card fee; use status to determine whether collection succeeded or failed. |
Event Business Fields
In addition to the common fields, events include the following business fields:
eventType | status Values | Business Fields |
|---|---|---|
CARD_OPENING | SUCCESS or FAILED | cardOrderNo, requestNo, feeAmount, assetCode, cardId, cardAccountId, last4, expiryMonth, expiryYear |
CARD_RECHARGE | SUCCESS or FAILED | orderNo, requestNo, cardId, amount, currency, feeAmount, feeCurrency |
CARD_WITHDRAWAL | SUCCESS or FAILED | orderNo, requestNo, cardId, amount, feeAmount, platformFeeAmount, tenantFeeAmount, totalAmount, currency |
CARD_CONSUMPTION | Final card transaction status, such as SUCCESS, COMPLETED, SETTLED, FAILED, REJECTED, CANCELLED, or CANCELED | providerTransactionId, cardId, cardAccountId, amount, assetCode, countryCode, feeCharged, transactionFee, authorizationFee, totalFee |
CARD_MONTHLY | SUCCESS or FAILED | cardId, billingMonth, amount, assetCode |
For CARD_CONSUMPTION, status describes the card transaction. Determine whether fee processing succeeded using feeCharged, totalFee, failCode, and failMessage together.
For CARD_WITHDRAWAL, both amount and totalAmount currently represent the total amount deducted for the withdrawal: principal plus fees.
Card Purchase Notification Example
The card purchase notification uses countryCode for the country or region of the purchase:
{
"schemaVersion": 2,
"eventNo": "UCCB202608040001",
"eventType": "CARD_CONSUMPTION",
"providerTransactionId": "TXN202608040001",
"cardId": "CARD001",
"cardAccountId": "ACCOUNT001",
"amount": "100.00",
"assetCode": "USD",
"countryCode": "US",
"feeCharged": true,
"transactionFee": "1.00",
"authorizationFee": "0.00",
"totalFee": "1.00",
"status": "SUCCESS",
"failCode": null,
"failMessage": null,
"occurredTime": "2026-08-04 12:00:00"
}Idempotency
FuturePay uses at-least-once delivery, so the same event may be sent multiple times. Use eventNo as the unique idempotency key. Do not deduplicate solely by eventType, order number, or transaction number.
Recommended processing order:
- Verify the platform signature.
- Insert
eventNointo your database with a unique constraint. - If
eventNoalready exists, return HTTP 2xx immediately. - Process the event according to
eventType. - Commit the local transaction, then return HTTP 2xx.
Returning 2xx before asynchronously persisting the event can lose notifications if the process crashes. If business processing is lengthy, first persist the original event reliably, then consume it asynchronously.
Retry Rules
- After the first delivery failure, FuturePay continues scanning pending events and retrying delivery.
- Each event receives at most 3 automatic attempts.
- A non-2xx response, connection error, or 10-second timeout consumes one attempt.
- Automatic retries and manual platform replays preserve the original
eventNoand request body. - After all three automatic attempts fail, automatic delivery stops. Operators may still replay the event manually, so merchants must not disable idempotency protection after any time window.
- Do not rely on a fixed retry interval or assume events arrive strictly in occurrence order.
Integration Checklist
- The correct Webhook URL is configured and enabled in the merchant console.
- The endpoint accepts
POST application/jsonand responds within 10 seconds. X-FP-*signatures are verified against the raw request body.- Business handling is dispatched by scenario-based
eventType, with support for historical status-based event formats. - The database enforces uniqueness for
eventNo. - Duplicate events return HTTP 2xx without repeating fund movements or order status changes.
