Custodial Funding Protocol

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.

Funding Component Diagram
Custodial Funding Components

Webhook Payment Delegation

Card payment authorization requests and other payment lifecycle events are actioned by delegating to the custodian's webhook endpoints.

Payment Sequence Diagram
Successful Custodial Payment Sequence

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:

  1. Find the payment resource based on the paymentId field.
  2. 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.
  3. Create or update the payment resource. Set the status based on the paymentFinalized field. Set the amount based on the paymentAmount field. Record the messageId field. In the same database transaction, apply an atomic balance adjustment if needed.

Auth Request Message

Nameauth-request
Delivery ModeTransactional

Description

A card payment is being requested. The custodian must decide if the payment should be allowed or declined.

The paymentAmount field is indicative of the expected final payment amount. The sign of the payment amount also indicates the type of payment. A positive, negative, or zero payment amount indicates the payment type is a purchase, refund or status enquiry respectively. The currency of the payment will align with the currency of the shared float.

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 ObligationsCreate 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 finalized payment advice message is received. The outcome of the authorization request is returned in the result field of the response payload.

Auth Confirm Message

Nameauth-confirm
Delivery ModeNotification
DescriptionThe 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 ObligationsThere 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

Namepayment-advice
Delivery ModeNotification

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 paymentAmount field indicates the total amount to be debited against the cardholders account for the payment. The advised payment amount supercedes any previously notified payment amount.

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 ObligationsCreate 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; if the payment is a refund (indicated by a negative payment amount) then the balance adjustment should be made only if the payment is finalized.

Cancellation Message

Nameauth-cancel
Delivery ModeNotification

Description

A payment has been cancelled. Any debits or credits must be rolled back. No further lifecycle notifications are expected for the payment.

The paymentAmount for a cancelled payment indicates the previously expected payment amount at the time of cancellation.

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 eventType and eventDescription fields.

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 ObligationsCreate 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 header. The public key for validating the signature can be obtained from the JWKS endpoint at https://api.immersve.com/.well-known/jwks.json.

Headers

HeaderDescription
X-Delivery-IdUnique identifier for the message delivery attempt.
X-Key-IdThe 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.
X-SignatureThe 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

DescriptionA real-time instruction to authorize a payment.
MethodPOST
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.

FieldAccepted Values
resultauthorized, 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

DescriptionA notification that a payment status has been updated.
MethodPOST
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.

FieldExampleDescription
messageIdbb32f1106c8d4c45Identifier 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.
messageTypepayment-adviceThe type of message: auth-request, auth-confirm, auth-cancel, or payment-advice. See Message Types above for more details about message semantics.
eventTypeclearing-acceptedThe 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.
eventTimestamp2022-04-01T10:00:00.000ZThe timestamp for the event that triggered the message.
eventDescriptionPayment CanceledA description of the payment event which may include additional details that can be useful for debugging.
paymentId38fb58acc55b4907Immersve payment transaction identifier. This attribute should be used to find the existing payment resource to update accordingly based on the message type.
paymentFinalizedtrueFlag 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.
paymentAmount13120000Total 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.
paymentCurrencyUSDCExpected payment currency which will be the same as the billing funding source.
paymentAcquirerAmount978Payment amount represented in the merchant's local currency. The amount will use fiat minor units. For example 978 GBP is £9.78.
paymentAcquirerCurrencyGBPThe merchant's local currency.
paymentFeeAmount32Immersve's payment fee amount in minor units. The fee currency is the same as the payment currency.
fundingSourceExternalIdabc123The custodial account external reference stored on the Immersve funding source. This attribute is used to resolve the custodial ledger account to be debited.
fundingSourceIdc65fe4d184a24619Immersve funding source identifier.
cardholderIdd44d045826d4484cImmersve cardholder account id.
cardId9ae177ea85ed4128Immersve card identifier.
merchantId92102062388908The merchant identifier from the payment network.
merchantNameUnsworth Height SuperThe merchant's name.
merchantCountryCodeNZThe merchant's ISO-3166-1 Alpha-2 country code.
merchantCityAucklandThe merchant's city name.
merchantTerminalId50487001The merchant's payment terminal identifier.
merchantCategoryCode5451The merchant's ISO-18245 category code.
networkMessageRef01005960960820000000000000The payment network identifier for the message which triggered the payment lifecycle event.