Xtopay
Payment APIs

Online Checkout

Integrate online payments into any application using Xtopay's hosted checkout page or embedded onsite iframe.

Online Checkout

The Online Checkout API allows merchants to accept online payments for goods and services. It creates a secure, hosted payment session that supports:

  • Mobile Money: MTN Mobile Money, Telecel Cash, AT Money (AirtelTigo)
  • Bank Cards: Visa, Mastercard, Verve
  • Wallets: Xtopay Wallets, G-Money, Zeepay
  • GhQR & Bank Transfers

This API offers RESTful endpoints that integrate online payments into any application. You may implement the Xtopay Online Checkout using one of two patterns:

  1. Redirect Checkout: Redirect the customer to a secure checkout page hosted by Xtopay to take payment.
  2. Onsite Checkout: Load the Xtopay checkout flow directly on your own website inside an iframe or modal.

Redirect Checkout - How It Works

  1. A customer arrives on your website and clicks on a pay button.
  2. Your backend server sends a request to POST /v1/payments to initiate a payment session.
  3. Xtopay returns a secure checkoutUrl and a unique transaction reference.
  4. You redirect the customer to the checkoutUrl.
  5. The customer selects how they wish to pay (e.g. entering their mobile money number).
  6. The customer verifies their identity and authorizes the payment (e.g. by completing a USSD push PIN prompt on their phone or entering an OTP).
  7. When payment is completed, a success or failure notification is presented to the customer.
  8. Xtopay dispatches a webhook notification to your registered webhook URL.
  9. The customer is redirected back to your website via the return URL specified in your request metadata.

Redirect Checkout Request Flow

sequenceDiagram
    autonumber
    actor Customer
    participant MerchantSite as Merchant Website
    participant MerchantServer as Merchant Server
    participant Xtopay as Xtopay API
    participant Telco as Telco / Bank Partner

    Customer->>MerchantSite: Click Pay Button
    MerchantSite->>MerchantServer: Initiate payment request
    MerchantServer->>Xtopay: POST /v1/payments (Auth: Bearer secret_key)
    Xtopay-->>MerchantServer: Return checkoutUrl & reference
    MerchantServer-->>MerchantSite: Redirect to checkoutUrl
    MerchantSite-->>Customer: Redirect to Xtopay hosted page
    Customer->>Xtopay: Select payment method & submit details
    Xtopay->>Telco: Trigger charge request (USSD Push / Card Auth)
    Telco-->>Customer: Receive USSD PIN Prompt / OTP
    Customer->>Telco: Approve transaction (Enter PIN / OTP)
    Telco-->>Xtopay: Authorization success notification
    Xtopay-->>Customer: Display success/failure status screen
    Xtopay->>MerchantServer: Webhook callback (POST payment.succeeded)
    Customer->>MerchantSite: Redirect back via returnUrl (metadata)

Onsite Checkout - How It Works

  1. A customer arrives on your website and clicks on a pay button.
  2. Your backend server initiates the payment session with Xtopay and returns the checkoutUrl to your frontend.
  3. Your website loads the checkoutUrl inside an iframe or modal directly on your checkout page.
  4. The customer selects their payment method and completes the transaction inside the iframe (e.g. scanning a GhQR code or entering their mobile wallet details).
  5. The customer completes the OTP or USSD authentication prompt on their mobile device.
  6. Xtopay dispatches a webhook notification to your registered webhook URL.
  7. The iframe emits completion events back to the parent window (via window.parent.postMessage), allowing you to smoothly transition the checkout page onsite.

Onsite Checkout Request Flow

sequenceDiagram
    autonumber
    actor Customer
    participant MerchantSite as Merchant Website
    participant Iframe as Xtopay Iframe
    participant MerchantServer as Merchant Server
    participant Xtopay as Xtopay API

    Customer->>MerchantSite: Click Pay Button
    MerchantSite->>MerchantServer: Request payment session
    MerchantServer->>Xtopay: POST /v1/payments
    Xtopay-->>MerchantServer: Return checkoutUrl & reference
    MerchantServer-->>MerchantSite: Return checkoutUrl
    MerchantSite->>Iframe: Load checkoutUrl in Iframe
    Customer->>Iframe: Select method & authorize transaction
    Xtopay->>MerchantServer: Webhook callback (POST payment.succeeded)
    Iframe-->>MerchantSite: postMessage event (payment.succeeded)
    MerchantSite->>Customer: Show custom success view onsite

[!NOTE] Mandatory Fallback Check In instances where a merchant does not receive the final status webhook callback within five (5) minutes from Xtopay, it is mandatory to perform a transaction status check using the Transaction Status Check API to determine the final status of the transaction.


API Reference

To initiate a transaction, send an HTTP POST request to the below URL with the required parameters in the JSON payload.

DetailDescription
API Endpointhttps://api.xtopay.co/v1/payments
Request TypePOST
Content Typeapplication/json
AuthenticationBasic Base64(clientId:clientSecret)

Request Parameters

ParameterTypeRequiredDescription
amountIntegerYesSpecifies the total amount expected to be paid for the items being purchased, in minor units (e.g. 5000 = GHS 50.00). Decimals are not allowed.
currencyStringNoThree-letter ISO 4217 currency code (e.g. GHS, NGN, USD). Case-insensitive. Defaults to GHS.
descriptionStringNoA brief description of the transaction shown to the customer on the checkout page (max 255 characters).
customerObjectNoRecommended. An object containing the customer details. Structure detailed below.
customer.nameStringYes*Customer's full name. *Mandatory if the customer object is provided.
customer.emailStringYes*Customer's email address. *Mandatory if the customer object is provided.
customer.phoneStringNoCustomer's mobile number.
metadataObjectNoFlat JSON key-value store to attach merchant references. Tip: include orderId and returnUrl (e.g., { "orderId": "inv0012", "returnUrl": "https://merchant.com/checkout/success" }).

Response Parameters

ParameterTypeDescription
successBooleanIndicates if the checkout session was created successfully.
dataObjectContains the checkout session details.
data.idStringUnique transaction ID generated by Xtopay.
data.referenceStringUnique reference matching the transaction ID.
data.statusStringInitial status of the checkout session (always PENDING).
data.amountIntegerIngested amount in minor units.
data.currencyStringIngested currency code.
data.descriptionStringIngested description.
data.checkoutUrlStringSecure URL where the payee should be redirected to make payment.
data.metadataObjectFlattened custom key-values attached to this payment.
data.createdAtStringISO 8601 creation timestamp.
data.customerObjectSanitized customer profile matching the created session.

Code Examples

curl https://api.xtopay.co/v1/payments \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 10000,
    "currency": "GHS",
    "description": "Book Shop Checkout",
    "customer": {
      "name": "Kwame Mensah",
      "email": "kwame@example.com",
      "phone": "+233241234567"
    },
    "metadata": {
      "orderId": "inv0012",
      "returnUrl": "https://merchant.com/checkout/success"
    }
  }'

Sample Response

201 Created

{
  "success": true,
  "data": {
    "id": "pay_cl8z2e8z20000g",
    "reference": "cl8z2e8z20000g",
    "status": "PENDING",
    "environment": "LIVE",
    "method": null,
    "amount": 10000,
    "currency": "GHS",
    "fee": 0,
    "net": 10000,
    "description": "Book Shop Checkout",
    "metadata": { 
      "orderId": "inv0012",
      "returnUrl": "https://merchant.com/checkout/success"
    },
    "failureCode": null,
    "failureMessage": null,
    "paidAt": null,
    "createdAt": "2026-06-06T12:00:00Z",
    "updatedAt": "2026-06-06T12:00:00Z",
    "customer": {
      "id": "cust_cl8z2e9z",
      "name": "Kwame Mensah",
      "email": "kwame@example.com",
      "phone": "+233241234567"
    },
    "refunds": [],
    "checkoutUrl": "https://pay.xtopay.co/cl8z2e8z20000g"
  }
}

Checkout Callback (Webhooks)

You should register a webhook endpoint in your merchant dashboard to receive asynchronous payment status notifications. When a customer completes payment, Xtopay dispatches an HTTP POST payload containing the transaction's final status to your webhook url.

Sample Webhook Payload

{
  "event": "payment.succeeded",
  "data": {
    "id": "pay_cl8z2e8z20000g",
    "reference": "cl8z2e8z20000g",
    "status": "SUCCEEDED",
    "environment": "LIVE",
    "method": "MOBILE_MONEY",
    "amount": 10000,
    "currency": "GHS",
    "fee": 150,
    "net": 9850,
    "description": "Book Shop Checkout",
    "metadata": {
      "orderId": "inv0012",
      "returnUrl": "https://merchant.com/checkout/success"
    },
    "paidAt": "2026-06-06T12:02:11Z",
    "customer": {
      "id": "cust_cl8z2e9z",
      "name": "Kwame Mensah",
      "email": "kwame@example.com",
      "phone": "+233241234567"
    },
    "mobileMoneyDetail": {
      "network": "MTN",
      "phone": "+233241234567",
      "externalRef": "0000006824852622"
    }
  }
}

Transaction Status Check

It is mandatory to implement the Transaction Status Check API. Use this to poll the transaction state in rare instances where your server does not receive the webhook callback from Xtopay within five (5) minutes.

To check the status of a transaction, send an HTTP GET request to the endpoint below, appending the transaction's reference as a path parameter.

DetailDescription
API Endpointhttps://api.xtopay.co/v1/payments/:reference
Request TypeGET
Content Typeapplication/json
AuthenticationBasic Base64(clientId:clientSecret)

Request Parameters

ParameterTypeRequiredDescription
:referenceStringYesThe unique reference of the payment session (e.g. cl8z2e8z20000g).

Sample GET Request

curl https://api.xtopay.co/v1/payments/cl8z2e8z20000g \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET"

Response Parameters

The GET endpoint returns the fully resolved payment record, including processor details (e.g. mobileMoneyDetail or cardDetail) and platform fees once processed.

Sample Response (Paid)

200 OK

{
  "success": true,
  "data": {
    "id": "pay_cl8z2e8z20000g",
    "reference": "cl8z2e8z20000g",
    "status": "SUCCEEDED",
    "environment": "LIVE",
    "method": "MOBILE_MONEY",
    "amount": 10000,
    "currency": "GHS",
    "fee": 150,
    "net": 9850,
    "description": "Book Shop Checkout",
    "metadata": {
      "orderId": "inv0012"
    },
    "paidAt": "2026-06-06T12:02:11Z",
    "createdAt": "2026-06-06T12:00:00Z",
    "customer": {
      "id": "cust_cl8z2e9z",
      "name": "Kwame Mensah",
      "email": "kwame@example.com"
    },
    "mobileMoneyDetail": {
      "network": "MTN",
      "phone": "+233241234567",
      "externalRef": "0000006824852622"
    }
  }
}

Sample Response (Unpaid / Pending)

200 OK

{
  "success": true,
  "data": {
    "id": "pay_cl8z2e8z20000g",
    "reference": "cl8z2e8z20000g",
    "status": "PENDING",
    "environment": "LIVE",
    "method": null,
    "amount": 10000,
    "currency": "GHS",
    "fee": 0,
    "net": 10000,
    "description": "Book Shop Checkout",
    "metadata": {
      "orderId": "inv0012"
    },
    "paidAt": null,
    "createdAt": "2026-06-06T12:00:00Z",
    "customer": {
      "id": "cust_cl8z2e9z",
      "name": "Kwame Mensah",
      "email": "kwame@example.com"
    }
  }
}

Response Codes & Actions

The Xtopay Sales API uses standard HTTP error reporting. Successful requests return HTTP status codes in the 2xx range. Failed requests return status codes in 4xx and 5xx ranges. Standard response error bodies contain a message describing the failure. In transaction callbacks and status reports, you may consult the following code mapping:

Response CodeDescriptionRequired Action
0000Request accepted or processed successfully.None. You can proceed with fulfilling the order.
0005connection error occurred when reaching the telco or card network.The transaction status is unknown. Perform a Status Check or contact support to confirm.
2001Transaction failed (e.g. customer entered an invalid PIN, has insufficient funds, or the session timed out).Instruct customer to verify their wallet balance, check their PIN, or try another payment method.
4000Validation errors. Something is incorrect in the request payload.Check that the amount is a positive integer and that customer credentials are correct.
4070declined by gateway. Gateway fees not configured or minimum transaction amount not met.Contact your Xtopay relationship manager to verify fee configurations.

How is this guide?

Edit this page on GitHub
Last updated on June 6, 2026

On this page