# Encoded Gateway API > Developer documentation for building against the Encoded Gateway API. > Production base URL: https://prod.encoded.services/api/v1 > Sandbox base URL: https://sit.encoded.services/api/v1 ## API Reference - [OpenAPI v1 YAML](http://docs.encoded.services/api/static/v1/encoded_openapi.yaml) - [OpenAPI v1 JSON](http://docs.encoded.services/api/static/v1/encoded_openapi.json) - [OpenAPI v1 YAML alias](http://docs.encoded.services/api/static/encoded_openapi.yaml) - [API reference](http://docs.encoded.services/api-reference/v1) ## Guides - [APM JavaScript Library](http://docs.encoded.services/alternative-payment-methods/v1/apm-javascript-library): APM JavaScript Library - [Apple Pay](http://docs.encoded.services/alternative-payment-methods/v1/apple-pay): Apple Pay - [Google Pay](http://docs.encoded.services/alternative-payment-methods/v1/google-pay): Google Pay - [Quick Start](http://docs.encoded.services/guides/v1/quick-start): Quick Start - [Separate Authorisation and Capture](http://docs.encoded.services/payment-flows/v1/authorise-and-capture): Separate Authorisation and Capture - [Create a Payment Plan](http://docs.encoded.services/payment-flows/v1/create-a-payment-plan): Create a Payment Plan - [ECOM Payment with 3DS2 Challenge](http://docs.encoded.services/payment-flows/v1/ecom-3ds2-card-payment): ECOM Payment with 3DS2 Challenge - [Hosted Payment Fields Session](http://docs.encoded.services/payment-flows/v1/hosted-payment-fields-session): Hosted Payment Fields Session - [Hosted Payment Page with an Order](http://docs.encoded.services/payment-flows/v1/hosted-payment-page-order): Hosted Payment Page with an Order - [Stored Card Transaction](http://docs.encoded.services/payment-flows/v1/pay-with-a-token): Stored Card Transaction - [Generate and Send a PayByLink](http://docs.encoded.services/payment-flows/v1/paybylink): Generate and Send a PayByLink - [Refund a Payment](http://docs.encoded.services/payment-flows/v1/refund-a-payment): Refund a Payment - [Store a Card](http://docs.encoded.services/payment-flows/v1/save-a-card): Store a Card - [Processing a MOTO Payment](http://docs.encoded.services/payment-flows/v1/take-a-card-payment): Processing a MOTO Payment - [Void an Authorisation](http://docs.encoded.services/payment-flows/v1/void-an-authorisation): Void an Authorisation - [Response Codes](http://docs.encoded.services/testing/v1/response-codes): Response Codes - [Testing](http://docs.encoded.services/testing/v1/testing): Testing ## Concepts - [API Object Model](http://docs.encoded.services/concepts/v1/api-object-model): API Object Model - [Authentication](http://docs.encoded.services/concepts/v1/authentication): Authentication - [Custom Domains](http://docs.encoded.services/concepts/v1/custom-domains): Custom Domains - [Customers](http://docs.encoded.services/concepts/v1/customers): Customers - [EMV 3-D Secure](http://docs.encoded.services/concepts/v1/emv-3d-secure): EMV 3-D Secure - [Environments and URLs](http://docs.encoded.services/concepts/v1/environments-and-urls): Environments and URLs - [Hosted Payment Fields](http://docs.encoded.services/concepts/v1/hosted-payment-fields): Hosted Payment Fields - [Hosted Payment Pages](http://docs.encoded.services/concepts/v1/hosted-payment-pages): Hosted Payment Pages - [Merchant Accounts](http://docs.encoded.services/concepts/v1/merchant-accounts): Merchant Accounts - [Notification Callbacks](http://docs.encoded.services/concepts/v1/notification-callbacks): Notification Callbacks - [Orders](http://docs.encoded.services/concepts/v1/orders): Orders - [PayByLink](http://docs.encoded.services/concepts/v1/paybylink): PayByLink - [Payment Orchestration](http://docs.encoded.services/concepts/v1/payment-orchestration): Payment Orchestration - [Payment Plans](http://docs.encoded.services/concepts/v1/payment-plans): Payment Plans - [Payment Sources](http://docs.encoded.services/concepts/v1/payment-sources): Payment Sources - [Sessions](http://docs.encoded.services/concepts/v1/sessions): Sessions - [Tokens](http://docs.encoded.services/concepts/v1/tokens): Tokens - [Transaction Results](http://docs.encoded.services/concepts/v1/transaction-results): Transaction Results - [Transactions](http://docs.encoded.services/concepts/v1/transactions): Transactions ## Operations - [GET /customers](http://docs.encoded.services/api-reference/v1?operation=get-customers): Returns a list of Customers - [POST /customers](http://docs.encoded.services/api-reference/v1?operation=post-customers): Create new customers. - [GET /customers/{customer_id}](http://docs.encoded.services/api-reference/v1?operation=get-customers-customer_id): Find a customer by ID. - [PUT /customers/{customer_id}](http://docs.encoded.services/api-reference/v1?operation=put-customers-customer_id): Update a customer. - [DELETE /customers/{customer_id}](http://docs.encoded.services/api-reference/v1?operation=delete-customers-customer_id): Delete a customer. - [POST /expresshpp](http://docs.encoded.services/api-reference/v1?operation=post-expresshpp): Creates a hosted payment page from a URL encoded form with all relevant data - [GET /customers/{customer_id}/tokens](http://docs.encoded.services/api-reference/v1?operation=get-customers-customer_id-tokens): Retrieve a list of customer's tokens. - [GET /customers/{customer_id}/tokens/{token_id}](http://docs.encoded.services/api-reference/v1?operation=get-customers-customer_id-tokens-token_id): Retrieve a specific token belonging to a customer. - [PATCH /customers/{customer_id}/tokens/{token_id}](http://docs.encoded.services/api-reference/v1?operation=patch-customers-customer_id-tokens-token_id): Update a token's attributes or expiry date. - [DELETE /customers/{customer_id}/tokens/{token_id}](http://docs.encoded.services/api-reference/v1?operation=delete-customers-customer_id-tokens-token_id): Delete a token - [POST /hpp/config/{access_level}](http://docs.encoded.services/api-reference/v1?operation=post-hpp-config-access_level): Set the user access level-wide configuration of Hosted Payment Pages - [GET /tokens](http://docs.encoded.services/api-reference/v1?operation=get-tokens): Retrieve a list of tokens. - [GET /tokens/{token_id}](http://docs.encoded.services/api-reference/v1?operation=get-tokens-token_id): Retrieve a specific token. - [PATCH /tokens/{token_id}](http://docs.encoded.services/api-reference/v1?operation=patch-tokens-token_id): Update a tokens attributes or expiry date. - [DELETE /tokens/{token_id}](http://docs.encoded.services/api-reference/v1?operation=delete-tokens-token_id): Delete a token - [GET /orders](http://docs.encoded.services/api-reference/v1?operation=get-orders): Returns a list of Orders - [POST /orders](http://docs.encoded.services/api-reference/v1?operation=post-orders): Inserts an array of provided Orders. - [GET /orders/{order_id}](http://docs.encoded.services/api-reference/v1?operation=get-orders-order_id): Find an order by ID. - [GET /orders/{order_id}/transactions](http://docs.encoded.services/api-reference/v1?operation=get-orders-order_id-transactions): Retrieve transactions for an order. - [DELETE /orders/{order_id}/hpp](http://docs.encoded.services/api-reference/v1?operation=delete-orders-order_id-hpp): Deactivate the hosted payment page for an order. - [GET /transactions](http://docs.encoded.services/api-reference/v1?operation=get-transactions): Returns a list of Transactions - [POST /transactions](http://docs.encoded.services/api-reference/v1?operation=post-transactions): Submit a new Transaction - [GET /transactions/{transaction_id}](http://docs.encoded.services/api-reference/v1?operation=get-transactions-transaction_id): Returns a Transaction - [POST /transactions/{transaction_id}/challenge/{challenge_id}](http://docs.encoded.services/api-reference/v1?operation=post-transactions-transaction_id-challenge-challenge_id): Complete a challenge - [POST /sessions](http://docs.encoded.services/api-reference/v1?operation=post-sessions): Start a new Session - [GET /sessions/{session_id}](http://docs.encoded.services/api-reference/v1?operation=get-sessions-session_id): Retrieve a session - [PATCH /sessions/{session_id}/fields/{field_name}](http://docs.encoded.services/api-reference/v1?operation=patch-sessions-session_id-fields-field_name): Update a session field - [GET /issuers/{issuer_iin}](http://docs.encoded.services/api-reference/v1?operation=get-issuers-issuer_iin): Retrieve an issuer and details on whether the resulting issuer is configured to be accepted - [POST /applepay/signing-requests](http://docs.encoded.services/api-reference/v1?operation=post-applepay-signing-requests): Generate an Apple Pay Payment Processing certificate signing request - [POST /applepay/certificates/{certificate_signing_request_id}](http://docs.encoded.services/api-reference/v1?operation=post-applepay-certificates-certificate_signing_request_id): Upload the Apple Pay Payment Processing public key certificate - [POST /plans](http://docs.encoded.services/api-reference/v1?operation=post-plans): Create a new Payment Plan - [GET /plans/{plan_id}](http://docs.encoded.services/api-reference/v1?operation=get-plans-plan_id): Retrieve a payment plan - [PATCH /plans/{plan_id}](http://docs.encoded.services/api-reference/v1?operation=patch-plans-plan_id): Update a payment plan - [DELETE /plans/{plan_id}](http://docs.encoded.services/api-reference/v1?operation=delete-plans-plan_id): Delete a payment plan - [GET /plans/{plan_id}/payments](http://docs.encoded.services/api-reference/v1?operation=get-plans-plan_id-payments): Retrieve all payments associated with a payment plan ## Full Documentation ### APM JavaScript Library URL: http://docs.encoded.services/alternative-payment-methods/v1/apm-javascript-library APM JavaScript Library To aid with your frontend implementation of the available APMs, Encoded provides a JavaScript library. The JavaScript library provides a single simplified methodology for implementing both Apple Pay and Google Pay at the same time. Workflow The workflow for implementing the JavaScript library is as follows: Include the Encoded APM JavaScript library in your checkout page. Generate a browser-safe JWT in your backend server with the scopes required for the API calls used by the library. Create placeholders in the DOM within your checkout page for the APM buttons to be placed. Initialise the JavaScript library in your checkout page. Write event listeners to retrieve JS events sent by the JavaScript library. Once an APM is selected and utilised by the customers, receive the encrypted token provided by the APM. Perform a transaction against the Encoded Gateway API with the retrieved encrypted token. If utilising Apple Pay with this library, you must undertake the actions detailed above relating to the creation of a merchant ID, and generation of the processing certificates. Your implementation manager within Encoded will be able to provide you support in registering with Apple and Google. Library File The javascript module is available at: For SIT, use https://sit.encoded.services/assets/js/apm/apm-uat.min.js. For production, use https://prod.encoded.services/assets/js/apm/apm-prod.min.js. Generate an APM JWT You must then generate a JWT that is safe to send to the browser to initialise the APM JavaScript. The public API does not expose an apm scope; see Authentication for APMs for the supported scope model. If Apple Pay is enabled, merchant-session generation is handled by the JavaScript library during the Apple Pay flow. DOM Placeholders The Encoded APM javascript library will automatically generate the appropriate APM buttons for you. To do this, on initialisation, you will provide a JS DOM Element to the initialisation function. The Encoded APM javascript library will then generate the appropriate buttons and place them within the provided JS DOM Elements. An example of this with your checkout page is provided below:
Initialise the JS Library Within your checkout page you must then initialise the JavaScript Library. Below is an example of this: Payment Form
Here is a detailed overview of the objects and properties mentioned above: enablement PropertyTypeDescription applePaybooleanSets the enablement of Apple Pay within your checkout page. googlePaybooleanSets the enablement of Google Pay within your checkout. merchantConfig PropertyTypeDescription applePayMerchantIdStringThe merchant ID to utilise with Apple Pay. See Create a merchant identifier for more information. unsupportedTypesString[]A list of payment types that are not supported, in all caps. unsupportedNetworksString[]A list of payment card networks that are not supported, in all caps. displayNameStringThe display name for your business shown on the payment sheet once an APM has been selected by the user. The supported card types are automatically identified via your merchant account configuration within the Encoded Gateway. If you wish to reduce this list of supported types when utilising an APM, you can do so here. If you are happy to utilise all supported payment types configured against your merchant account, leave this blank. The supported card networks are automatically identified via your merchant account configuration within the Encoded Gateway. If you wish to reduce this list of supported cards when utilising an APM, you can do so here. If you are happy to utilise all supported card networks configured against your merchant account, leave this blank. payment PropertyTypeDescription amountStringThe payment amount as a string. currencyStringThe three digit currency code for the payment. countryCodeStringThe two digit country code. descriptionStringA description of the order to show within the payment sheet. itemsItem[]An array of the items that make up the order and should be shown within the payment sheet. Item PropertyTypeDescription labelStringA descriptive label of the order item. amountStringThe payment amount as a string. buttonStyling PropertyTypeDescription colourStringThe button colour to use. One of black or white. typeStringThe type of button to use. This provides an APM button with a customised message once generated and displayed. localeStringThe locale for the button. widthnumericThe width of the payment button in pixels. A sensible default is 240. heightnumericThe height of the payment button in pixels. A sensible default is 40. cornerRadiusnumericThe corner radius of the payment button in pixels. A sensible default is 4. Supported type values: "book", "buy", "checkout", "donate", "order", "payment", "subscribe". domContainers PropertyTypeDescription applePayHTMLElementAn HTMLElement from the DOM to place the Apple Pay button once generated. googlePayHTMLElementAn HTMLElement from the DOM to place the Google Pay button once generated. listeners PropertyTypeDescription paymentSheetOpenedfunctionReceives a JS event callback once the payment sheet has been opened. paymentSheetClosedfunctionReceives a JS event callback once the payment sheet has been closed. paymentSheetFailedfunctionReceives a JS event callback if a payment sheet has failed. paymentSheetSuccessfulfunctionReceives a JS event callback once the payment has been authorised by the user. Events The event functions provided will be called once an associated event has occurred within a payment button. You will receive an Event object which will contain: PropertyTypeDescription typeStringThe event type. One of the values below. "APM.APPLE_PAY.PAYMENT_SHEET_OPEN", "APM.APPLE_PAY.PAYMENT_SHEET_CLOSED", "APM.APPLE_PAY.PAYMENT_SHEET_FAILED", "APM.APPLE_PAY.PAYMENT_SHEET_SUCCESSFUL", "APM.GOOGLE_PAY.PAYMENT_SHEET_OPEN", "APM.GOOGLE_PAY.PAYMENT_SHEET_CLOSED", "APM.GOOGLE_PAY.PAYMENT_SHEET_FAILED", "APM.GOOGLE_PAY.PAYMENT_SHEET_SUCCESSFUL", token String If the event type is "APM.APPLE_PAY.PAYMENT_SHEET_SUCCESSFUL" or "APM.GOOGLE_PAY.PAYMENT_SHEET_SUCCESSFUL", the encrypted token received from the APM. Processing the Transaction Once an encrypted token has been received, you can then go ahead and process the transaction. For Apple Pay, please see here for details on how to do this. For Google Pay, please see here for details on how to do this. ### Apple Pay URL: http://docs.encoded.services/alternative-payment-methods/v1/apple-pay Apple Pay Apple Pay lets cardholders pay with cards saved in Apple Wallet. In the Gateway API, Apple Pay is submitted as an apple_pay payment source. Your checkout collects the Apple Pay payment token, base64-encodes it, and sends it to the Gateway in a transaction request. You can implement Apple Pay in two ways: ApproachUse when Encoded APM JavaScript LibraryYou want Encoded to provide a browser integration that handles Apple Pay and Google Pay with one integration pattern. Direct Apple Pay JS or PassKit integrationYou already have your own Apple Pay checkout and only need to submit the resulting payment token to the Gateway. Setup Overview Before you can process Apple Pay payments, complete the Apple Pay setup for your merchant account. StepWherePurpose 1Apple DeveloperCreate an Apple Pay merchant identifier. 2Gateway APIGenerate a certificate signing request for the merchant identifier. 3Apple DeveloperCreate the Apple Pay Payment Processing Certificate from the CSR. 4Gateway APIUpload the payment processing certificate to Encoded. 5Apple DeveloperFor Apple Pay on the web, register and verify your merchant domain. 6CheckoutConfigure Apple Pay JS, PassKit, or the Encoded APM JavaScript Library. Apple requires an Account Holder or Admin role for the merchant identifier, certificate, and web-domain setup. Create a Merchant Identifier A merchant identifier uniquely identifies you to Apple Pay as a merchant. It does not expire and can be reused across multiple apps or websites where that is appropriate for your Apple Pay setup. In the Apple Developer account, open **Certificates, Identifiers & Profiles**, add a new **Merchant ID**, then register a descriptive identifier. Use a name that makes the owning environment clear, for example: merchant.services.encoded.prod Generate a Certificate Signing Request Generate the CSR through the Gateway API using the merchant identifier created in Apple Developer. POST /applepay/signing-requests { "merchantIdentifier": "merchant.services.encoded.prod" } The response contains a CSR and a links.self URL. Save the CSR content as a .certSigningRequest file and upload it to Apple when creating the Apple Pay Payment Processing Certificate. { "id": "4fefad24-a6ce-41ba-a222-c823a31e7961", "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIHZMIGBAgEAMB8xEDAOBgNVBAoMB0VuY29kZWQx...\n-----END CERTIFICATE REQUEST-----", "links": { "self": "https://sit.encoded.services/api/v1/applepay/certificates/4fefad24-a6ce-41ba-a222-c823a31e7961" } } Keep the id or links.self value. You will use it to upload the certificate back to Encoded. Create the Payment Processing Certificate In Apple Developer, open the merchant identifier and create an **Apple Pay Payment Processing Certificate**. Make sure you are creating the payment processing certificate, not the Merchant Identity Certificate. Upload the CSR generated by the Gateway API, then download the certificate from Apple. Apple downloads the certificate as a .cer file. Upload the Certificate to Encoded The payment processing certificate must be uploaded to Encoded in PEM format. If Apple provides the certificate in DER format, convert it to PEM before upload. openssl x509 -inform der -in apple_pay.cer -out apple_pay.pem Upload the PEM certificate to the endpoint returned by the signing-request response. POST /applepay/certificates/4fefad24-a6ce-41ba-a222-c823a31e7961 { "certificate": "-----BEGIN CERTIFICATE-----\nMIIEezCCBCGgAwIBAgIIDM6aT...\n-----END CERTIFICATE-----" } Configure Apple Pay on the Web For Apple Pay on the web, Apple also requires merchant domain registration and verification. In Apple Developer, add each fully qualified domain that will present Apple Pay, download the verification file, host it at the path Apple specifies, then complete verification. If you are building your own Apple Pay JS integration, your backend also needs to perform merchant validation with Apple using a Merchant Identity Certificate. If you use the Encoded APM JavaScript Library, merchant-session generation is handled by the library during the Apple Pay flow once Apple Pay has been configured for your account. Configure the Payment Request When creating the Apple Pay payment request, use networks and capabilities supported by your Encoded configuration. const paymentRequest = { countryCode: "GB", currencyCode: "GBP", supportedNetworks: ["amex", "discover", "masterCard", "visa"], merchantCapabilities: ["supports3DS"], total: { label: "Example Merchant", amount: "20.54" } } You can also request billing contact, shipping contact, and shipping method data from Apple Pay. If you use that data in the transaction, map it into the Gateway request fields such as billingCustomer and shippingCustomer. Receive the Apple Pay Token When the cardholder authorises payment, Apple Pay returns an ApplePayPayment object to your checkout. Send the payment token to your backend from the ApplePaySession.onpaymentauthorized handler. session.onpaymentauthorized = async event => { const applePayToken = event.payment.token await submitApplePayToken(applePayToken) } Base64-encode the serialized token before sending it to the Gateway API. const gatewayToken = btoa(JSON.stringify(applePayToken)) The token can contain encrypted payment data, payment method information, and a transaction identifier. Do not modify the token contents before encoding it. Submit the Payment Send the base64-encoded Apple Pay token as an apple_pay source in a standard transaction request. POST /transactions { "object": "transaction.request", "action": "pay", "ref": "APPLE-PAY-10001", "amount": 20.54, "currency": "GBP", "source": { "object": "source", "apple_pay": { "object": "apple_pay", "token": "eyJwYXltZW50RGF0YSI6eyJkYXRhIjoiLi4uIn0sInBheW1lbnRNZXRob2QiOnsibmV0d29yayI6Ik1hc3RlckNhcmQiLCJ0eXBlIjoiY3JlZGl0In19" } } } The Gateway returns a normal transaction response. Check the final transaction result before fulfilling the order. Implementation Checklist Create and configure the Apple Pay merchant identifier before going live. Upload the Apple Pay Payment Processing Certificate to Encoded. Register and verify each web domain that will present Apple Pay. Use the Encoded APM JavaScript Library or perform Apple merchant validation from your backend. Base64-encode the Apple Pay token exactly as received from Apple Pay. Submit the token as an apple_pay payment source. Fulfil only after the Gateway transaction result is accepted. Platform Documentation Configure Apple Pay Configure Apple Pay on the web Apple Pay on the Web ### Google Pay URL: http://docs.encoded.services/alternative-payment-methods/v1/google-pay Google Pay Google Pay lets cardholders pay with cards saved to their Google Account. In the Gateway API, Google Pay is submitted as a google_pay payment source. Your checkout requests a Google Pay payment token, base64-encodes it, and sends it to the Gateway in a transaction request. You can implement Google Pay in two ways: ApproachUse when Encoded APM JavaScript LibraryYou want Encoded to provide a browser integration that handles Apple Pay and Google Pay with one integration pattern. Direct Google Pay API integrationYou already have your own Google Pay checkout and only need to submit the resulting payment token to the Gateway. Setup Overview Before going live, make sure you have: RequirementNotes Encoded Client IDUsed as the gatewayMerchantId in the Google Pay tokenization configuration. Google Pay merchant profileRequired for production Google Pay processing. Supported card networksEncoded currently supports AMEX, MASTERCARD, and VISA for Google Pay. Supported authentication methodsEncoded supports PAN_ONLY and CRYPTOGRAM_3DS. HTTPS checkoutRequired for production browser payment flows. Use Google Pay's TEST environment while developing and switch to PRODUCTION only after Google Pay production access and domain approval are complete. Configure Google Pay When requesting a payment token for Encoded, set the tokenization type to PAYMENT_GATEWAY, the gateway to encoded, and the gatewayMerchantId to your Encoded Client ID. const tokenizationSpecification = { type: "PAYMENT_GATEWAY", parameters: { gateway: "encoded", gatewayMerchantId: "ENCODED_GATEWAY_CLIENT_ID" } } Define the card networks and authentication methods you accept. const allowedCardNetworks = ["AMEX", "MASTERCARD", "VISA"] const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"] CRYPTOGRAM_3DS indicates a device token authenticated by Google Pay. PAN_ONLY can return a card PAN-style token, so the resulting Gateway transaction may still require a 3-D Secure challenge depending on issuer, merchant account, and transaction risk. Build a Payment Data Request Include the tokenization specification in the CARD payment method used by the Google Pay payment data request. const baseCardPaymentMethod = { type: "CARD", parameters: { allowedAuthMethods: allowedCardAuthMethods, allowedCardNetworks: allowedCardNetworks } } const cardPaymentMethod = { ...baseCardPaymentMethod, tokenizationSpecification } const paymentDataRequest = { apiVersion: 2, apiVersionMinor: 0, merchantInfo: { merchantName: "Example Merchant" }, allowedPaymentMethods: [cardPaymentMethod], transactionInfo: { totalPriceStatus: "FINAL", totalPrice: "20.54", currencyCode: "GBP", countryCode: "GB" } } For production, Google may require merchantInfo.merchantId as well as the merchant name. Use the merchant ID issued through Google Pay production access. Request the Payment Token When the customer confirms Google Pay, the Google Pay API returns a PaymentData object. The Gateway needs the token at: paymentData.paymentMethodData.tokenizationData.token The token value is a JSON string returned by Google Pay. Base64-encode that token string exactly as returned before sending it to the Gateway. const googlePayToken = paymentData.paymentMethodData.tokenizationData.token const gatewayToken = btoa(googlePayToken) If you request billing address, shipping address, or email data from Google Pay, map those values into Gateway fields such as billingCustomer and shippingCustomer when you create the transaction. Submit the Payment Send the base64-encoded Google Pay token as a google_pay source in a standard transaction request. POST /transactions { "object": "transaction.request", "action": "pay", "ref": "GOOGLE-PAY-10001", "amount": 20.54, "currency": "GBP", "source": { "object": "source", "google_pay": { "object": "google_pay", "token": "eyJwcm90b2NvbFZlcnNpb24iOiJFQ3YyIiwic2lnbmF0dXJlIjoiLi4uIiwic2lnbmVkTWVzc2FnZSI6Ii4uLiJ9" } } } The Gateway returns a normal transaction response. Check the final transaction result before fulfilling the order. 3-D Secure Handling If you allow PAN_ONLY, the transaction may return challenged after POST /transactions. In that case, complete the 3-D Secure challenge before fulfilling the order. See EMV 3-D Secure for the challenge flow. Implementation Checklist Configure Google Pay with gateway: "encoded". Use your Encoded Client ID as gatewayMerchantId. Use only card networks and authentication methods enabled for your Encoded account. Base64-encode paymentMethodData.tokenizationData.token exactly as returned by Google Pay. Submit the token as a google_pay payment source. Handle a possible 3-D Secure challenge when using PAN_ONLY. Fulfil only after the Gateway transaction result is accepted. Platform Documentation Google Pay API tutorial Google Pay request objects ### API Object Model URL: http://docs.encoded.services/concepts/v1/api-object-model API Object Model The Gateway API is built around a small set of core objects. Once you understand how these objects connect, the payment flows and API reference become much easier to use. The Core Model ConceptWhat it isWhy it matters customerThe person, organisation, or account holder.Lets you group payment activity and retrieve stored cards. orderThe commercial context for a payment journey.Required for Hosted Payment Pages and useful for grouping related transactions. transaction.requestThe instruction you send to take or manage payment.Defines action, amount, currency, source, customer, and routing data. transactionThe payment attempt or payment action created by the API.Holds status, challenge, response, and reconciliation links. sourceThe payment credential or reference used by a transaction.Determines whether the transaction uses a card, token, session, previous transaction, or wallet. tokenA stored card reference.Allows future payments without recollecting full card details. sessionTemporary Hosted Payment Fields data.Allows hosted field collection while your backend submits a transaction using a session ID. resultFinal transaction outcome.Tells your system whether to fulfil, retry, recover, or investigate. Common Object Relationships RelationshipMeaning order.billingCustomerThe customer paying for the order. Can be a new customer or a reference to an existing one. order.hppHosted Payment Page settings used to generate links.hpp.v1. transaction.request.orderThe order a direct transaction belongs to, where used. transaction.request.sourceThe single source used for the transaction. transaction.request.sourcesMultiple source components used together. transaction.response.tokenA token created as part of a tokenising transaction. customer.links.tokensThe customer's stored card tokens. session.sessionFieldsHosted Payment Fields field state and iframe links. Three Ways to Take Payment PatternMain objectsUse when Direct transactiontransaction.request, source, transactionYour backend can submit the payment source directly, such as MOTO. Hosted Payment Pageorder, hpp, transactionYou want Encoded to host the checkout page. Hosted Payment Fieldssession, source.session, transactionYou want your own checkout layout with hosted card fields. Object IDs and References Most resources have two identifiers: IdentifierPurpose idAPI-generated UUID. Use this for precise API calls. refYour own reference. Use this for reconciliation and search. Store both. Use id when calling resource-specific endpoints, and use ref to connect API objects to your own orders, accounts, invoices, or cases. Attributes Several objects support attributes. This is a flexible metadata object for values that matter to your implementation but are not standard API fields. Attributes can contain strings, numbers, booleans, arrays, and nested objects. Good uses for attributes include: Internal account identifiers. Customer flags. Reporting categories. Downstream reconciliation data. Product or channel metadata. Do not put sensitive card data in attributes. How to Read Any Flow Most payment flows follow the same structure: Create or identify context, such as a customer, order, token, or session. Submit a transaction.request or open a hosted payment page. Watch the returned transaction.status. Complete any challenge. Read transaction.response.result. Reconcile with your own system using id, ref, and attributes. The Payment Flow pages walk through concrete scenarios. The Concept pages explain what each object is and how it behaves. ### Authentication URL: http://docs.encoded.services/concepts/v1/authentication Authentication The Gateway API uses OAuth 2.0 client credentials. Your backend exchanges a client_id and client_secret for a bearer access token, then sends that token on API requests. Do not expose your normal client secret or normal API access token in browser code. Browser integrations such as Hosted Payment Fields should use a limited token scoped to a specific payment session. Token Endpoint The authentication server is environment-specific. https://[env].encoded.services/auth/oauth/token Use the same environment as the API request you intend to make. For example, sandbox credentials should be used against the sandbox environment, not production. Getting an Access Token Send the client credentials using HTTP Basic authentication and request the client_credentials grant. POST /auth/oauth/token Authorization: Basic {base64(client_id:client_secret)} Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&scope=read write The response contains an access_token, token_type, expiry information, and the granted scope. { "access_token": "{jwt}", "token_type": "bearer", "expires_in": 21599, "scope": [ "read", "write" ] } Calling the API Send the token as a bearer token. GET /api/v1/transactions/{transaction_id} Authorization: Bearer {access_token} Scopes The OpenAPI specification declares the scopes required by each endpoint. ScopePurpose readAllows read operations such as GET /transactions/{transaction_id}. writeAllows modifying operations such as POST, PUT, PATCH, and DELETE. session_limited_readAllows browser-safe access to one payment session without exposing sensitive card data. Read-only API requests normally need read. Modifying API requests normally need both read and write. Session retrieval and session field updates used by Hosted Payment Fields should use session_limited_read. Session-Limited Tokens Hosted Payment Fields runs in the browser and therefore cannot use your normal API token. Create a token with session_limited_read and bind it to the session using payment_session_id. POST /auth/oauth/token Authorization: Basic {base64(client_id:client_secret)} Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&scope=session_limited_read&payment_session_id=10b3ca21-d9fd-4030-b5f5-fb45f220a6dd Use this token only to initialise the Hosted Payment Fields JavaScript for the matching session. Backend and Browser Responsibilities LocationShould doShould not do BackendStore client credentials, request normal API tokens, create sessions, submit transactions.Send the client secret to the browser. BrowserUse hosted components and session-limited tokens.Handle full card data or normal API tokens. Common Authentication Failures SymptomLikely cause 401 from APIMissing, expired, malformed, or environment-mismatched bearer token. 403 from APIToken exists but does not have the required scope. Hosted Payment Fields cannot initialiseToken is not session_limited_read, is not bound to the session, or references the wrong payment_session_id. Sandbox credentials fail in productionCredentials are environment-specific. ### Custom Domains URL: http://docs.encoded.services/concepts/v1/custom-domains Custom Domains The Gateway API and hosted payment experiences can be served under your own domain names. This is normally used for hosted payment links, PayByLink, and any customer-facing payment pages where brand consistency helps the customer trust the journey. Custom domains are configured operationally with Encoded. They are not created or changed through the public Gateway API. When to Use a Custom Domain Use a custom domain when customers will see a payment URL, hosted page, or payment link and you want that URL to sit under your own domain. Common examples: EnvironmentExample domainTypical use Productionpay.example.comLive hosted payment pages and payment links. Testingpay-test.example.comSandbox testing and user acceptance testing. You can configure only a production domain, or you can configure separate domains for production and testing. Separate domains are recommended when UAT users need to test the exact customer-facing experience before launch. URL Format Once configured, API and hosted-payment URLs use your domain instead of the standard environment host. https://[your-domain]/api/[version]/ For example: https://pay.example.com/api/v1/ Setup Flow StepOwnerWhat happens 1. Choose domainsYouSelect one subdomain per environment, such as pay.example.com and pay-test.example.com. 2. Request setupYouSend the chosen domains to your implementation contact. 3. Generate CSRsEncodedEncoded generates a Certificate Signing Request for each required domain. 4. Issue certificatesYouUse your certificate authority or SSL vendor to issue certificates from the CSRs. 5. Return certificatesYouSend the issued certificates back to your implementation contact. 6. Board certificatesEncodedEncoded installs the certificates and confirms when DNS can be updated. 7. Update DNSYouCreate or update the CNAME records for the custom domains. 8. VerifyYou and EncodedConfirm that the custom domain resolves and serves the expected API or hosted payment experience. DNS After the certificates have been boarded, update your DNS so each custom domain points to the Encoded Gateway target. Record typeNameTarget CNAMEYour chosen subdomain, such as pay.example.comcname.encoded.services Your DNS provider may ask for only the subdomain label in the Name field. For example, for pay.example.com, the record name may be pay. Go-Live Checks Before using a custom domain in production: Confirm the domain resolves to the CNAME target. Confirm the TLS certificate is valid for the custom domain. Confirm sandbox and production domains point to the correct environments. Confirm hosted payment pages, PayByLink URLs, return URLs and notification callbacks are using the intended environment. Confirm your backend uses the matching OAuth credentials for the custom-domain API base URL. If a hosted payment URL or callback crosses environments, reconciliation can fail or the wrong environment may be queried for the final transaction. ### Customers URL: http://docs.encoded.services/concepts/v1/customers Customers A customer represents the payer or account holder in your integration. Customers can be attached to orders, transactions, and tokens so that payment activity can be searched, reconciled, and reused across future journeys. Customers are optional for a simple one-off transaction, but they become important when you need stored cards, Hosted Payment Pages with token display, customer-level search, or repeat payments. How Customers Are Created MethodUse when POST /customersYou want to create or manage customer records explicitly before taking payments. Inline on an orderThe order is the first time you receive customer details. Inline on a transactionThe transaction is a one-off payment but still needs billing customer details. Reference by idThe customer already exists and should be reused. When creating a customer directly, the request body is an array of customer objects. If one object in the array is invalid, none of the customers are created. Core Fields FieldPurpose objectMust be customer. idAPI-generated UUID returned after creation. refYour customer reference. Searchable, but not unique by default. title, forename, surname, dateOfBirthPersonal customer details. organisationOrganisation details for business customers. contactAddress, email, and phone details. attributesYour own structured customer metadata. links.tokensLink to tokens associated with this customer. On creation, object is required and at least one other meaningful field must be populated. References and IDs Store the API-generated id once a customer has been created. Use id for precise API operations such as GET /customers/{customer_id} and PUT /customers/{customer_id}. Use ref for your own customer, account, or debtor identifier. ref can be used for filtering, but it is not guaranteed to be unique unless your implementation has been configured that way. Customer Attributes attributes is a flexible object for metadata that is specific to your implementation. It can contain strings, numbers, booleans, arrays, and nested objects. { "attributes": { "account": { "accountNumber": "100001234", "paymentAmount": 800.00, "arrearsAmount": 100.00, "tokenisationEnabled": true, "creditCardsEnabled": true, "defaultToken": "2156d9ef-a16a-4e43-b5d2-bfdcb6c9afae" } } } Attributes can also hold arrays when one customer has multiple related accounts or agreements. Searching Customers GET /customers supports paging and filtering. Use ref for reference searches, or filter by custom attributes when your implementation needs to find a customer by an account number or another nested value. GET /customers?ref=CUST-10001 GET /customers?attributes.account.accountNumber=100001234 Updating and Deleting Customers Use PUT /customers/{customer_id} to update a customer. Treat this as replacing the customer representation with the submitted object, so include the fields you want to retain. Use DELETE /customers/{customer_id} only when the customer should be removed. Tokens associated with that customer are also removed, so do not delete a customer if stored card references still need to be used. Customers and Tokens Tokens are easiest to manage when they are linked to a customer. Use GET /customers/{customer_id}/tokens to retrieve the stored cards available for that customer. Hosted Payment Pages can also use the billing customer to display existing tokens and offer tokenisation. ### EMV 3-D Secure URL: http://docs.encoded.services/concepts/v1/emv-3d-secure EMV 3-D Secure EMV 3-D Secure, often referred to as 3DS2, adds cardholder authentication to an e-commerce card transaction. It is used to reduce fraud risk by allowing the issuer to assess the transaction and, when needed, ask the cardholder to complete an authentication challenge. This page explains the concepts and data returned by the Gateway API during a 3-D Secure flow. For a step-by-step implementation, see ECOM Payment with 3DS2 Challenge. Where 3-D Secure Fits 3-D Secure applies to e-commerce card payments. The Gateway API determines the 3-D Secure version and behaviour from the merchant account configuration, the transaction request, and the payment source. To request 3-D Secure on a direct API card transaction: RequirementValue Platform typeplatformType must be ecom. 3-D Secure flagthreeDSecure must be true. Merchant accountThe selected merchant account must be configured for e-commerce and 3-D Secure. Payment sourceThe source must be eligible for 3-D Secure authentication. The issuer can complete authentication without customer interaction, known as a frictionless flow, or require a browser challenge. Transaction States Your integration should treat 3-D Secure as part of the transaction lifecycle. The initial POST /transactions response can be final, or it can tell you that further action is required. Transaction statusMeaningIntegration action processedThe transaction has reached a final processing state.Check transaction.response before fulfilling the order. challengedA 3-D Secure challenge must be completed.Send the cardholder to the ACS, then submit the challenge response. processingThe transaction is still being processed asynchronously.Poll GET /transactions/{transaction_id} or wait for notification callbacks. Do not fulfil an order while the transaction is challenged or processing. Challenge Object When a challenge is required, the transaction includes a transaction.challenge object. The current challenge is always returned in transaction.challenge; previous challenges may be returned in transaction.challenges. { "object": "transaction", "id": "4b502950-8801-4112-ba15-88f8eb280525", "status": "challenged", "challenge": { "object": "transaction.challenge", "id": "1", "threeDSecure": { "object": "transaction.challenge.threeDSecure", "v2": { "object": "transaction.challenge.threeDSecure.v2", "acsUrl": "https://sit.encoded.services/emv3ds/acs/init/4b502950-8801-4112-ba15-88f8eb280525" } }, "links": { "self": "https://sit.encoded.services/api/v1/transactions/4b502950-8801-4112-ba15-88f8eb280525/challenge/1" } }, "links": { "self": "https://sit.encoded.services/api/v1/transactions/4b502950-8801-4112-ba15-88f8eb280525" } } FieldMeaning challenge.idThe identifier for the challenge on this transaction. challenge.threeDSecure.v2.acsUrlThe Gateway API ACS URL that the cardholder's browser must POST to. challenge.links.selfThe API endpoint your backend calls after the ACS posts the authentication result to your return URL. The ACS URL is a browser destination. The challenge link is a server-to-server API endpoint. Browser Handoff to the ACS To start the challenge, POST the cardholder's browser to challenge.threeDSecure.v2.acsUrl. Include a returnUrl so the ACS can post the authentication result back to your application.
In a live checkout, this form is normally submitted automatically or rendered inside your challenge container. Challenge Window Size You can send challengeWindowSize to indicate the size of the challenge container you intend to display. ValueIntended challenge window 01250 x 400 02390 x 400 03500 x 600 04600 x 400 05Full screen ACS Callback Fields When authentication completes, the ACS posts the authentication result to your returnUrl. Capture the posted fields and pass them to the challenge endpoint. FieldMeaning dsTransIdUnique ID for the directory server transaction. authenticationValueAuthentication value returned by the ACS. eciElectronic commerce indicator. transStatusStatus of the authentication attempt. messageVersion3DS2 message version used for the challenge. The ACS callback is not the final payment result. It only gives your application the authentication data needed to continue the transaction. Challenge Response Submit the ACS callback fields to the endpoint from challenge.links.self. POST /transactions/4b502950-8801-4112-ba15-88f8eb280525/challenge/1 { "object": "transaction.challenge.response", "threeDSecure": { "object": "transaction.challenge.response.threeDSecure", "v2": { "object": "transaction.challenge.response.threeDSecure.v2", "dsTransId": "8b167401-2c2e-4f5c-80e0-6dcbf68737cd", "authenticationValue": "MTIzNDU2Nzg5MDEyMzQ1OTcyODM=", "eci": "05", "transStatus": "Y", "messageVersion": "2.2.0" } } } The challenge endpoint returns an updated transaction object. If the transaction is processed, inspect transaction.response to decide whether to fulfil the order. Multiple Challenges Some transactions can return another challenged status after you submit a challenge response. This can happen if authentication is escalated or if another challenge is required before processing can continue. When this happens, repeat the challenge loop using the latest transaction.challenge object. Continue until the transaction reaches a final processed state, or until your integration decides to time out and recover the payment state later. Implementation Checklist Request 3-D Secure only for eligible e-commerce transactions. Treat acsUrl as a browser POST target, not a backend API endpoint. Treat challenge.links.self as the backend endpoint used to continue the transaction. Persist enough transaction context to match the ACS callback to the original order. Do not fulfil from the ACS callback alone. Fulfil only after the final transaction response is accepted. ### Environments and URLs URL: http://docs.encoded.services/concepts/v1/environments-and-urls Environments and URLs Every API request is made against a specific environment and API version. Keep credentials, base URLs, callbacks, and hosted-page URLs aligned to the same environment. OpenAPI Specification The OpenAPI specification for the active brand is available at: https://sit.encoded.services/api/v1/docs Use the API Reference in this portal for field-level documentation, request builders, response schemas, and endpoint-specific scopes. Base URL The API base URL follows this pattern: https://[env].encoded.services/api/[version]/ The following environments are currently available: prod Production environment for live transacting. sit Testing environment for implementors to test their implementation and perform test transactions. The following versions are currently available: v1 Environment Rules RuleWhy it matters Use sandbox credentials only with sandbox URLs.Credentials are environment-specific. Use production credentials only with production URLs.Production requests can move real money. Keep API callbacks on the same environment journey.Hosted Payment Pages, PayByLink, 3DS, and notifications must reconcile to the environment that created the object. Store returned API IDs per environment.A sandbox transaction.id is not a production transaction. Hosted URLs Some API responses contain URLs outside /api/v1, such as: URL typeExample context /hpp/v1/...Hosted Payment Page links returned at links.hpp.v1. /hpf/v1/...Hosted Payment Fields iframe URLs on session fields. /emv3ds/acs/...3-D Secure challenge URLs. Treat these as returned links. Do not build them manually unless the documentation explicitly tells you to. Custom Domains The Gateway API and hosted payment experiences can be used under custom domains for each environment. This improves customer confidence and brand consistency for hosted payment links. A typical custom-domain setup uses separate subdomains for production and testing. EnvironmentExample Productionpay.example.com Testingpay-test.example.com After agreeing the domains, Encoded generates certificate signing requests. You generate certificates using those CSRs, return the certificates to your implementation contact, and then point DNS at the provided CNAME target. Changelogs Changelogs for the Encoded Gateway API and associated services can be found at: https://wiki.encoded.support/changelogs ### Hosted Payment Fields URL: http://docs.encoded.services/concepts/v1/hosted-payment-fields Hosted Payment Fields Hosted Payment Fields let you keep your own checkout layout while individual card input fields are hosted securely by Encoded. Each sensitive field is rendered in its own iframe, so card data is collected outside your page while the checkout can still match your user interface. This is useful when a full Hosted Payment Page is too detached from your checkout, but you still want to avoid handling raw card data directly. How They Fit Together ComponentPurpose Payment sessionServer-created container for hosted card fields. Session fieldA single hosted field, such as pan, expiryDate, or securityCode. Session-limited tokenBrowser-safe OAuth token using session_limited_read and bound to one session. Hosted Payment Fields JavaScriptRenders iframes and syncs field state to the session. source.sessionTransaction payment source that uses the collected session data. Security Boundary Your backend creates the session and later submits the transaction. Your browser code receives only a session-limited token with the session_limited_read scope and never receives full card data or normal API credentials. When to Use It Use Hosted Payment Fields whenPrefer Hosted Payment Pages when Your checkout layout must remain under your control.You want Encoded to host the full checkout journey. You need hosted card fields embedded into an existing form.You want the simplest redirect or iframe hosted checkout. Your backend can coordinate sessions and transactions.You want fewer moving parts in your own frontend. See Hosted Payment Fields Session for the implementation flow. ### Hosted Payment Pages URL: http://docs.encoded.services/concepts/v1/hosted-payment-pages Hosted Payment Pages Hosted Payment Pages let Encoded host the checkout form while your system creates and owns the order. The customer is sent to a hosted page that can display the order, collect payment details, present available payment methods, process the transaction, and return the customer to your site. Because the sensitive payment form is hosted by Encoded, this approach can help keep the merchant integration eligible for SAQ-A PCI scope, provided the rest of the implementation follows the required PCI rules. How They Fit Together Resource or settingPurpose orderHolds the amount, currency, description, customer details and hosted-page configuration. hppConfiguration on the order that controls the hosted page. links.hpp.v1URL returned by the API for the hosted checkout. hpp.returnUrlBrowser destination after the payment attempt. GET /orders/{order_id}/transactionsServer-side source of truth for payment reconciliation. Common Configuration FieldPurpose hpp.actionTransaction action, usually pay or authorise. hpp.returnUrlWhere the browser is returned after payment. hpp.tokensShows stored cards or offers tokenisation. hpp.viewControls what order and custom details are displayed. hpp.deliveryDelivery settings used by PayByLink. Fulfilment Rule Do not treat a browser return as proof of payment. Use the order or transaction API to confirm that the final transaction is processed and accepted before fulfilment. See Hosted Payment Page with an Order for the implementation flow. ### Merchant Accounts URL: http://docs.encoded.services/concepts/v1/merchant-accounts Merchant Accounts A merchant account is the acquiring account used to process card and alternative payment method transactions. It is normally provided by an acquirer and is configured operationally before you start processing. The Gateway API is acquirer agnostic. Your implementation can process through merchant accounts connected to different acquirers without changing the shape of your transaction requests. How Merchant Accounts Are Used Merchant account selection normally happens through payment orchestration rules configured in the Gateway. Those rules can route transactions based on your commercial and operational requirements, such as acquirer availability, payment method, currency, acceptance performance, or cost. Merchant account setup and routing rule configuration are not public API resources in the current OpenAPI specification. Work with your Implementation Manager when merchant accounts need to be added, changed, or routed differently. Explicit Merchant Account Selection Most integrations should let the Gateway choose the merchant account. In some implementations, you may be given specific merchant account IDs and told to send them in the request. FieldContext transactionRequest.merchantAccountIdOverrides automated merchant account selection for direct transaction requests. order.hpp.merchantAccountIdOverrides automated merchant account selection for Hosted Payment Page transactions generated from an order. Use these fields only when your implementation has been configured for explicit selection and you have been given valid IDs. Common Mistakes Do not invent merchant account IDs in sandbox. They must match configured accounts. Do not assume a merchant account endpoint exists in the public API. Merchant account administration is operational. Do not use explicit merchant account selection as a substitute for orchestration rules unless your Implementation Manager has confirmed that pattern. ### Notification Callbacks URL: http://docs.encoded.services/concepts/v1/notification-callbacks Notification Callbacks Notification callbacks allow the Gateway to tell your system when an asynchronous payment event has completed. They are especially useful for journeys where the final transaction result may not be available at the point your original request returns, such as hosted checkout, PayByLink, Hosted Payment Fields, 3-D Secure, or processor flows that remain in processing for a short period. Callbacks complement API polling. Your integration should still be able to retrieve the transaction or order through the API and should treat the API resource as the source of truth before fulfilment. Configuration A notification callback URL can be configured at account level or user level. The callback is sent to the configured endpoint as an HTTP POST with a JSON body. Ask your Encoded implementation contact or service desk to configure the callback URL for each environment. Keep sandbox and production callback URLs separate, and make sure the callback endpoint is reachable from the environment that will send the notification. Your implementation contact will also provide the HMAC key used to validate callback signatures. Notification Payload The callback body contains a notification object. The payload is usually the object that caused the callback, such as a processed transaction. { "object": "notification", "id": "9799936c-27be-432d-be84-e1249c7cac9e", "creationDate": "2021-12-17T10:53:08Z", "user": "Encoded1", "environment": "prod", "payload": { "object": "transaction", "id": "c7b66223-927d-41fd-afcc-a006d4cecb06", "amount": 10.00, "currency": "GBP", "response": { "result": { "resultType": "accepted" } } }, "signature": "OTA4ZTE1YjNkMzhjNzc4ODUyNTZkOGQ0ZDI5YjgzOTMzYjQ3MTQzM2EwYzNjZWFjZWUxZDEzOTdmYmJhM2FhMQ==" } Core Fields FieldPurpose objectAlways notification. idUnique notification ID. Store this to make callback handling idempotent. creationDateDate and time the notification was created. userUser context that generated the callback. environmentEnvironment where the action occurred, such as sit or prod. payloadEvent payload, usually the processed object. For transaction callbacks, this is the transaction. signatureBase64-encoded SHA256 HMAC signature used to validate the callback. Transaction Notifications Transaction callbacks are sent when a transaction has been processed. The payload is the transaction object, so your integration can read the final status and response.result. For fulfilment decisions, check: FieldExpected for successful payment payload.statusprocessed payload.response.result.resultTypeaccepted Do not fulfil from the presence of a callback alone. Validate the signature, confirm that the callback belongs to the expected environment, then use the transaction result or retrieve the transaction from the API before final fulfilment. Signature Validation The notification signature helps verify that the callback came from Encoded and that the key transaction fields were not tampered with. For transaction notifications, build the signature input string from these fields: notification_id:user:environment:transaction_id:amount_in_decimal:currency:resultType Using the example payload above, the input string is: 9799936c-27be-432d-be84-e1249c7cac9e:Encoded1:prod:c7b66223-927d-41fd-afcc-a006d4cecb06:10.00:GBP:accepted Then: Calculate a SHA256 HMAC of the input string using the HMAC key provided for your environment. Convert the HMAC bytes to a lowercase hexadecimal string. Base64 encode that hexadecimal string. Compare your computed Base64 value with notification.signature. Reject the notification if the values do not match. The amount must be represented in decimal form exactly as expected by the signature algorithm. Keep formatting consistent, including decimal places. Worked Signature Example Use this example to confirm that your HMAC implementation produces the same signature. Example HMAC key: secret Example notification payload: { "object": "notification", "id": "9799936c-27be-432d-be84-e1249c7cac9e", "creationDate": "2021-12-17T10:53:08Z", "user": "Encoded1", "environment": "prod", "payload": { "object": "transaction", "id": "c7b66223-927d-41fd-afcc-a006d4cecb06", "amount": 10.00, "currency": "GBP", "response": { "result": { "resultType": "accepted" } } }, "signature": "OTA4ZTE1YjNkMzhjNzc4ODUyNTZkOGQ0ZDI5YjgzOTMzYjQ3MTQzM2EwYzNjZWFjZWUxZDEzOTdmYmJhM2FhMQ==" } Signature input string: 9799936c-27be-432d-be84-e1249c7cac9e:Encoded1:prod:c7b66223-927d-41fd-afcc-a006d4cecb06:10.00:GBP:accepted SHA256 HMAC digest as lowercase hexadecimal: 908e15b3d38c77885256d8d4d29b83933b471433a0c3ceacee1d1397fbba3aa1 Base64 of the hexadecimal digest string: OTA4ZTE1YjNkMzhjNzc4ODUyNTZkOGQ0ZDI5YjgzOTMzYjQ3MTQzM2EwYzNjZWFjZWUxZDEzOTdmYmJhM2FhMQ== That Base64 value is the expected signature for this example. Do not Base64 encode the raw HMAC bytes for this signature format. For the same input, Base64 encoding the raw HMAC bytes would produce a different value: kI4Vs9OMd4hSVtjU0puDkztHFDOgw86s7h0Tl/u6OqE= That value should not be compared with notification.signature. Implementation Pseudocode input = notification.id + ":" + notification.user + ":" + notification.environment + ":" + notification.payload.id + ":" + formatAmount(notification.payload.amount) + ":" + notification.payload.currency + ":" + notification.payload.response.result.resultType hexDigest = hmacSha256(input, hmacKey).toLowercaseHex() expectedSignature = base64EncodeUtf8(hexDigest) if expectedSignature != notification.signature: reject notification Use a constant-time comparison function where your platform provides one. Receiver Behaviour Your callback endpoint should: Accept only HTTPS traffic in production. Validate the HMAC signature before trusting the payload. Check that environment matches the endpoint receiving the callback. Store notification.id and process each notification only once. Return a success response only after the notification has been accepted for processing. Retrieve the transaction or order from the API when your fulfilment process needs the latest full resource state. Avoid long-running work inside the HTTP request; hand off to a queue or background worker where appropriate. Reconciliation Use notification callbacks for timely updates, but keep API reconciliation in place: GET /transactions/{transaction_id} For order-based journeys: GET /orders/{order_id}/transactions This is important for hosted payment flows and PayByLink, where browser callbacks and customer redirects should not be treated as proof of payment. ### Orders URL: http://docs.encoded.services/concepts/v1/orders Orders An order groups the commercial context for one or more transactions. It represents what the customer is paying for: amount, currency, description, items, billing customer, shipping customer, and optional Hosted Payment Page configuration. Use an order when you need a durable payment container that can be looked up later, linked to multiple transactions, or used to generate a Hosted Payment Page. When to Use an Order Use an order whenA standalone transaction may be enough when You need Hosted Payment Pages or PayByLink.You are taking a simple server-side MOTO payment. You need to group authorise, capture, refund, or void transactions.The transaction is not linked to a basket, invoice, or order record. You need order-level customer, item, tax, or display information.Your own system already holds all commercial context. You need to retrieve all transactions for the same payment journey.You only need to retrieve a single transaction by ID or ref. Core Fields FieldPurpose objectMust be order. idAPI-generated UUID returned after creation. refYour own order reference. If omitted, it is populated from the generated order ID. Searchable, but not unique by default. descriptionHuman-readable order description. Useful on hosted payment pages and payment links. currencyISO 4217 currency, such as GBP. totalAmountTotal order amount. Required and must have no more than two decimal places. pendingAmountRead-only amount remaining unpaid. Updated as transactions are made against the order. itemsOptional item lines for the order. billingCustomerCustomer details or a reference customer used for billing and payment checks. shippingCustomerOptional customer details or reference for delivery context. hppHosted Payment Page configuration. When supplied, the response includes links.hpp.v1. attributesYour own structured metadata for reconciliation, reporting, or downstream behaviour. Customers on Orders billingCustomer and shippingCustomer can either contain a new customer object or a reference to an existing customer. Use an existing customer ID when you already know the payer. Provide a new customer object when the order is creating the customer context for the first time. The billing customer can be used as the default billing customer on a transaction when the transaction request does not specify one. Hosted Payment Pages An order must be created to generate a Hosted Payment Page. Put page behaviour under hpp when creating the order. FieldPurpose hpp.actionThe transaction action the hosted page should perform, usually pay or authorise. hpp.returnUrlWhere the browser is returned after the payment attempt. hpp.tokensWhether stored cards are shown or tokenisation is offered. hpp.viewWhat order and payment details are displayed to the customer. hpp.deliveryEmail, SMS, or QR delivery settings for PayByLink. hpp.merchantAccountIdOptional explicit merchant account override for HPP transactions. The generated Hosted Payment Page URL is returned at links.hpp.v1. Transactions on Orders Use GET /orders/{order_id}/transactions to retrieve the payment activity for an order. This is the safest way to reconcile a hosted payment or asynchronous PayByLink because browser callbacks should not be treated as the source of truth. Amounts and Lifecycle totalAmount is the order value. pendingAmount is read-only and reflects what remains unpaid after transactions are processed. Captures, payments, refunds, and voids should be understood through their transaction results, not by assuming the order state from a browser event. Important Constraints A transaction can be created without an order. An order can be created before any transaction exists. A transaction that was created without an order cannot be retroactively attached to one. A Hosted Payment Page is tied to the order that generated it. Use ref and attributes to connect orders to your own system, but store the API id for reliable API calls. ### PayByLink URL: http://docs.encoded.services/concepts/v1/paybylink PayByLink PayByLink is an asynchronous hosted payment journey where the customer receives a payment URL by email, SMS, or QR code. It is built on Hosted Payment Pages and configured through the hpp.delivery data on an order. Use PayByLink when the customer is not completing payment inside an immediate checkout session, such as invoice payment, assisted payment, collections, or a payment request sent after a support interaction. Key Characteristics AreaBehaviour OrderYour system creates an order with amount, currency, customer details and delivery settings. DeliveryThe payment link can be sent by email, SMS, or returned for QR/printed use. Payment timingThe customer may pay later, so the flow is asynchronous. ReconciliationUse notification callbacks or GET /orders/{order_id}/transactions. BrandingCustom domains are recommended for customer trust. Implementation Guidance Provide a clear order description so the customer recognises the payment request. Include enough customer or account context on the hosted page and message body. Configure an expiry period where payment links should not remain valid indefinitely. Use notification callbacks or polling to confirm payment completion. Do not fulfil from the delivery response alone; delivery only confirms that the link was sent or generated. See Generate and Send a PayByLink for the implementation flow. ### Payment Orchestration URL: http://docs.encoded.services/concepts/v1/payment-orchestration Payment Orchestration Payment orchestration is the Gateway's ability to decide how a payment should be processed behind the API. Your integration sends a consistent request model, and the Gateway can route the payment to the appropriate underlying provider, acquirer, merchant account, or payment method configuration. This allows your implementation to stay stable while operational routing changes are made behind the scenes. What Orchestration Can Influence AreaExamples Merchant account selectionChoosing the acquiring account used for the transaction. Provider routingSelecting the underlying gateway or acquirer path. Payment method availabilityEnabling or disabling methods on Hosted Payment Pages. Risk and authenticationApplying rules that determine whether 3D Secure or other checks are needed. Cost or acceptance optimisationRouting to support lower cost, higher acceptance, or resilience goals. The exact routing rules are configured operationally. They are not currently managed through the public Gateway API. What Developers Need to Know Most integrations should not hard-code routing assumptions. Instead: Send accurate platformType, currency, amount, source, customer, and order data. Use merchantAccountId only when your implementation is explicitly configured for it. Treat resultCode and message as the outcome of the routed attempt, not as proof that one fixed acquirer path was used. Keep your reconciliation keyed on API objects such as transaction.id, order.id, and your own ref values. Explicit Overrides When configured, explicit merchant account selection can be supplied on: FieldApplies to transactionRequest.merchantAccountIdDirect calls to POST /transactions. order.hpp.merchantAccountIdHosted Payment Page transactions generated from an order. Use explicit overrides carefully. Invalid or unsupported merchant account selection can cause validation or processing failures. Orchestration and Hosted Payment Pages Hosted Payment Pages can also be shaped by orchestration and configuration. The order hpp object controls customer-facing behaviour, while operational configuration determines what is available and how the resulting payment is processed. ### Payment Plans URL: http://docs.encoded.services/concepts/v1/payment-plans Payment Plans Payment Plans schedule and manage recurring or instalment-based payments through the Gateway API. They let the Gateway calculate scheduled payments, process payment attempts, record outcomes, and expose payment history without your system implementing all scheduling logic itself. A payment plan is always built around a customer, an order, a schedule, retry rules, and a payment source. Core Model Object or fieldPurpose customerOwns the plan and associated payment source. orderProvides the commercial context for the plan. typeDefines whether the plan is a subscription or installment. scheduleDefines when payments are attempted. transaction.sourcePayment source used for scheduled payment attempts, usually a stored card token. retriesControls retry attempts after failed scheduled payments. Plan Types TypeUse whenOrder behaviour installmentA fixed total amount is collected over a finite schedule.The order represents the full value being paid down. subscriptionA recurring amount is collected on an ongoing or date-bounded schedule.The order acts as the template for each scheduled payment. Lifecycle StatusMeaning initCreated but not ready to process scheduled payments. activeScheduled payments can be processed. inactiveScheduled payments are stopped. deletedPlan has been deleted and no further payments are taken. Scheduling Schedules are declarative. A plan can define daily, weekly, monthly, or yearly recurrence using fields such as interval, anchor day, and processing time. The Gateway uses the schedule to calculate planned payments and records completed, failed, cancelled, or pending payment attempts under the plan. Reconciliation Use GET /plans/{plan_id} for current plan state and GET /plans/{plan_id}/payments for scheduled payment history. See Create a Payment Plan for the implementation flow. ### Payment Sources URL: http://docs.encoded.services/concepts/v1/payment-sources Payment Sources A payment source tells a transaction where the funds or payment credential should come from. In the API this is represented by a source object, or by sources when a transaction needs more than one source component. Understanding sources is the key to understanding how the same POST /transactions endpoint supports card payments, stored card payments, Hosted Payment Fields, captures, refunds, voids, and wallet payments. Source and Sources FieldUse when sourceThe transaction has one source of funds or one reference object. This is the most common case. sourcesThe transaction needs multiple source components. For example, a stored card token plus a session containing a freshly collected security code. Each item inside sources is still a source object. Supported Source Types Source typeWhat it representsCommon uses cardDirect card details such as pan, expiry, and securityCode.MOTO payments, server-side card payments, token creation. tokenA stored card token previously created by tokenisation.Stored card payments and repeat payments. transactionA previous transaction.Capturing an authorisation, voiding an authorisation, refunding a prior payment. sessionA Hosted Payment Fields payment session.ECOM payments where card data was collected in hosted iframes. googlePayA Google Pay payment token.Google Pay transactions. applePayAn Apple Pay payment token.Apple Pay transactions. networkTokenA network token payment credential.Network token transactions where configured. musqetBtcA Musqet Bitcoin source.Musqet-branded Bitcoin flows where configured. Only one source type should be populated inside a single source object. Direct Card Source Use source.card when your backend is allowed to submit card details directly. { "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111" } } } For browser-based ECOM integrations, prefer Hosted Payment Pages or Hosted Payment Fields so sensitive card data is collected by hosted components. Token Source Use source.token when you already have a stored card token. { "source": { "object": "source", "token": { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd" } } } Transaction Source Use source.transaction when the new action depends on an earlier transaction. ActionSource transaction should be captureThe accepted authorisation being captured. voidThe accepted authorisation being cancelled. refundThe captured transaction being refunded, where supported. Session Source Use source.session when Hosted Payment Fields collected card data into a session. { "source": { "object": "source", "session": { "object": "session", "id": "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd" } } } The session source allows your backend to process a transaction without receiving the full card number from the browser. Combining Token and Session Some stored card journeys require a stored token plus a newly collected security code. Use sources for this. { "sources": [ { "object": "source", "token": { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd" } }, { "object": "source", "session": { "object": "session", "id": "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd" } } ] } Tokenising a Source Sources that support tokenisation can include tokenisation. For card payments, this is placed under source.card.tokenisation. { "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111", "tokenisation": { "object": "tokenisation", "agreement": "card_on_file", "ref": "TOKEN-10001" } } } If tokenisation succeeds, the created token is returned in transaction.response. ### Sessions URL: http://docs.encoded.services/concepts/v1/sessions Sessions A session is a temporary payment data container used by Hosted Payment Fields. It lets the browser collect sensitive card fields in hosted iframes while your backend later processes a transaction using only the session ID. Sessions are the bridge between a custom checkout UI and a transaction request that uses source.session. When to Use Sessions Use sessions when: You need your own checkout layout rather than a full Hosted Payment Page. You want card inputs hosted securely in iframes. Your backend should not receive the full card number from the browser. You need to combine a stored card token with a newly collected security code. Use Hosted Payment Pages instead when you want the entire payment form and payment journey hosted for you. Session Lifecycle StepAPI or componentPurpose 1POST /sessionsCreate a session and request fields such as pan, expiryDate, and securityCode. 2Session-limited JWTGenerate a browser-safe token scoped to the session. 3Hosted Payment Fields JavaScriptRender each hosted field iframe in your checkout. 4PATCH /sessions/{session_id}/fields/{field_name}Hosted field updates are synced to the session. 5POST /transactionsUse source.session.id to process the payment. Session Fields The supported field names are: FieldPurpose panCard number. expiryDateCard expiry date. securityCodeCard security code. Each field has a state, such as unset, updating, valid, or invalid, and can include a validation message. Updating Session Fields The Hosted Payment Fields JavaScript library normally performs session field updates for you. The update endpoint is PATCH /sessions/{session_id}/fields/{field_name}. The current implementation should treat these request fields as mutable: FieldPurpose valueField value to validate and store against the session. selectedWhether the field is selected in the browser. sequenceIdIncrementing ID used to apply updates in order. Although the schema includes state, do not rely on client-side state updates through this endpoint. The API determines field state from validation. Session-Limited Authentication Hosted Payment Fields needs a browser-visible JWT. Do not expose your normal API token to the browser. Generate a token with session_limited_read and bind it to the session with payment_session_id. The session-limited token should be used only for the matching session and should not include normal read/write API capability. Using a Session in a Transaction After the hosted fields have synced successfully, submit a transaction with source.session. { "object": "transaction.request", "action": "pay", "platformType": "ecom", "threeDSecure": true, "amount": 39.99, "currency": "GBP", "source": { "object": "source", "session": { "object": "session", "id": "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd" } } } Security Model The session may contain sensitive payment data. Your backend should store the session ID only for as long as it needs to complete the transaction. Your frontend should use the hosted field library and a session-limited token rather than attempting to handle card data itself. ### Tokens URL: http://docs.encoded.services/concepts/v1/tokens Tokens A token is a stored reference to card details. It lets you process future transactions without collecting or storing the full card number again in your own systems. Tokens are not created by calling POST /tokens. A token is created as the result of a transaction when you include tokenisation on a payment source. If token creation succeeds, the created token is returned inside transaction.response. Tokenisation Model ObjectPurpose tokenisationRequest object placed on a source, such as source.card.tokenisation, to ask the API to store the payment credential. tokenRead-only stored credential returned after successful tokenisation. token.refYour reference for the stored credential, originally supplied as tokenisation.ref. token.attributesMetadata supplied in tokenisation.attributes. source.tokenA reference to an existing token used as a payment source in a future transaction. Creating a Token Include tokenisation when submitting a transaction with card details or another tokenisable source. { "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111", "tokenisation": { "object": "tokenisation", "agreement": "card_on_file", "ref": "TOKEN-10001" } } } } pay, authorise, capture, and verify actions can be used in tokenising flows where supported by the source and provider. Use verify when you want to verify and store a card without taking funds. Agreement Types AgreementMeaning card_on_fileCardholder-initiated stored card use, such as a customer choosing a saved card at checkout or in a call centre. recurringA series of transactions for regular services, subscriptions, or ongoing billing. instalmentA fixed series of payments for a single purchase over a known period. unscheduledMerchant-initiated future transactions where the cardholder has given permission but the amount or timing may vary. Choose the agreement that matches how the stored credential will be used later. This matters for scheme rules and downstream processing. Token Contents A token response contains safe display data such as masked pan, expiry, issuer details, agreement type, billing customer, and attributes. It does not expose the full card number. { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd", "ref": "TOKEN-10001", "pan": "444433******1111", "expiry": "2028-10", "agreement": "card_on_file" } Using a Token Use source.token.id in a future transaction. { "object": "transaction.request", "action": "pay", "amount": 19.99, "currency": "GBP", "source": { "object": "source", "token": { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd" } } } If you need to collect a fresh security code for a stored card payment, use Hosted Payment Fields to create a session, then submit sources containing both the token and the session. Retrieving and Managing Tokens API callUse when GET /customers/{customer_id}/tokensYou want the stored cards for a known customer. GET /tokensYou need to search or page through tokens directly. GET /tokens/{token_id}You need one specific token. PATCH /tokens/{token_id}You need to update token attributes or expiry date. DELETE /tokens/{token_id}You need to remove a stored credential. Prefer customer-scoped token retrieval when building checkout or account-management experiences. ### Transaction Results URL: http://docs.encoded.services/concepts/v1/transaction-results Transaction Results Transaction outcome has two layers: transaction.status tells you where the transaction is in the lifecycle, and transaction.response.result tells you the final processor outcome once the transaction is processed. Do not treat these as the same thing. A transaction can exist and still be processing or challenged. A payment should only be fulfilled after the final result is known. Status vs Result FieldAvailable whenMeaning transaction.statusAlwaysLifecycle state: processing, challenged, or processed. transaction.challengeWhen status is challengedThe action your integration must complete before processing can continue. transaction.responseWhen status is processedFinal payment response. transaction.response.result.resultTypeWhen status is processedFinal outcome: accepted, declined, or error. transaction.response.result.resultCodeWhen status is processedSpecific machine-readable outcome code. transaction.response.result.messageWhen status is processedHuman-readable supporting message. Transaction Statuses StatusMeaningIntegration behaviour processingThe API is still waiting for a final outcome.Poll the transaction or wait for notification. Do not fulfil. challengedFurther action is needed, such as 3-D Secure authentication.Complete the challenge and submit the challenge response. Do not fulfil. processedProcessing has completed.Inspect resultType before fulfilment or recovery. Result Types Result typeMeaningIntegration behaviour acceptedThe transaction action succeeded.Continue the flow, such as fulfilment, capture state update, refund confirmation, or token storage. declinedThe transaction was declined by the processor or scheme rules.Show a recoverable payment failure where appropriate. Do not retry blindly. errorThe API or processor could not complete the request normally.Investigate resultCode and message. Retry only when the error is safe to retry. Result Codes resultCode is an underscored machine-readable value, such as invalid_merchant_account, invalid_card_number, declined_insufficient_funds, or error_system. Use resultCode for application logic. Use message for support and diagnostics, but avoid depending on message text for programmatic decisions. Polling and Timeouts POST /transactions can return processing if the configured or supplied pollTimeMs is reached before the acquirer responds. This does not mean the payment failed. It means the final result is not available yet. Your integration should: Store the transaction.id. Poll GET /transactions/{transaction_id} or wait for notifications. Fulfil only after status is processed and resultType is accepted. Make retry decisions based on the final resultCode, not on the existence of a timeout alone. Challenges When a transaction is challenged, the latest challenge is available at transaction.challenge. Previous challenges may be listed in transaction.challenges, ordered newest to oldest. After completing the external action, submit the response to POST /transactions/{transaction_id}/challenge/{challenge_id}. The returned transaction may become processed, remain processing, or in some cases become challenged again. ### Transactions URL: http://docs.encoded.services/concepts/v1/transactions Transactions A transaction is the API record for a payment attempt or payment-related action. It contains the original transaction.request, the current processing status, the final transaction.response when processing has completed, and any challenge details when further customer action is required. You do not create a transaction object directly. You submit a transaction.request to POST /transactions, and the API returns the resulting transaction. How Transactions Fit Together ObjectPurpose transaction.requestThe instruction you send to the API. It contains action, amount, currency, source, customer/order references, and optional routing data. transactionThe resource returned by the API. It records processing state and links the request, response, challenge, and audit data. transaction.responseThe final outcome from the payment processor when the transaction reaches processed. resultThe final result inside transaction.response, with resultType, resultCode, and message. challengeA required next action, such as a 3-D Secure challenge, when the transaction reaches challenged. Transaction Actions ActionUse whenSource normally used payYou want authorisation and capture in a single payment.card, token, session, wallet source, or another supported source. authoriseYou want to reserve funds and capture later.card, token, session, wallet source, or another supported source. captureYou want to collect funds from an earlier accepted authorisation.transaction referencing the authorisation. refundYou want to return captured funds to the payer.Usually transaction, sometimes card or token where supported by the provider. voidYou want to cancel an uncaptured authorisation.transaction referencing the authorisation. verifyYou want to verify a payment source without taking funds.card, token, session, or another supported source. Transaction Status status describes where the transaction is in the processing lifecycle. It is not the same as the final payment result. StatusMeaningWhat your integration should do processingThe API has not yet received a final outcome from the underlying processor.Poll GET /transactions/{transaction_id} or wait for notification before fulfilment. challengedThe API needs a challenge response before processing can continue.Complete the challenge flow and submit to POST /transactions/{transaction_id}/challenge/{challenge_id}. processedThe transaction has completed processing.Read transaction.response.result to decide whether it was accepted, declined, or errored. Result Type When status is processed, inspect transaction.response.result.resultType. Result typeMeaning acceptedThe transaction action was accepted by the processor. declinedThe transaction was declined. Use resultCode and message to explain or recover. errorThe API or processor could not complete the transaction normally. Investigate before retrying. Do not fulfil an order because a transaction exists. Fulfil only when the relevant transaction is processed and the result is accepted. Source and Sources A transaction needs a payment source. Most requests use source, which contains exactly one source type. Some requests use sources, an array of source objects, when more than one source component is needed. A common example is a stored card token plus a Hosted Payment Fields session containing a freshly collected security code. See Payment Sources for the full model. Orders and Transactions Transactions can be processed independently, or they can be linked to an order. Use an order when you need to group multiple related transactions, such as authorise followed by capture, or a payment followed by one or more refunds. If you need a Hosted Payment Page, you must create an order because the Hosted Payment Page URL is generated from order hpp configuration and returned at links.hpp.v1. References, Attributes, and Reconciliation Use ref to connect the transaction to your own order, invoice, case, or account identifier. The ref value is searchable, but it is not guaranteed to be unique unless your implementation has been configured that way. Use attributes for implementation-specific metadata. Attributes can contain strings, numbers, booleans, arrays, and nested objects. They are useful for internal routing, reporting, and reconciliation data that does not belong in standard payment fields. Polling Behaviour POST /transactions accepts a pollTimeMs query parameter. The API waits until the transaction reaches processed or challenged, or until the poll time is reached. If the poll time is reached first, the API returns the transaction with status set to processing. The same pattern applies when retrieving a transaction by ID. Your integration should be designed for asynchronous completion. ### Quick Start URL: http://docs.encoded.services/guides/v1/quick-start Quick Start This guide takes you from onboarding to a first sandbox payment. It uses the simplest server-side journey: get OAuth credentials, create a customer, create an order, submit a card payment transaction, then inspect the transaction response. Use this as a first integration path before moving into Hosted Payment Pages, Hosted Payment Fields, tokenisation, 3-D Secure, refunds, payment plans, or production launch activity. 1. Request Environment Access Before you can call the API, contact your Encoded implementation contact or service desk and request sandbox onboarding. If your portal is provided under another brand, use the implementation contact for that brand. You should receive or agree the following before development starts: ItemWhy you need it Sandbox base URLsThe API and OAuth endpoints for test traffic. OAuth client_id and client_secretUsed by your backend to request bearer tokens. Enabled OAuth scopesUsually read and write for backend API calls. Merchant account configurationDetermines routing, supported currencies, payment methods and optional merchantAccountId values. Network allow-listingYour outbound IP addresses may need to be allow-listed before requests are accepted. Test cards and expected outcomesUsed to trigger accepted, declined, errored or challenged responses in sandbox. Hosted payment settingsRequired if you will use Hosted Payment Pages, PayByLink or Hosted Payment Fields. Production readiness processProduction credentials are normally issued after sandbox testing and launch checks. Keep sandbox and production credentials separate. Sandbox credentials should only be used with sandbox URLs, and production credentials should only be used with production URLs. 2. Set Your Base URLs The API base URL follows this pattern: https://[env].encoded.services/api/[version]/ For the current version, sandbox API calls use: https://sit.encoded.services/api/v1/ OAuth tokens are requested from the matching environment: https://sit.encoded.services/auth/oauth/token The examples below use these placeholders: PlaceholderMeaning {client_id}Your sandbox OAuth client ID. {client_secret}Your sandbox OAuth client secret. {access_token}The bearer token returned by OAuth. {customer_id}The API-generated customer ID. {order_id}The API-generated order ID. {transaction_id}The API-generated transaction ID. 3. Get an OAuth Access Token Exchange your client credentials for a bearer token using the OAuth client credentials grant. Keep this request on your backend; do not expose the client secret in browser code. POST /auth/oauth/token Authorization: Basic {base64(client_id:client_secret)} Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&scope=read write Example using curl: curl -u "{client_id}:{client_secret}" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&scope=read write" \ https://sit.encoded.services/auth/oauth/token The response includes an access token and its expiry. { "access_token": "{access_token}", "token_type": "bearer", "expires_in": 21599, "scope": [ "read", "write" ] } Use the token on API requests: Authorization: Bearer {access_token} 4. Create Your First Customer A customer represents the payer or account holder. Creating a customer first makes later order, token and transaction activity easier to search and reconcile. POST /customers accepts an array of customer objects. curl -X POST https://sit.encoded.services/api/v1/customers \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '[ { "object": "customer", "ref": "QS-CUST-10001", "forename": "Alex", "surname": "Example", "contact": { "object": "contact", "email": "alex@example.com" }, "attributes": { "source": "quick-start" } } ]' Record the customer ID returned by the API. If your implementation returns only a created status, retrieve the customer by the reference you supplied: GET /customers?ref=QS-CUST-10001 Use the resulting id as {customer_id} in the next step. 5. Create Your First Order An order groups the commercial context for payment: amount, currency, description and customer details. It is also required for Hosted Payment Pages and PayByLink. POST /orders accepts an array of order objects. This example links the order to the customer created above. curl -X POST https://sit.encoded.services/api/v1/orders \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '[ { "object": "order", "ref": "QS-ORD-10001", "description": "Quick Start test order", "currency": "GBP", "totalAmount": 29.99, "billingCustomer": { "object": "customer", "id": "{customer_id}" }, "attributes": { "source": "quick-start" } } ]' Record the created order id as {order_id}. You can use this ID to connect the transaction to the order and to retrieve all payment activity for the order later. 6. Process Your First Transaction Submit a transaction.request to POST /transactions. This example uses a MOTO pay transaction with a direct card source and links it to the order you just created. Use a sandbox test card supplied for your implementation. The card number below is illustrative; your onboarding contact can confirm the active test card set and the responses each card should trigger. curl -X POST "https://sit.encoded.services/api/v1/transactions?pollTimeMs=10000" \ -H "Authorization: Bearer {access_token}" \ -H "Content-Type: application/json" \ -d '{ "object": "transaction.request", "action": "pay", "platformType": "moto", "ref": "QS-TXN-10001", "amount": 29.99, "currency": "GBP", "order": { "object": "order", "id": "{order_id}" }, "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111" } }, "billingCustomer": { "object": "customer", "id": "{customer_id}" }, "attributes": { "source": "quick-start" } }' pollTimeMs=10000 asks the API to wait briefly for a final result. If processing does not complete within that time, the API can return a transaction with status set to processing. 7. Check the Transaction Response The transaction response is the source of truth for whether the payment was accepted. A completed accepted payment has: FieldExpected value objecttransaction statusprocessed response.result.resultTypeaccepted Example accepted response: { "object": "transaction", "id": "b015dd96-a8e5-46e1-b390-af39d0b93960", "status": "processed", "request": { "object": "transaction.request", "action": "pay", "amount": 29.99, "currency": "GBP" }, "response": { "object": "transaction.response", "result": { "object": "result", "resultType": "accepted", "resultCode": "accepted", "message": "Approved" }, "auth": { "object": "auth", "code": "006348" } } } Store the transaction id as {transaction_id}. If the initial response is still processing, retrieve it again: GET /transactions/{transaction_id} If the payment is linked to an order, you can also retrieve the order's payment activity: GET /orders/{order_id}/transactions 8. Handle Each Outcome Do not fulfil an order just because a transaction was created. Fulfil only after checking the final transaction result. Response stateWhat your system should do processed with response.result.resultType of acceptedTreat the payment as successful and continue fulfilment. processed with response.result.resultType of declinedDo not fulfil. Show or record the decline reason and allow another payment method where appropriate. processed with response.result.resultType of errorDo not fulfil. Investigate the result code and retry only when safe. processingPoll GET /transactions/{transaction_id} or wait for notification before making a fulfilment decision. challengedComplete the required challenge flow before expecting a final result. 9. What to Build Next After this first sandbox payment, continue with the documentation that matches your target journey: Next stepRead this Understand authentication and token scopesAuthentication Understand IDs, references and linksAPI Object Model Build a hosted checkoutHosted Payment Page with an Order Use hosted card capture in your own checkoutHosted Payment Fields Store cards for repeat useTokens and Store a Card Receive asynchronous payment updatesNotification Callbacks Test response handlingTesting and Response Codes Prepare for productionEnvironments and URLs Before production launch, confirm with your implementation contact that sandbox testing is complete, production credentials have been issued, network access is configured, merchant accounts are enabled, and any hosted payment return URLs or custom domains are ready. ### Create a Payment Plan URL: http://docs.encoded.services/payment-flows/v1/create-a-payment-plan Create a Payment Plan Use this flow when you want the Gateway to schedule and process future payments using a stored payment source. The flow assumes you already have a customer, an order, and a stored card token. Read Payment Plans first if you need the difference between subscriptions and instalments. Flow Overview StepAPI callPurpose 1Customer and token setupCreate or identify the customer and stored payment source. 2POST /ordersCreate the order that gives the plan its commercial context. 3POST /plansCreate the payment plan with type, schedule, retries and payment source. 4GET /plans/{plan_id}Confirm the plan status. 5GET /plans/{plan_id}/paymentsReconcile scheduled payment attempts. Step 1. Prepare Customer, Order and Token A payment plan needs: ResourceRequirement CustomerExisting customer that owns the payment source. OrderExisting order used as the commercial context for the plan. TokenStored card token used as the scheduled payment source. The token should belong to the customer used for the plan. Step 2. Create the Plan Create the plan with a type, referenced order, retry policy, schedule and transaction source. This example creates a daily subscription plan. { "ref": "PLAN-10001", "type": "subscription", "order": { "object": "order", "id": "8cfe36c0-cf48-42f7-8c03-2cb998bbdf78" }, "retries": { "amount": 2, "duration": "P1D" }, "schedule": { "daily": { "interval": 1, "time": "12:00" } }, "startDate": "2026-09-24", "endDate": "2027-09-24", "transaction": { "object": "transaction", "source": { "object": "source", "token": { "object": "token", "id": "9902749a-a972-46f5-8f4c-1a8e553603d7" } } } } Submit it to: POST /plans Step 3. Check the Created Plan The response includes the payment plan ID, status, schedule, order reference and links to scheduled or completed payments. { "id": "f7d8e2c2-20e8-4df7-87b5-d9672f0c11f4", "ref": "PLAN-10001", "type": "subscription", "status": "active", "order": { "object": "order", "id": "8cfe36c0-cf48-42f7-8c03-2cb998bbdf78" }, "links": { "scheduledPayments": "https://sit.encoded.services/api/v1/plans/f7d8e2c2-20e8-4df7-87b5-d9672f0c11f4/payments?status=pending", "payments": "https://sit.encoded.services/api/v1/plans/f7d8e2c2-20e8-4df7-87b5-d9672f0c11f4/payments?status=completed&status=failed&status=canceled" } } Store the plan ID for future updates and reconciliation. Step 4. Reconcile Payments Retrieve the plan to check its current state: GET /plans/{plan_id} Retrieve scheduled and attempted payments: GET /plans/{plan_id}/payments Use payment results and transaction results for fulfilment, retry handling and customer communication. Developer Checkpoints Use subscription for ongoing recurring payments. Use installment for a finite plan that pays down a fixed total. Confirm the token is valid before expecting a plan to become active. Store the plan ID and reconcile payment attempts regularly. Use notification callbacks where available for asynchronous payment outcomes. ### ECOM Payment with 3DS2 Challenge URL: http://docs.encoded.services/payment-flows/v1/ecom-3ds2-card-payment ECOM Payment with 3DS2 Challenge Use this flow when a cardholder is paying online and the transaction may require 3D Secure authentication. 3DS2 adds cardholder authentication to an e-commerce card transaction and can protect both merchants and cardholders from credit and debit card fraud. The Gateway API determines the 3D Secure version to use from the merchant account configuration. Your integration should be ready for either a frictionless result, where the transaction completes without cardholder interaction, or a challenge result, where the cardholder must authenticate in the browser before the payment can continue. For background on 3-D Secure transaction states, ACS handoff, callback fields, and multiple challenge handling, see EMV 3-D Secure. Flow Overview StepAPI callPurpose 1POST /transactionsSubmit an ECOM transaction with threeDSecure enabled. 2Read the transaction statusContinue immediately if processed, or start challenge handling if challenged. 3Browser POST to acsUrlRedirect the cardholder to the Gateway API Access Control Server. 4Receive ACS callbackCapture the authentication response posted to your returnUrl. 5POST /transactions/{transaction_id}/challenge/{challenge_id}Submit the challenge response to continue processing. 6GET /transactions/{transaction_id}Retrieve the final transaction result if needed. Step 1. Submit the ECOM Payment Start the transaction with platformType set to ecom and threeDSecure set to true. The action can be pay for authorisation and capture in one step, or authorise if you want a separate capture later. { "object": "transaction.request", "action": "pay", "platformType": "ecom", "threeDSecure": true, "ref": "ECOM-ORDER-10001", "amount": 59.99, "currency": "GBP", "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111" } }, "billingCustomer": { "object": "customer", "forename": "Alex", "surname": "Example", "contact": { "object": "contact", "email": "alex@example.com" } } } Step 2. Detect Whether a Challenge Is Required If the issuer and risk checks allow a frictionless result, the transaction can return processed with a normal transaction.response. If authentication is required, the transaction returns challenged with a transaction.challenge object. { "object": "transaction", "id": "4b502950-8801-4112-ba15-88f8eb280525", "creationDate": "2020-07-01T00:00:00Z", "status": "challenged", "challenge": { "object": "transaction.challenge", "id": "1", "threeDSecure": { "object": "transaction.challenge.threeDSecure", "v2": { "object": "transaction.challenge.threeDSecure.v2", "acsUrl": "https://sit.encoded.services/emv3ds/acs/init/4b502950-8801-4112-ba15-88f8eb280525" } }, "links": { "self": "https://sit.encoded.services/api/v1/transactions/4b502950-8801-4112-ba15-88f8eb280525/challenge/1" } }, "links": { "self": "https://sit.encoded.services/api/v1/transactions/4b502950-8801-4112-ba15-88f8eb280525" } } The challenge.threeDSecure.v2.acsUrl value is the Gateway API Access Control Server URL. The challenge.links.self value is the API endpoint you will call after the cardholder completes authentication. Step 3. Redirect the Cardholder to the ACS The cardholder's browser must POST to the acsUrl. Include your callback URL in returnUrl. You can also provide challengeWindowSize to tell the ACS the display size you intend to use.
In a production checkout, the form is normally auto-submitted or rendered inside your challenge container. Step 4. Process the ACS Callback When authentication completes, the ACS posts the authentication result to your returnUrl. Capture the posted fields and use them to build the challenge response sent to the Gateway API. FieldMeaning dsTransIdUnique ID for the directory server transaction. authenticationValueAuthentication value returned by the ACS. eciElectronic commerce indicator. transStatusStatus of the authentication attempt. messageVersion3DS2 message version used for the challenge. Do not fulfil the order at this point. The ACS callback only proves that the authentication step has returned to your site. The payment must still be continued through the challenge endpoint. Step 5. Submit the Challenge Response Send the authentication fields received from the ACS to the challenge endpoint returned in challenge.links.self. POST /transactions/4b502950-8801-4112-ba15-88f8eb280525/challenge/1 { "object": "transaction.challenge.response", "threeDSecure": { "object": "transaction.challenge.response.threeDSecure", "v2": { "object": "transaction.challenge.response.threeDSecure.v2", "dsTransId": "8b167401-2c2e-4f5c-80e0-6dcbf68737cd", "authenticationValue": "MTIzNDU2Nzg5MDEyMzQ1OTcyODM=", "eci": "05", "transStatus": "Y", "messageVersion": "2.2.0" } } } The challenge endpoint returns a transaction object. In the usual successful case, the transaction status is processed and the transaction contains a transaction.response object. Step 6. Handle the Final Transaction Response stateWhat to do processed with acceptedFulfil the order. processed with declinedDo not fulfil. Show a payment failure and allow another attempt. processed with errorDo not fulfil. Investigate the result before retrying. challengedRepeat the challenge handling for the latest transaction.challenge. processingPoll GET /transactions/{transaction_id} until the transaction is complete or your timeout is reached. Multiple Challenges In some circumstances, the transaction returned after a challenge response may still have status set to challenged. This means an additional challenge has been requested. Code your implementation to repeat the challenge handling loop until the transaction reaches a final state. The latest challenge is returned in transaction.challenge. Previous challenges may be present in transaction.challenges. Developer Checkpoints ECOM 3DS2 payments use platformType of ecom. 3D Secure runs only when threeDSecure is enabled and the merchant account and source are eligible. acsUrl is used by the browser; challenge.links.self is used by your backend to submit the authentication result. Do not fulfil while the transaction is challenged or processing. Fulfil only after the final transaction response result is accepted. ### Generate and Send a PayByLink URL: http://docs.encoded.services/payment-flows/v1/paybylink Generate and Send a PayByLink Use this flow when payment is asynchronous and the customer should receive a payment URL by email, SMS, or QR code. PayByLink is configured through the Hosted Payment Page data on an order. Flow Overview StepAPI callPurpose 1POST /ordersCreate an order with hpp.delivery. 2Delivery provider sends the linkThe response records delivery status and URL data. 3Customer pays laterThe customer opens the hosted page and completes payment. 4Notification or pollingConfirm the final transaction before fulfilment. Step 1. Create an Order with Email Delivery The hpp.delivery.email object controls the email that is sent to the customer. The message template must include hpp.shortenedUrl so the payment link can be inserted. { "object": "order", "ref": "PBL-10001", "description": "Invoice 10001", "currency": "GBP", "totalAmount": 74.50, "billingCustomer": { "object": "customer", "forename": "Alex", "surname": "Example", "contact": { "object": "contact", "email": "alex@example.com" } }, "hpp": { "action": "pay", "expiryDuration": "P7D", "delivery": { "email": { "recipient": "alex@example.com", "subject": "Payment request for {order.description}", "body": { "type": "text", "format": "Please pay {order.totalAmount} using {hpp.shortenedUrl}" } } } } } Step 2. Read the Delivery Result The order response includes delivery responses. Store the order ID and use notification or polling to reconcile the eventual payment. { "object": "order", "id": "96d7d98a-46fd-4d3b-a15b-b03c116ae949", "ref": "PBL-10001", "hpp": { "deliveries": [ { "response": { "deliveryStatus": "sent", "message": "Order sent to email address alex@example.com", "url": "https://yourpay.link/84bBR" } } ] } } Step 3. Confirm Payment Completion Because PayByLink is asynchronous, do not rely on the order creation response as proof of payment. Use notifications where available, or retrieve the order transactions. GET /orders/{order_id}/transactions Delivery Options Delivery typeUse when emailThe customer should receive the payment link by email. smsThe customer should receive the payment link by text message. qrThe payment link should be printed, displayed, or scanned. Developer Checkpoints Use a clear description and custom order fields so the customer recognises the payment request. Configure an expiry for payment links where appropriate. Confirm payment completion through the API or notifications before fulfilment. ### Hosted Payment Fields Session URL: http://docs.encoded.services/payment-flows/v1/hosted-payment-fields-session Hosted Payment Fields Session Use this flow when you want your checkout UI to keep its own layout while card data is collected in secure hosted fields. Your server creates a session, the browser fills the hosted fields, and your server uses the session as the transaction source. Flow Overview StepAPI callPurpose 1POST /sessionsCreate a payment session and requested fields. 2Session-limited tokenGenerate a browser-safe token scoped to the session. 3Hosted Payment Fields JavaScriptRender and populate the hosted fields. 4PATCH /sessions/{session_id}/fields/{field_name}Field values are synced to the session. 5POST /transactionsProcess the payment using source.session. Step 1. Create the Session Create a session for the fields you need to collect. { "object": "session", "fields": [ "pan", "expiryDate", "securityCode" ] } The response includes a session id and iframe URLs for each requested field. { "object": "session", "id": "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd", "sessionFields": [ { "object": "sessionField", "name": "pan", "state": "unset", "links": { "iframeURL": "https://sit.encoded.services/hpf/v1/10b3ca21-d9fd-4030-b5f5-fb45f220a6dd/pan" } } ] } Step 2. Initialise Hosted Payment Fields Generate a session-limited JWT on your backend and initialise the JavaScript in the browser. The token should use session_limited_read and be bound to the session ID. HostedPaymentFields.initialise(JWT_AUTH_TOKEN, { sessionId: "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd", form: { id: "payment-form", fields: { pan: { id: "pan" }, expiry: { id: "expiry" }, securityCode: { id: "securityCode" } } }, onEvent: function (event) { // Update checkout state from Hosted Payment Fields events. } }); Step 3. Sync the Hosted Fields When the user submits the form, dispatch paymentSessionSyncRequest.encodedHpf. The JavaScript library syncs field updates to the session using PATCH /sessions/{session_id}/fields/{field_name}. const syncRequest = new CustomEvent("paymentSessionSyncRequest.encodedHpf"); document.getElementById("payment-form").dispatchEvent(syncRequest); Step 4. Process the Transaction After the session fields are valid and synced, submit a transaction using source.session. { "object": "transaction.request", "action": "pay", "platformType": "ecom", "threeDSecure": true, "ref": "HPF-10001", "amount": 39.99, "currency": "GBP", "source": { "object": "source", "session": { "object": "session", "id": "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd" } } } Step 5. Handle the Transaction Result Response stateWhat to do processed with acceptedFulfil the order. challengedComplete the 3DS flow and submit the challenge response. processed with declinedShow a payment failure and allow another attempt. processingPoll GET /transactions/{transaction_id}. Developer Checkpoints The browser should receive only a session-limited token, not your normal API credentials. The session ID is the bridge between hosted field collection and the transaction request. Do not submit the transaction until the hosted fields have synced successfully. ### Hosted Payment Page with an Order URL: http://docs.encoded.services/payment-flows/v1/hosted-payment-page-order Hosted Payment Page with an Order Use this flow when you want Encoded to host the checkout page while your system creates and owns the order. Hosted Payment Pages provide a hosted card payment form that can collect payment details, present available payment methods, run the transaction, and return the cardholder to your site. Because the sensitive payment form is hosted by Encoded, this flow can help keep the merchant integration eligible for SAQ-A PCI scope, provided the rest of the implementation follows the required PCI rules. Flow Overview StepAPI callPurpose 1POST /ordersCreate the order and include Hosted Payment Page configuration. 2Order-time configurationConfigure the hosted page action, return URL, stored-card options, and view settings before opening the page. 3Open links.hpp.v1Send the cardholder to the hosted checkout. 4Hosted checkoutCardholder selects a payment method and completes payment. 5Receive returnUrl callbackReceive the browser result after payment. 6GET /orders/{order_id} or GET /orders/{order_id}/transactionsVerify the result server-side. 7Token and fulfilment handlingStore any created token and fulfil only after an accepted transaction is confirmed. Step 1. Create the Order Create an order with the amount, currency, customer details, and hpp configuration. The hpp.action controls the transaction action used by the Hosted Payment Page. If no action is supplied, pay is used by default. { "object": "order", "ref": "ORD-10001", "description": "Checkout order 10001", "currency": "GBP", "totalAmount": 49.99, "billingCustomer": { "object": "customer", "forename": "Alex", "surname": "Example", "contact": { "object": "contact", "email": "alex@example.com" } }, "hpp": { "action": "pay", "returnUrl": "https://merchant.example.com/payment-result" } } The response includes the created order and a Hosted Payment Page link. { "object": "order", "id": "96d7d98a-46fd-4d3b-a15b-b03c116ae949", "creationDate": "2019-07-01T00:00:00Z", "ref": "ORD-10001", "description": "Checkout order 10001", "currency": "GBP", "totalAmount": 49.99, "hpp": { "action": "pay", "returnUrl": "https://merchant.example.com/payment-result" }, "links": { "self": "https://sit.encoded.services/api/v1/orders/96d7d98a-46fd-4d3b-a15b-b03c116ae949", "hpp": { "v1": "https://sit.encoded.services/hpp/v1/96d7d98a-46fd-4d3b-a15b-b03c116ae949" } } } Step 2. Configure the Hosted Page Decide the hosted page behaviour before the page is opened. These settings belong in the order creation payload because they affect the page generated for links.hpp.v1. Configuration areaFieldsPurpose Payment actionhpp.actionControls whether the hosted page performs pay, authorise, or another supported action. Browser returnhpp.returnUrlReturns the cardholder to your site after the payment attempt. Stored cardshpp.tokensDisplays existing customer tokens or offers card storage. Page displayhpp.viewControls order display, custom fields, and page presentation. Stored Card Options If the Hosted Payment Page should show stored cards or offer card storage, provide a valid billingCustomer and include hpp.tokens. FieldPurpose hpp.tokens.enabledShows existing customer tokens as available payment methods. hpp.tokens.tokenisationGives the cardholder an option to save the card used on the hosted page. tokenisation.agreementDescribes the future use of the stored credential, such as card_on_file, recurring, instalment, or unscheduled. { "object": "order", "ref": "ORD-10002", "description": "Checkout order 10002", "currency": "GBP", "totalAmount": 49.99, "billingCustomer": { "object": "customer", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }, "hpp": { "action": "pay", "returnUrl": "https://merchant.example.com/payment-result", "tokens": { "enabled": true, "tokenisation": { "object": "tokenisation", "agreement": "card_on_file", "ref": "TOKEN-ORD-10002" } } } } View Configuration You can configure aspects of the Hosted Payment Page view inside hpp.view when creating the order. { "hpp": { "view": { "order": { "type": "expanded", "fields": [ { "name": "Customer Name", "value": "Alex Example" }, { "name": "Customer ID", "value": "CUST-10001" } ] } } } } Theme The default theme is Modern. The previous Classic theme is deprecated and should not be used. Classic does not support Apple Pay, Google Pay, display of order items and custom key fields, or legal notices. Display Display typeUse when minimalThe Hosted Payment Page is embedded in a checkout that already displays the order details. expandedThe Hosted Payment Page is used as a full-page redirect, standalone checkout, or PayByLink destination. You can also control individual order display fields through hpp.view.order.display. Custom Order Fields Use custom order fields to display extra context to the cardholder, such as account number, invoice number, delivery reference, or customer name. These fields can improve customer confidence that the payment request is legitimate. Step 3. Open or Embed the Hosted Payment Page Open links.hpp.v1 in the cardholder's browser. You can redirect the browser to the URL or embed it in an iframe inside your checkout. Payment Form The Hosted Payment Page is responsible for displaying available payment methods, collecting payment information, and processing the transaction for the order. Step 4. Handle the Return URL After the payment attempt, the cardholder is returned to the returnUrl you supplied. The callback is a HTTP POST containing fields that identify the order, transaction, and high-level result. Field nameField valuesNotes orderIdOrder IDUse this to match the callback to the order in your backend. transactionIdTransaction IDUse this to retrieve the full transaction from the API. resultaccepted, declined, or errorIndicates the Hosted Payment Page transaction result. authCodeAuthorisation codeSupplied when the transaction is accepted. tokenIdToken IDSupplied only when tokenisation created a stored card. Use the callback to decide what browser page to show the cardholder. Do not treat the browser callback alone as proof of payment. Step 5. Verify the Payment Server-Side Retrieve the order or the order transactions before fulfilment. GET /orders/{order_id}/transactions The transaction result is the source of truth for fulfilment. Transaction resultWhat to do acceptedFulfil the order. declinedShow a failed payment state and allow another attempt where appropriate. errorDo not fulfil. Investigate the result code and retry only when safe. processingPoll the transaction or wait for notification before fulfilment. Step 6. Manage Tokens Created by the Hosted Page If the callback includes tokenId, a card token was created as part of the transaction. Store the token ID against the customer if your product supports stored cards. For stricter token management, use your own customer rules after token creation. For example, if a customer may only have one active stored card, retrieve the customer's tokens and remove or disable older tokens according to your business rules. Step 7. Configure Default Hosted Page Settings Some Hosted Payment Page settings can also be configured as defaults rather than supplied on every order. These include custom logos, PayByLink expiry defaults, and Apple Pay or Google Pay enablement. Use the Hosted Payment Page configuration endpoint for account-level or user-level defaults. POST /hpp/config/{level} Developer Checkpoints Use POST /orders for this flow; the Hosted Payment Page URL is returned on the order. Include hpp.returnUrl when you want the cardholder returned to your site after payment. Decide hpp.tokens and hpp.view settings before opening the hosted page. Treat the browser return as untrusted until you have checked the order or transaction through the API. Use POST /hpp/config/{level} for default hosted-page configuration that should not be supplied on every order. ### Processing a MOTO Payment URL: http://docs.encoded.services/payment-flows/v1/take-a-card-payment Processing a MOTO Payment Use this flow when an operator is taking card details by mail order or telephone order and submitting the payment server-side. The API request is a single pay transaction with platformType set to moto. Flow Overview StepAPI callPurpose 1POST /transactionsSubmit the MOTO payment request. 2GET /transactions/{transaction_id}Check the final status if the first response is still processing. 3Fulfil or investigateFulfil only when the transaction response result is accepted. Step 1. Submit the Payment Send a transaction.request with action set to pay, platformType set to moto, and a direct card source. { "object": "transaction.request", "action": "pay", "platformType": "moto", "ref": "MOTO-ORDER-10001", "amount": 29.99, "currency": "GBP", "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111" } }, "billingCustomer": { "object": "customer", "forename": "Alex", "surname": "Example", "contact": { "object": "contact", "email": "alex@example.com" } } } Step 2. Read the Response A successful synchronous response returns a transaction with status set to processed and response.result.resultType set to accepted. { "object": "transaction", "id": "b015dd96-a8e5-46e1-b390-af39d0b93960", "status": "processed", "request": { "object": "transaction.request", "action": "pay", "amount": 29.99, "currency": "GBP" }, "response": { "object": "transaction.response", "result": { "object": "result", "resultType": "accepted", "resultCode": "accepted", "message": "Approved" }, "auth": { "object": "auth", "code": "006348" } } } Step 3. Handle Each Outcome Response stateWhat to do processed with acceptedTreat the payment as successful and continue fulfilment. processed with declinedShow or record the decline message and ask for another payment method. processed with errorDo not fulfil. Investigate the result code and retry only when safe. processingPoll GET /transactions/{transaction_id} until the transaction is complete or your own timeout is reached. Developer Checkpoints MOTO payments should use platformType of moto. MOTO payments do not use 3D Secure challenges. Use your own ref so the transaction can be reconciled with your internal order, case, or account record. Always use the transaction result returned by the API before fulfilling the payment. ### Refund a Payment URL: http://docs.encoded.services/payment-flows/v1/refund-a-payment Refund a Payment Use this flow when a processed payment needs to be returned to the payer after funds have been captured. A refund is a new transaction.request with action set to refund. Flow Overview StepAPI callPurpose 1Locate the original paymentFind the captured transaction you want to refund. 2POST /transactionsSubmit a refund transaction. 3GET /transactions/{transaction_id}Check the refund if it remains processing. 4Update your systemRecord the refund result against the original payment. Step 1. Choose the Refund Source The most common refund source is the original successful transaction. Source typeWhen to use it source.transactionRefund against a previous transaction. This is the usual flow. source.cardRefund to supplied card details, where supported by the underlying provider. source.tokenRefund to a stored card token, where supported by the underlying provider. Step 2. Submit the Refund For a linked refund, pass the original transaction ID as source.transaction.id. Include amount and currency for a partial refund. If the amount is omitted for a transaction-backed refund, the API can inherit the amount from the referenced transaction where supported. { "object": "transaction.request", "action": "refund", "ref": "REFUND-10001", "amount": 12.50, "currency": "GBP", "source": { "object": "source", "transaction": { "object": "transaction", "id": "b015dd96-a8e5-46e1-b390-af39d0b93960" } } } Step 3. Read the Refund Response { "object": "transaction", "id": "2156d9ef-a16a-4e43-b5d2-bfdcb6c9afae", "status": "processed", "request": { "object": "transaction.request", "action": "refund", "amount": 12.50, "currency": "GBP" }, "response": { "object": "transaction.response", "result": { "object": "result", "resultType": "accepted", "resultCode": "accepted", "message": "Refunded" } } } Step 4. Handle Each Outcome Response stateWhat to do processed with acceptedMark the refund as complete. processed with declinedKeep the original payment as captured and review the decline reason. processed with errorDo not assume the refund happened. Investigate before retrying. processingPoll GET /transactions/{transaction_id} for the refund transaction. Developer Checkpoints A refund is used after money has been captured. A void is used to cancel an outstanding authorisation before capture. Store both the original transaction ID and the refund transaction ID for reconciliation. ### Separate Authorisation and Capture URL: http://docs.encoded.services/payment-flows/v1/authorise-and-capture Separate Authorisation and Capture Use this flow when you need to reserve funds first and collect them later. This is common where fulfilment, stock checks, or manual review must happen before the cardholder is charged. Flow Overview StepAPI callPurpose 1POST /transactionsCreate an authorise transaction. 2Review the authorisation responseContinue only if the authorisation was accepted. 3POST /transactionsCreate a capture transaction using the authorisation transaction as the source. 4GET /transactions/{transaction_id}Check the capture if it remains processing. Step 1. Authorise the Payment Submit a transaction with action set to authorise. The response reserves the funds but does not move them to the merchant. { "object": "transaction.request", "action": "authorise", "platformType": "moto", "ref": "AUTH-10001", "amount": 45.00, "currency": "GBP", "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111" } } } Step 2. Store the Authorisation Transaction ID The accepted authorisation response contains the transaction id. Store this value against your order because it becomes the source.transaction.id for the capture request. { "object": "transaction", "id": "4b502950-8801-4112-ba15-88f8eb280525", "status": "processed", "response": { "object": "transaction.response", "result": { "object": "result", "resultType": "accepted", "resultCode": "accepted", "message": "Authorised" }, "auth": { "object": "auth", "code": "123456" } } } Step 3. Capture the Authorisation When you are ready to collect the funds, submit a new transaction with action set to capture. Use the authorisation transaction as the source. { "object": "transaction.request", "action": "capture", "ref": "CAPTURE-10001", "amount": 45.00, "currency": "GBP", "source": { "object": "source", "transaction": { "object": "transaction", "id": "4b502950-8801-4112-ba15-88f8eb280525" } } } Step 4. Handle Capture Outcomes Response stateWhat to do processed with acceptedMark the order as captured. processed with declinedDo not fulfil until the capture issue is resolved. processingPoll GET /transactions/{transaction_id} for the capture transaction. Partial and Excessive Capture A lower capture amount can be used for a partial capture. If you capture less than the authorised amount, there is no need to void the remaining amount. The gateway does not currently support excessive capture. If the amount to collect is higher than the authorised amount, void the original authorisation and create a new authorisation, or create an additional authorisation for the difference and capture both authorisations. ### Store a Card URL: http://docs.encoded.services/payment-flows/v1/save-a-card Store a Card Use this flow when you want to create a stored card token that can be used for future payments without collecting the full card details again. Token creation is requested by including source.card.tokenisation on a card-backed transaction. Flow Overview StepAPI callPurpose 1POST /transactionsSubmit a card transaction with tokenisation. 2Read transaction.response.tokenStore the returned token ID. 3GET /tokens/{token_id} or GET /customers/{customer_id}/tokensRetrieve the token later when needed. Step 1. Submit a Tokenising Transaction Use verify if you only need to verify and store the card, or use pay if card storage is part of a payment. The agreement describes how the stored card will be used later. { "object": "transaction.request", "action": "verify", "platformType": "moto", "ref": "SAVE-CARD-10001", "source": { "object": "source", "card": { "object": "card", "pan": "4444333322221111", "expiry": "2028-10", "securityCode": "111", "tokenisation": { "object": "tokenisation", "agreement": "card_on_file", "ref": "TOKEN-10001" } } }, "billingCustomer": { "object": "customer", "ref": "CUST-10001", "forename": "Alex", "surname": "Example" } } Step 2. Store the Token ID When tokenisation succeeds, the transaction response includes the token details. Store the token id against the customer record in your system. { "object": "transaction", "status": "processed", "response": { "object": "transaction.response", "result": { "object": "result", "resultType": "accepted" }, "token": { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd", "ref": "TOKEN-10001", "agreement": "card_on_file", "pan": "444433******1111" } } } Step 3. Retrieve Stored Cards If the token belongs to a customer, retrieve the customer's stored cards before taking a future payment. GET /customers/{customer_id}/tokens You can also retrieve a specific token directly. GET /tokens/{token_id} Developer Checkpoints Use agreement values such as card_on_file, recurring, instalment, or unscheduled to describe the intended future use. Store only the token ID and non-sensitive display details returned by the API. Use verify only when you do not need to take money immediately. ### Stored Card Transaction URL: http://docs.encoded.services/payment-flows/v1/pay-with-a-token Stored Card Transaction Use this flow when a payer has an existing stored card token and you want to process a new payment without collecting the full card details again. Flow Overview StepAPI callPurpose 1GET /customers/{customer_id}/tokensLet the payer or operator choose a stored card. 2POST /transactionsSubmit a pay transaction with source.token. 3GET /transactions/{transaction_id}Check the result if the response is processing. Step 1. Select the Stored Card Retrieve the available customer tokens or use a token ID already stored against your customer record. GET /customers/{customer_id}/tokens The token response contains masked card details that can be displayed safely. { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd", "ref": "TOKEN-10001", "pan": "444433******1111", "expiry": "2028-10", "agreement": "card_on_file" } Step 2. Submit the Stored Card Payment Use source.token.id instead of a direct card source. { "object": "transaction.request", "action": "pay", "platformType": "moto", "ref": "TOKEN-PAY-10001", "amount": 19.99, "currency": "GBP", "source": { "object": "source", "token": { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd" } }, "billingCustomer": { "object": "customer", "id": "7ff16945-db98-4216-af7d-cf6094ae5f61" } } Step 3. Handle Each Outcome Response stateWhat to do processed with acceptedFulfil the stored card payment. processed with declinedAsk for another payment method or a new card. processed with errorInvestigate before retrying the token transaction. processingPoll GET /transactions/{transaction_id}. Security Code Collection If the flow requires a new security code alongside the stored token, collect it using Hosted Payment Fields and submit sources containing both the token and a session source. { "sources": [ { "object": "source", "token": { "object": "token", "id": "09f50370-8d25-43b7-8250-2b2e56b360bd" } }, { "object": "source", "session": { "object": "session", "id": "10b3ca21-d9fd-4030-b5f5-fb45f220a6dd" } } ] } ### Void an Authorisation URL: http://docs.encoded.services/payment-flows/v1/void-an-authorisation Void an Authorisation Use this flow when an accepted authorisation will not be captured. A void attempts to cancel the reserved funds before settlement. Flow Overview StepAPI callPurpose 1Locate the authorisationFind the accepted authorise transaction. 2POST /transactionsSubmit a void transaction using the authorisation as the source. 3GET /transactions/{transaction_id}Check the void if it remains processing. 4Update the orderMark the authorisation as cancelled only after an accepted void. Step 1. Submit the Void The void request references the original authorisation transaction. A void does not require amount. { "object": "transaction.request", "action": "void", "ref": "VOID-10001", "source": { "object": "source", "transaction": { "object": "transaction", "id": "4b502950-8801-4112-ba15-88f8eb280525" } } } Step 2. Read the Void Response { "object": "transaction", "id": "3d32f189-c8d4-48e4-8b0d-9b74b8fb6c02", "status": "processed", "request": { "object": "transaction.request", "action": "void" }, "response": { "object": "transaction.response", "result": { "object": "result", "resultType": "accepted", "resultCode": "accepted", "message": "Voided" } } } Step 3. Handle Each Outcome Response stateWhat to do processed with acceptedMark the authorisation as voided. processed with declinedThe authorisation may still exist. Consider capture or refund rules for the provider. processed with errorInvestigate before retrying. processingPoll GET /transactions/{transaction_id} for the void transaction. Developer Checkpoints Void as soon as possible when an authorisation will not be captured. Use refund instead of void once the payment has been captured. If you perform a partial capture, the remaining authorised amount does not need an additional void. ### Response Codes URL: http://docs.encoded.services/testing/v1/response-codes Response Codes The following response codes are available as part of the transaction response. Response codes provided are translations of the responses received from the underlying gateway and/or card issuer once a transaction has processed. Not all gateways and card issuers will support all response codes. Many gateways and card issuers provide only basic response codes. Responses from the underlying gateway and/or card issuer without a specific response code will be mapped to the closest generic response code. Validation CodeDescription invalid_merchant_accountThe merchant account is incorrectly configured. Contact Encoded Support to rectify. invalid_card_numberThe card number supplied is invalid. invalid_expiry_dateThe expiry date supplied is invalid. invalid_security_codeThe security code supplied is invalid. requires_cardholder_nameNo cardholder name has been provided as part of the billing address for card schemes or transaction types that mandate a cardholder name. insufficient_billing_addressInsufficient billing address details have been provided for card schemes or transaction types that mandate certain address details. invalid_emailThe email supplied is invalid. invalid_phoneThe phone number supplied is invalid. invalid_amountThe amount supplied is invalid. invalid_currencyThe currency supplied is invalid. invalid_source_transactionThe source transaction referenced could not be found. expired_source_transactionThe source transaction referenced has expired. requires_source_transactionA transaction has been attempted that requires a source transaction. excessively_capturedThe transaction attempts to capture more than was authorised. excessively_refundedThe transaction attempts to refund more than was captured. cannot_refundCan not perform a refund on this type of transaction. cannot_voidCan not perform a void on this type of transaction. unsupported_currencyUnsupported currency. expired_cardThe card has expired. requires_security_codeThe security code is required. already_settledThe transaction has already been settled and can not be voided. already_voidedThe transaction has been voided. invalid_3dsThe 3DS details provided were invalid. requires_3dsThe transaction was attempted without 3DSecure. invalid_apple_pay_tokenInvalid Apple Pay token has been provided. invalid_google_pay_tokenInvalid Google Pay token has been provided. expired_google_pay_tokenAn expired Google Pay token has been provided. unsupported_sourceThe source provided for the transaction is unsupported for your account. This could be because it is unsupported by the underlying acquirer and/or gateway configured. unsupported_recurrenceThe type of recurrence attempted is invalid for this card. invalid_requestGeneric invalid request response. Transaction Declined CodeDescription declinedNon-specific declined response. declined_insufficient_fundsDeclined due to insufficient funds. referred_retain_cardThe card should be retained. blocked_blacklistedThe card is on a blacklist. excessively_authedCard authorisation attempt limit reached. excessively_declinedThe card has reached a limit of declines for the card scheme and should continue to be declined. cancelled_continuous_authorityThe continuous authority for this card has been cancelled. incorrect_security_codeThe security code provided is incorrect. incorrect_expiry_dateThe expiry date provided is incorrect. blocked_fraudBlocked due to anti-fraud checks. referredReferral. declined_3dsDeclined by the 3DS2 authentication server prior to the transaction being processed. Errors CodeDescription error_commsError communicating with the issuer. error_systemError in the system. error_unknownAn unknown error has occurred. timeoutThe request has timed out. no_responseThe issuer did not respond. ### Testing URL: http://docs.encoded.services/testing/v1/testing Testing The following test cards can be used to perform test transactions against the SIT environment. Use the specified security code to trigger an approved transaction. SchemeTypeCard numberExpirySecurity code VisaStandard4000000000000002Any valid future expiry123 VisaPrepaid4462030000000000Any valid future expiry444 MastercardStandard5555555555554444Any valid future expiry321 MastercardPrepaid5597507644910558Any valid future expiry888 American ExpressStandard340001916255521Any valid future expiry1234 To force a declined transaction, use security code 999. Only use these cards in the SIT environment. They are not valid production card numbers.