Skip to main content

ePayment PSP API guide

As a PSP, you can process card payments through your own infrastructure using CARD_PASSTHROUGH as the payment method type. When the user selects a card in the Vipps MobilePay app, the card token is sent to your callback URL. You process the payment and respond with the result.

This page covers the PSP-specific additions.

tip

The ePayment API covers the full breadth of the underlying platform — including detailed flow diagrams, user journey walkthroughs, and advanced features that apply to PSP integrations as well.

Flow​

With CARD_PASSTHROUGH, the payment creation flow is:

  1. PSP creates a payment with paymentMethod.type: CARD_PASSTHROUGH and a cardPassthrough object specifying your callback URL (cardCallbackUrl).
  2. The user is redirected to the Vipps MobilePay app and selects a card.
  3. Vipps MobilePay sends the card token (or encrypted PAN) to cardCallbackUrl synchronously.
  4. PSP processes the payment using their own payment processing systems and responds within 20 seconds.
  5. The user is redirected to your returnUrl.
  6. PSP updates the payment status in Vipps MobilePay.

PSP merchant payment flow

  1. PSP creates a payment with Vipps MobilePay (POST /epayment/v1/payments with cardPassthrough).
  2. Vipps MobilePay returns the payment created response with a redirectUrl to PSP.
  3. PSP redirects user to Vipps MobilePay.
  4. User selects a card and confirms the payment.
  5. Vipps MobilePay posts a card token to the PSP's cardCallbackUrl.
  6. PSP processes the payment using the token.
  7. PSP returns 200 OK to Vipps MobilePay.
  8. Vipps MobilePay redirects the user to the returnUrl.
  9. PSP updates the payment status with Vipps MobilePay (e.g., POST /epayment/v1/payments/{reference}/capture).

Operations​

PSPs can use all ePayment API endpoints with the Psp-Id header added to every request. The only endpoint requiring PSP-specific configuration is POST:/epayment/v1/payments.

The following table shows how ePayment endpoints are used in a PSP CARD_PASSTHROUGH integration.

ePayment endpointsPSP usage and notes
Create payment:
POST:/epayment/v1/payments
Create CARD_PASSTHROUGH payment with Psp-Id and cardPassthrough callback fields. See Create payment.
Update the payment status:
POST:/epayment/v1/payments/{reference}/capture
POST:/epayment/v1/payments/{reference}/refund
POST:/epayment/v1/payments/{reference}/cancel
Communicate capture, refund, and cancel status to Vipps MobilePay. Payment processing happens in PSP/acquirer systems. See Update the payment status.
Check the payment status:
GET:/epayment/v1/payments/{reference}
GET:/epayment/v1/payments/{reference}/events
Optional: compare current state/amounts with PSP records and decide if updates are needed. See Get payment information.

Create a single online payment​

The payment flow is user-initiated. The user selects a card in the Vipps MobilePay app, and Vipps MobilePay calls your cardCallbackUrl synchronously with the card token. You process the payment and respond with the result, then update us with the outcome.

Send a POST:/epayment/v1/payments request with the required parameters. Set paymentMethod.type to CARD_PASSTHROUGH and include the cardPassthrough object.

Example request (PSP-specific fields are highlighted):

curl -X POST https://apitest.vipps.no/epayment/v1/payments \
-H "Content-Type: application/json" \
-H "Psp-Id: YOUR-PSP-ID" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H "Idempotency-Key: YOUR-IDEMPOTENCY-KEY" \
-d '{
"amount": {
"currency": "NOK",
"value": 6000
},
"customer": {
"phoneNumber": "4712345678"
},
"paymentMethod": {
"type": "CARD_PASSTHROUGH"
},
"cardPassthrough": {
"pspReference": "payment-ref-123456",
"cardCallbackUrl": "https://example.com/psp-callback",
"allowedCardTypes": ["VISA_DEBIT", "VISA_CREDIT", "DANKORT", "MC_CREDIT", "MC_DEBIT"],
"publicEncryptionKeyId": "3f1c2e90-7a4b-4c9d-8f21-6b3e2d7a91c4"
},
"reference": "acme-shop-123-order123abc",
"userFlow": "WEB_REDIRECT",
"returnUrl": "https://example.com/redirect?orderId=1512202",
"paymentDescription": "Purchase of socks"
}'

When the user confirms the payment in the Vipps MobilePay app and selects their card, Vipps MobilePay sends a card token to your cardCallbackUrl. See Card callback for the request format, HMAC authentication, and expected response.

Once you've processed the payment, update payment status so that the Vipps MobilePay app will show the user the correct status.

Parameters​

Required header parameters

  • Authorization - Bearer-Authorization. The access token is a base64-encoded string that is required for all API calls.
  • Idempotency-Key - Idempotency key for the request, ensures idempotent actions. See Idempotency
  • Ocp-Apim-Subscription-Key - The subscription key for a sales unit. See API keys.
  • Merchant-Serial-Number - The Merchant Serial Number is a unique identifier that is defined when a sales unit is created. See How to find the Merchant Serial Number
  • Psp-Id - Only used by Payment Service Providers.

There are several optional HTTP headers that are helpful for debugging (e.g., Vipps-System-Name).

Required body parameters

  • paymentMethod.type - Must be set to CARD_PASSTHROUGH.
  • cardPassthrough - Supply values as described in cardPassthrough.
  • amount - Amount object, containing a value and a currency. The minimum amounts allowed are: NOK 100 øre, DKK 1 øre, EUR 1 cent. The allowed currencies are these string values: "NOK", "DKK", "EUR", "SEK", "USD", "GBP". PSPs are not limited to using the currency registered for the sales unit.
  • reference - The reference is the unique identifier for the payment, specified when initiating the payment. The reference must be unique for the sales unit (MSN), but is not globally unique, so several MSNs may use the same reference. See the orderId / reference recommendations.
  • userFlow - The normal flow is WEB_REDIRECT. See ePayment API: userFlow for more details.
  • customer - Required for userFlow of PUSH_MESSAGE. The customer phone number or login token.
  • returnUrl - Required for userFlow of WEB_REDIRECT. The URL the user is returned to after the payment session. The URL must use the https:// scheme or a custom URL scheme.
cardPassthrough​

The cardPassthrough object is required when creating a CARD_PASSTHROUGH payment.

FieldRequiredDescription
pspReferenceYesYour unique reference for this payment.
cardCallbackUrlYesURL where we send the user's card data. See Card callback for the expected request and response format.
allowedCardTypesYesCard types the user can select. Values: VISA_DEBIT, VISA_CREDIT, MC_CREDIT, MC_DEBIT, DANKORT.
preferVisaPartOfVisaDankortNoWhen true, prefer the Visa part of a Visa/Dankort co-branded card. Default: false.
publicEncryptionKeyIdNoGUID of your public key registered with us. When provided, we encrypt the PAN in the card callback. If not provided, only tokens are returned.
note

If you include DANKORT in allowedCardTypes, consider providing a publicEncryptionKeyId. Standalone Dankort cards are not tokenizable — without a key, payments from those cards will fail. See Token vs encrypted PAN in the Card callback section for details.

Create an Express payment​

Approval required

The merchant's sales unit must be approved to use the Express feature. PSPs must ensure their merchants have obtained this approval before enabling Express payments. To request access, the merchant should contact their key account manager, their partner manager, or customer service.

With Express, the user selects shipping options and shares their profile inside the app. Then the PSP's cardCallbackUrl is called with the card token to process. For a visual walkthrough of the customer's experience with Express, see How Express works.

To enable Express, add the following to your payment creation request, POST:/epayment/v1/payments:

  • paymentMethod.type set to CARD_PASSTHROUGH
  • cardPassthrough object with your server URL specified in the cardCallbackUrl field
  • profile.scope: "name address email phoneNumber" (all four values required)
  • shipping: either fixedOptions or dynamicOptions — For full details, see Shipping options
  • Other required parameters as mentioned above

Note that amount is the base product price. Vipps MobilePay adds the selected shipping cost before the user confirms.

Example request (PSP and Express-specific fields are highlighted):

curl -X POST https://apitest.vipps.no/epayment/v1/payments \
-H "Content-Type: application/json" \
-H "Psp-Id: YOUR-PSP-ID" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H "Idempotency-Key: YOUR-IDEMPOTENCY-KEY" \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
-d '{
"amount":{
"currency":"NOK",
"value":6000
},
"customer":{
"phoneNumber":"4712345678"
},
"paymentMethod": {
"type": "CARD_PASSTHROUGH"
},
"cardPassthrough": {
"pspReference": "payment-ref-1234567",
"cardCallbackUrl": "https://example.com/psp-callback",
"allowedCardTypes": ["VISA_DEBIT", "VISA_CREDIT", "DANKORT", "MC_CREDIT", "MC_DEBIT"],
"publicEncryptionKeyId": "3f1c2e90-7a4b-4c9d-8f21-6b3e2d7a91c4"
},
"profile": {
"scope": "name address email phoneNumber"
},
"shipping": {
"fixedOptions": [
{
"isDefault": true,
"priority": 0,
"type": "PICKUP_POINT",
"brand": "POSTNORD",
"options": [
{
"id": "meny_grunerlokka",
"isDefault": true,
"amount": {
"currency": "NOK",
"value": 3900
},
"priority": 0,
"name": "Meny Grünerløkka",
"meta": "Henrik Ibsens Gate 1, 0000 Oslo",
"estimatedDelivery": "In 2 days"
},
{
"id": "bunnpris_skoyen",
"isDefault": false,
"amount": {
"currency": "NOK",
"value": 3900
},
"name": "Bunnpris Skøyen",
"priority": 1,
"meta": "Gatenavn 21, 0001 Oslo",
"estimatedDelivery": "In 2 days"
}
]
}
]
},
"reference": "acme-shop-123-order123abc",
"userFlow": "WEB_REDIRECT",
"returnUrl": "https://developer.vippsmobilepay.com/docs/example-pages/result-page/",
"paymentDescription": "Purchase of socks"
}'

After authorization, retrieve shippingDetails and userDetails from GET:/epayment/v1/payments/{reference} (include the Psp-Id header). You can also get this information through the ePayment webhook payload.

The shippingDetails object provides information about the shipment:

  • address - An object that holds the recipient's shipping address, including: addressLine1, addressLine2, city, country, postCode.
  • shippingCost - The cost of shipping, specified in minor currency units. For example, 9900 (99.00 NOK).
  • shippingOptionId - The ID of the selected shipping option.
  • shippingOptionName - The name of the selected shipping option.

The userDetails object contains email, firstName, lastName, mobileNumber, and addresses.

For example:

"shippingDetails": {
"address": {
"addressLine1": "BOKS 6300, ETTERSTAD",
"addressLine2": "",
"city": "OSLO",
"country": "NO",
"postCode": "0603"
},
"shippingCost": 0,
"shippingOptionId": "posten2",
"shippingOptionName": "Postibutikk"
},
"userDetails": {
"email": "test.user@example.com",
"firstName": "Test",
"lastName": "User",
"mobileNumber": "4712345678",
"addresses": [
{
"addressLine1": "BOKS 6300, ETTERSTAD",
"addressLine2": "",
"city": "OSLO",
"country": "NO",
"postCode": "0603"
},
{
"addressLine1": "Robert Levins gate 5",
"addressLine2": "",
"city": "Oslo",
"country": "NO",
"postCode": "0152"
}
]
}

For full details on shipping options, dynamic callbacks, and button guidelines, see the Express feature guide.

With this information, you have all you need to ship the package and collect payment. Remember to update the payment status with Vipps MobilePay.

Get payment information​

To get information about a payment (including shipping details for Express):

Supply the Psp-Id header.

Example request:

curl -X GET https://apitest.vipps.no/epayment/v1/payments/PAYMENT-REFERENCE-ID \
-H "Psp-Id: YOUR-PSP-ID" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \

For a sequence of events, see: GET:/epayment/v1/payments/{reference}/events.

See ePayment API guide: Get payment details for more information.

Update payment status​

Use these ePayment endpoints to keep us aligned with the payment state in your PSP/acquirer systems — both immediately after processing and later for captures and refunds. Include your PSP identifier in the Psp-Id header.


Card callback​

The card callback applies to:

  • ePayment PSP API: creating a payment
  • Recurring PSP API: agreement sign-up and payment source updates

The flow works like this:

  1. The PSP sends Vipps MobilePay an API request to initiate an ePayment or Recurring request.
  2. Vipps MobilePay presents the request to the user in the app.
  3. If the user approves and selects their card, Vipps MobilePay sends a POST request to the cardCallbackUrl specified in the initial request.
  4. The PSP must decrypt the message and respond within 20 seconds, or the request will fail.

How the callback works:

  • The callback is synchronous — your endpoint must respond with the payment authorization result.
  • If you respond with a retryable error, the user can retry with the same or a different card.
  • HTTP 500 errors and timeouts are treated as non-retryable.
tip

If you need to whitelist our servers, find details on the servers page.

Callback request​

Request body​

The callback we send to your server contains the following properties:

  • pspReference: Your unique reference for this payment, as provided in the create payment request.
  • authorizationAttemptId: Unique identifier for this authorization attempt.
  • merchantSerialNumber: The merchant serial number for the payment.
  • amount: Object containing the payment amount:
    • value: The amount in minor units.
    • currency: The three-letter ISO 4217 currency code.
  • softDeclineCompletedRedirectUrl: URL to redirect to after a soft decline is resolved.
  • cardInfo: Object containing the card details:
    • maskedCardNumber: The masked card number (for example, 47969485XXXX1234).
    • cardType: The card type (for example, VISA-DEBIT).
    • cardIssuedInCountryCode: The ISO 3166-1 alpha-2 country code where the card was issued.
    • cardDataType: The type of card data included in the callback. Possible values are TOKEN or PAN. See Token vs encrypted PAN.
    • networkToken: Object containing the network token details when cardDataType is TOKEN:
      • number: The token number.
      • cryptogram: The cryptogram for the transaction.
      • expiryMonth: Token expiry month.
      • expiryYear: Token expiry year.
      • tokenType: Token network type (for example VISA).
      • eci: Electronic Commerce Indicator.
      • paymentAccountReference: Stable reference across token renewals.
    • encryptedPan: Encrypted PAN when cardDataType is PAN.

The callback body is plain JSON — no decryption is needed to read it. Use HMAC authentication to verify that the callback is genuine before processing it.

An example request body containing a token:

{
"pspReference": "7686f7788898767977",
"authorizationAttemptId": "d8f9a1d7-b9d3-4c2f-b5c2-7d8b93df12ab",
"merchantSerialNumber": "123456",
"amount": {
"value": 1000,
"currency": "DKK"
},
"softDeclineCompletedRedirectUrl": "https://vipps.no/mobileintercept?transactionId=123456789&responsecode=OK",
"cardInfo": {
"maskedCardNumber": "47969485XXXX1234",
"cardType": "VISA-DEBIT",
"cardIssuedInCountryCode": "DK",
"cardDataType": "TOKEN",
"networkToken": {
"number": "5000000000000000001",
"cryptogram": "AAAAAAAAAAAAAAA=",
"expiryMonth": "03",
"expiryYear": "2030",
"tokenType": "VISA",
"eci": "7",
"paymentAccountReference": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
},
"encryptedPan": null
}
}

If you requested an encrypted PAN and one is available, encryptedPan will be populated instead of networkToken:

{
"pspReference": "7686f7788898767977",
"authorizationAttemptId": "731C95C5-7E8B-40C3-A6EA-713B24694E6E",
"merchantSerialNumber": "123456",
"softDeclineCompletedRedirectUrl": "https://vipps.no/mobileintercept?transactionId=123456789&responsecode=OK",
"cardInfo": {
"maskedCardNumber": "47969485XXXX1234",
"cardType": "VISA-DEBIT",
"cardIssuedInCountryCode": "DK",
"cardDataType": "PAN",
"encryptedPan": "fsfnsdjkfbgdft34895u7345"
},
"amount": {
"value": 1000,
"currency": "DKK"
}
}

You must decrypt encryptedPan using your RSA private key to obtain the card number. See Token vs encrypted PAN for details.

HMAC authentication​

To verify that the callback originates from us and has not been tampered with, we sign each callback using HMAC with a shared secret.

The shared secret is your PSP client secret.

Use the shared secret together with the Host, x-ms-date, x-ms-content-sha256, and Authorization headers of the request.

How HMAC works
  1. Secret key: A secret key is shared between the sender and the receiver.
  2. Message: The message to be authenticated.
  3. Hash function: A cryptographic hash function such as SHA-256 is used.
  4. HMAC generation:
    • The message and the secret key are combined in a specific way.
    • The combined data is hashed using the cryptographic hash function.
    • The result is the HMAC value.
  5. Verification:
    • The receiver uses the same secret key and hash function to generate an HMAC value for the received message.
    • The receiver compares the generated HMAC value with the HMAC value sent with the message.
    • If they match, the message is verified as authentic and unaltered.

You will receive an HTTP POST with this format:

POST https://example.com/psp-makepayment

Host: example.com
x-ms-date: Thu, 30 Mar 2023 08:38:32 GMT
x-ms-content-sha256: WyZnKtAizV4gkGbiMMhm2NIrvlumpic9Zdjcqs6Q2hw=
Authorization: HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=RwcYy13oXAu1ZFU1zOi0MmSIHynnNnHe9lwNx+LgMqc=
X-Vipps-Authorization: HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=RwcYy13oXAu1ZFU1zOi0MmSIHynnNnHe9lwNx+LgMqc=
Content-Type: application/json

{ ... }

X-Vipps-Authorization contains the same value as Authorization. You can verify either header, but they should match when both are present.

  1. Check that the content has not been modified

    Hash the exact request body as UTF-8 using SHA-256, then base64 encode it. This hash must match the x-ms-content-sha256 header. Use the raw body exactly as received. Re-serializing the JSON may change whitespace and produce a different hash.

  2. Verify the authentication header

    Concatenate the request method, path and query, date, host, and content hash in this format:

    POST\n<pathAndQuery>\n<date>;<host>;<hash>

    The host value must match the Host header, including the port if one is present.

    Please note the use of \n not \r\n.

    Sign the string with HMAC-SHA256 using your shared secret. This must match the Signature part of the Authorization header.

Sample code
'use strict';

const assert = require('node:assert');
const { describe, it } = require('node:test');
const crypto = require('crypto');

describe('Sample code', () => {
it('Verifying card callback HMAC headers', () => {
const secret = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==';

const request = {
method: 'POST',
url: 'https://example.com/psp-makepayment',
pathAndQuery: '/psp-makepayment',
headers: {
'Host': 'example.com',
'x-ms-date': 'Thu, 30 Mar 2023 08:38:32 GMT',
'x-ms-content-sha256': 'WyZnKtAizV4gkGbiMMhm2NIrvlumpic9Zdjcqs6Q2hw=',
'Authorization': 'HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=RwcYy13oXAu1ZFU1zOi0MmSIHynnNnHe9lwNx+LgMqc=',
'X-Vipps-Authorization': 'HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=RwcYy13oXAu1ZFU1zOi0MmSIHynnNnHe9lwNx+LgMqc='
},
content: '{"pspReference":"7686f7788898767977","authorizationAttemptId":"3030303thisisaguid","merchantSerialNumber":"123456"}'
};

const expectedContentHash = crypto
.createHash('sha256')
.update(request.content, 'utf8')
.digest('base64');

assert.equal(
request.headers['x-ms-content-sha256'],
expectedContentHash,
'Content hash was not valid');

const expectedSignedString =
`${request.method}\n` +
`${request.pathAndQuery}\n` +
`${request.headers['x-ms-date']};${request.headers['Host']};${request.headers['x-ms-content-sha256']}`;

const expectedSignature = crypto
.createHmac('sha256', secret)
.update(expectedSignedString, 'utf8')
.digest('base64');

const expectedAuthorization =
`HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=${expectedSignature}`;

assert.equal(expectedAuthorization, request.headers.Authorization, 'Authorization was not valid');
assert.equal(request.headers['X-Vipps-Authorization'], request.headers.Authorization, 'Headers did not match');
});
});

Token vs encrypted PAN​

By default, the card callback includes a card token and cryptogram, covering the vast majority of Visa and Mastercard cards.

A small number of cards (~0.1%) are not tokenizable — primarily the Danish Dankort rail, but occasionally individual Visa or Mastercard issuers. Provide a publicEncryptionKeyId to receive an encrypted PAN for these cards; without it, those payments will fail.

Encrypted PAN setup and handling

To enable encrypted PAN, you must:

  1. Onboard a public encryption key with us.

    The RSA public key should be provided as X.509 SubjectPublicKeyInfo (using ASN.1 DER Encoding) represented in PEM encoding (use PEM file extension). The public key must have a length of 4096 bits. You must clearly state your PSP name in the file name. Naming template for public key: {integratorname}-{environment}-public

    • Example: company-prod-public

    Please send the public keys in a ZIP-file. We will register the keys and supply you with a PublicKeyId to be used when initiating payments.

    Please note that if a public key is unused for 6 months, we will delete it. If this happens, you must supply a new public key.

  2. Pass the resulting publicEncryptionKeyId in the cardPassthrough object when creating the payment or agreement.

The encryptedPan is encrypted using RSA/NONE/OAEPWithSHA256AndMGF1Padding (SHA-256 is also used for padding). Once decrypted, the structure looks like this:

{"timestampticks":123456789123456789,"encryptedCardData": { "cardNumber": 1234567812345678, "expiryMonth": 12, "expiryYear": 28 }}
Always use the cardType field

Always process the payment using the card type specified in the cardType field. This is the only way we can offer card type picking for co-branded cards in accordance with PSD2 requirements. If you process a PAN where cardType is DANKORT as a Visa transaction, the SCA will be missing and an unwanted 3DS step-up is likely to occur. PAN-based transactions are not regarded as authenticated — handle them according to your acquirer's scheme rules for SCA compliance.

Dankort co-branded cards

Most Dankort cards are co-branded as Visa/Dankort, supporting both a tokenizable Visa flow and a PAN-based Dankort flow. If you include DANKORT in allowedCardTypes and provide a publicEncryptionKeyId, the Dankort rail will be available. Use the preferVisaPartOfVisaDankort flag to route co-branded cards through the Visa rail instead.

To process tokens only, omit publicEncryptionKeyId and remove DANKORT from allowedCardTypes — standalone Dankort cards are not tokenizable.

Callback response​

You must return a valid callback response within 20 seconds or the operation will fail.

Respond with HTTP 200 OK and a JSON body with the following properties:

  • status (required): The payment authorization result. One of:
    • RESERVE - The authorization succeeded, and the amount was reserved.
    • SOFT_DECLINE - Additional cardholder action is required to complete the authorization. Include softDeclineUrl.
    • FAIL - The authorization failed. Include errorCode and errorMessage.
  • networkTransactionReference: Your reference for the network transaction. Include this when the authorization succeeded and you have such a reference.
  • softDeclineUrl: URL the user should be redirected to in order to complete a soft decline flow. Required when status is SOFT_DECLINE.
  • errorCode: Numeric error code describing why the authorization failed. Required when status is FAIL.
  • errorMessage: Human-readable description of the failure. Required when status is FAIL.

The following examples show what the response body should look like for each status value.

Use RESERVE when the authorization succeeded and the payment should remain reserved for a later capture.

{
"networkTransactionReference": "123456789",
"status": "RESERVE"
}

Use SOFT_DECLINE when the cardholder must complete an additional issuer or authentication step before the payment can proceed.

{
"status": "SOFT_DECLINE",
"softDeclineUrl": "https://example.com"
}

Use FAIL when the authorization did not succeed and no soft decline flow is available.

{
"status": "FAIL",
"errorCode": 300,
"errorMessage": "Refused by Issuer"
}

When you respond with status: FAIL, use one of the following errorCode values:

errorCodeNameRetryableDescription
100Card ErrorYesCard-related failure where the card should not be retried unchanged for this payment.
200Insufficient FundsYesThe card or account does not have enough available funds to complete the payment.
210Limit ExceededYesA card, account, or issuer limit has been reached, so the payment cannot be authorized.
300Issuer DeclinedYesThe issuer declined the payment without providing a more specific reason.
400Permanent DeclineNoA hard decline where the payment must not be retried.
500Risk DeclinedYesThe payment was blocked by fraud or risk controls.
600Temporary Technical ErrorYesA transient PSP, issuer, or network problem prevented the authorization attempt from completing.
700Merchant Configuration ErrorNoThe payment failed because of merchant, PSP, or transaction configuration issues.
800Duplicate or In ProgressNoThe payment is already being processed, or a duplicate attempt was detected, so retrying immediately is not allowed.
900Unknown ErrorYesThe authorization failed, but the reason could not be mapped confidently to a more specific error.

If we receive a FAIL response, we will allow the user to retry with the same or a new payment source unless the errorCode maps to a non-retryable failure.

If there is a timeout or HTTP 500, the payment cannot be tried again by the user. You will need to initiate a new payment request.

More information​

  • ePayment API guide — More examples and details for using these endpoints.
  • ePayment API spec — the full technical specification for all endpoints, including required fields, data types, and valid formats