The Immersve Custodial funding protocol allows client applications to authorize Immersve card payments in real-time using their own ledger.
Protocol Mechanics
On-Chain Pooled Float
The custodian deposits a "float" into an Immersve smart contract in order to cover the anticipated cardholder payments. The available balance of the float is adjusted in real-time according to cardholder payments. When the available balance drops to zero then all cardholder payments will be declined. Settlements are handled automatically by Immersve by drawing on the float.
Webhook Payment Delegation
Card payment authorization requests and other payment lifecycle events are actioned by delegating to the custodian's webhook endpoints.
Webhook Message Types
There are four message types: auth-request
, auth-confirm
, payment-advice
, and auth-cancel
. Messages are generated from Payment Lifecycle events. Messages relating to a payment are guaranteed to be delivered in the same sequence as the lifecycle events. The semantics and integrator obligations are described below for each of these message types.
There are two delivery modes: "transactional" and "notification". Transactional delivery means the message is delivered in real-time while the payment network waits for the transaction result. Notification delivery means the message is sent asynchronously and will be retried until a successfull response has been observed. The auth-request
message type uses the transactional delivery mode and all other message types use the notification delivery mode. The two delivery modes correspond to the two webhook endpoint paths: /authorize
and /notify
.
Handling the different custodial payment message types will generally follow the same sequence:
- Find the payment resource based on the
paymentId
field. - If the payment exists and the
messageId
has already been handled (due to duplicate message delivery) then do nothing and return the same response as the first time the message was handled. - Create or update the payment resource. Set the status based on the
paymentFinalized
field. Set the amount based on thepaymentAmount
field. Record themessageId
field. In the same database transaction, apply an atomic balance adjustment if needed.
Auth Request Message
Description | A card payment is being requested. The custodian must decide if the payment should be allowed or declined. The For most payments there will be one auth request message. If the merchant requests an adjustment to the authorized amount (incremental auth) then additional auth requests will be sent with the adjusted amount. If a forced payment has been issued then there will be zero auth requests. An auth request will always be followed up with at least one more payment notification message. The subsequent notification messages will indicate changes to the status and/or payment amount. |
Handler Obligations | Create or update the payment resource relating to the paymentId field. The status should indicate the payment is pending. The amount should be set based on the paymentAmount field. If the payment is a purchase (indicated by a positive payment amount) and it is permitted then an account balance adjustment should be performed. If the payment already exists then the balance adjustment should use the difference from what has already been debited. If the payment is a refund (indicated by a negative payment amount) then the balance adjustment should not be performed until later when a payment advice message is received. The outcome of the authorization request is returned in the result field of the response payload. |
Auth Confirm Message
Description | The auth confirm message acknowledges that a payment has been successfully authorized end-to-end. The auth confirm message always follows after an auth request message. |
Handler Obligations | There are no specific requirements for handling an auth confirmation message. Handlers may choose to use this message for scheduling an asset transfer or sale. |
Payment Advice Message
Description | A payment advice message indicates a payment status has been updated or a payment has been accepted without prior authorization (forced payment). Payment advice messages cannot be declined. The Multiple payment advice messages may be delivered for a single payment. This may happen when a payment is incrementally authorized, partially cleared or partially reversed. If the payment status is non-finalized then an additional payment advice can be expected. In case a payment has been forced by the payment network then the payment advice message may be the sole message delivered in relation to the payment. |
Handler Obligations | Create or update the payment resource relating to the paymentId field. If the payment already exists, the status and amount should be adjusted based on the paymentFinalized and paymentAmount fields. Perform an account balance adjustment if necessary: a balance adjustment should be performed if the amount differs from what has already been debited or credited. |
Cancellation Message
Description | A payment has been cancelled. Any debits or credits must be rolled back. No further lifecycle notifications are expected for the payment. The A payment can be canceled at any point in the payment lifecycle. Some of the scenarios where a payment may be canceled are: payment was declined due to card block; authorization expired; or payment failed due to network error. Specific cancelation details can be discovered in the In case an error is encountered while authorizing payment then the cancellation message may be the sole message delivered in relation to the payment. |
Handler Obligations | Create or update the payment resource relating to the paymentId field. The payment status should indicate it was cancelled. The recorded payment amount should reflect the paymentAmount field. Any ledger debits or credits relating to the payment must be reverted. |
Partner Setup
A Funding Channel must be created using the Create A Funding Channel endpoint. The funding channel should have a funding type of custodial-usdc
.
Cardholder Setup
A funding source must be created for each Cardholder using the Create Funding Source endpoint. An externalId field must be supplied which can be correlated to a user's custodial ledger account. The externalId field will be supplied with every webhook notification for payments relating to the funding source.
Webhook Specs
Authentication
Webhooks are authenticated by an RSA signature. The signature is made against the concatenation of the request headers and body like {deliveryId}:{keyId}:{body}
. The signature is provided in the X-Signature
Headers
Header | Description |
---|---|
Unique identifier for the message delivery attempt. | |
The id of the signing key used to generate the signature. The key can be obtained from https://api.immersve.com/.well-known/jwks.json and matched by the "kid" attribute. | |
The hex encoded RSA SHA-256 signature of the request. |
Idempotency
Notification messages are guaranteed to be delivered. When message delivery fails, delivery will be retried at an exponentially increasing interval. When the same message has been delivered twice then the handler must ignore it and return a successful response. The messageId
field can be used to detect duplicate messages. Authorization messages are not retried; if an authorization message fails a cancel message will be sent instead.
Authorize Payment Webhook
Description | A real-time instruction to authorize a payment. |
Method | POST |
URL | {base_url}/authorize |
The authorization webhook is called when a merchant requests payment from the card.
The authorization request is expected to respond within 1000 milliseconds. Unresponsive authorization requests will be canceled.
Response Format
The authorize response must contain a JSON object with the following fields.
Field | Accepted Values |
---|---|
result | authorized , insufficient-funds , account-not-found , declined |
Merchants rely on the result value to determine the next steps in the payment process. A value of authorized
indicates payment success. All other values will result in the decline of the payment. Use declined
when a more specific value does not apply.
Payment Notification Webhook
Description | A notification that a payment status has been updated. |
Method | POST |
URL | {base_url}/notify |
A balance adjustment instruction will be sent in several scenarios: when a payment is cleared for an amount greater or less than the authorized amount; when a payment is reversed or expired; or when a refund has been issued.
The integrated client must accept the balance adjustment and increment or decrement the funding source balance accordingly.
Immersve will send a cancel payment instruction in case an error has occurred while handling an authorization request.
Request Body Format
All custodial webhook endpoints share the same message body format. The request content type is application/json. Client consumers of the message format must tolerate the addition of unknown message attributes.
Field | Example | Description |
---|---|---|
message | bb32f1106 | Identifier which uniquely identifies the message. Payment messages are guaranteed to be delivered and must be handled idempotently. This identifier can be used to detect duplicate message delivery attempts. |
message | payment-advice | The type of message: auth-request , auth-confirm , auth-cancel , or payment-advice . See Message Types above for more details about message semantics. |
event | clearing-accepted | The payment lifecycle event which triggered the message. This may be useful to discriminate the reason for an auth cancellation message. Clients must tolerate unknown event types. Event types may include the following: auth-requested ,auth-confirmed , auth-declined , auth-forced ,clearing-accepted , clearing-declined , payment-expired ,auth-reversal-accepted ,clearing-reversal-accepted . |
event | 2022-04-01T | The timestamp for the event that triggered the message. |
event | Payment Canceled | A description of the payment event which may include additional details that can be useful for debugging. |
payment | 38fb58acc | Immersve payment transaction identifier. This attribute should be used to find the existing payment resource to update accordingly based on the message type. |
payment | true | Flag indicating if the payment is expected to have further updates. Messages of type "auth-request" will always be non-finalized. Payments are eventually finalized after being cleared, expired or cancelled. Payments may be updated after being finalized if, for example, the payment is reversed. |
payment | 13120000 | Total payment amount that the cardholder will be debited in minor units. The payment amount may increase or decrease when cleared or reversed. A positive, negative, or zero payment amount indicates the payment type is a purchase, refund or status enquiry respectively. The amount will use the stable coin minor units. For example, 13120000 USDC is $13.12. The payment amount includes fees. |
payment | USDC | Expected payment currency which will be the same as the billing funding source. |
payment | 978 | Payment amount represented in the merchant's local currency. The amount will use fiat minor units. For example 978 GBP is £9.78. |
payment | GBP | The merchant's local currency. |
payment | 32 | Immersve's fee portion of the payment amount in minor units. The fee currency is the same as the payment currency. |
funding | abc123 | The custodial account external reference stored on the Immersve funding source. This attribute is used to resolve the custodial ledger account to be debited. |
fundingSourceId | c65fe4d18 | Immersve funding source identifier. |
cardholder | d44d04582 | Immersve cardholder account id. |
card | 9ae177ea8 | Immersve card identifier. |
merchant | 921020623 | The merchant identifier from the payment network. |
merchant | Unsworth Height Super | The merchant's name. |
merchant | NZ | The merchant's ISO-3166-1 Alpha-2 country code. |
merchant | Auckland | The merchant's city name. |
merchant | 50487001 | The merchant's payment terminal identifier. |
merchant | 5451 | The merchant's ISO-18245 category code. |
network | 010059609 | The payment network identifier for the message which triggered the payment lifecycle event. |