OpenPay API Reference

Developer documentation for the OpenPay payment processing API

OpenPay Public API Documentation

The OpenPay Public API allows merchants to programmatically create payment links, retrieve transaction details, and integrate OpenPay directly into their applications.

Authentication

All API requests must be authenticated using an API Key. You can generate API keys in the Merchant Dashboard under Settings > Developer API.

Include your API key in the x-api-key header of each request.

x-api-key: sk_live_...

Base URL

https://api.openpay.bz/v1

Paylinks

Paylinks are secure, shareable URLs that allow customers to make payments.

Create a Paylink

Creates a new payment link.

Endpoint: POST /paylinks

Request Body:

Field Type Required Description
amount number Yes Payment amount (e.g., 150.00)
currency string Yes Currency code (e.g., "BZD", "USD")
description string No Description of the payment
customer_name string No Name of the customer
customer_email string No Email of the customer for receipts
return_url string No URL to redirect customer after successful payment

Example Request:

curl -X POST https://api.openpay.bz/v1/paylinks \
  -H "x-api-key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 150.00,
    "currency": "BZD",
    "description": "Invoice #1234",
    "customer_name": "John Doe",
    "customer_email": "john@example.com",
    "return_url": "https://myshop.com/success"
  }'

Success Response (201 Created):

{
  "success": true,
  "data": {
    "id": "cafe62fc-11e5-4000-a11b-e95f0f5f54e7",
    "url": "https://merchant.openpay.bz/payment/cafe62fc-11e5-4000-a11b-e95f0f5f54e7",
    "qr_code": "https://api.openpay.bz/qr/cafe62fc-11e5-4000-a11b-e95f0f5f54e7.png",
    "amount": 150.00,
    "currency": "BZD",
    "status": "active",
    "created_at": "2026-02-11T09:30:43.473Z"
  }
}

The qr_code field is a URL to a PNG image that encodes the paylink URL — useful for printing on receipts or displaying on a checkout screen.

Retrieve a Paylink

Retrieves details of a specific paylink.

Endpoint: GET /paylinks/:id

Parameters:

Parameter Type Required Description
id string Yes The ID of the paylink to retrieve

Example Request:

curl -X GET https://api.openpay.bz/v1/paylinks/cafe62fc-11e5-4000-a11b-e95f0f5f54e7 \
  -H "x-api-key: sk_live_..."

Success Response (200 OK):

{
  "success": true,
  "data": {
    "id": "cafe62fc-11e5-4000-a11b-e95f0f5f54e7",
    "url": "https://merchant.openpay.bz/payment/cafe62fc-11e5-4000-a11b-e95f0f5f54e7",
    "qr_code": "https://api.openpay.bz/qr/cafe62fc-11e5-4000-a11b-e95f0f5f54e7.png",
    "amount": 150.00,
    "currency": "BZD",
    "status": "active",
    "description": "Invoice #1234",
    "customer_name": "John Doe",
    "created_at": "2026-02-11T09:30:43.473Z"
  }
}

Direct Payments

Process payments directly through the API without creating a paylink first. This is ideal for integrating payment processing into your application (e.g., food ordering apps, e-commerce checkouts).

Process a Payment

Processes a direct payment with card details.

Endpoint: POST /payments

Request Body:

Field Type Required Description
amount number Yes Payment amount (e.g., 50.00)
currency string Yes Currency code (e.g., "BZD", "USD")
card_number string Yes Full card number (16 digits)
card_expiry_month string Yes Card expiry month (e.g., "12")
card_expiry_year string Yes Card expiry year (e.g., "2025")
card_cvv string Yes Card CVV/CVC code (3-4 digits)
card_holder_name string Yes Name on the card
description string No Description of the payment
customer_name string No Name of the customer
customer_email string No Email of the customer for receipts

Example Request:

curl -X POST https://api.openpay.bz/v1/payments \
  -H "x-api-key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50.00,
    "currency": "BZD",
    "card_number": "4541250000000001",
    "card_expiry_month": "12",
    "card_expiry_year": "2025",
    "card_cvv": "123",
    "card_holder_name": "John Doe",
    "description": "Order #5678",
    "customer_name": "John Doe",
    "customer_email": "john@example.com"
  }'

Success Response (200 OK):

{
  "success": true,
  "data": {
    "transaction_id": "25501adf-48e0-41b7-bbbc-c831de450dd0",
    "status": "completed",
    "message": "Payment processed successfully",
    "gateway_reference": "BPREF-609286",
    "response_code": "APPROVED"
  }
}

Verification Required Response (402 Payment Required):

When a new card is used for the first time, verification is required:

{
  "success": false,
  "error_code": "VERIFICATION_INITIATED",
  "message": "Card verification required. A small random amount has been charged to your card. Please verify the amount to continue.",
  "verification_required": true
}

Error Response (400 Bad Request):

{
  "success": false,
  "message": "Invalid card",
  "response_code": "INVALID_CARD"
}

Rate-Limited / Abuse Block (429 Too Many Requests):

OpenPay's abuse-detection layer transparently rejects requests that look like card-enumeration or velocity attacks. The card, IP, or merchant is blocked for a cooldown window; legitimate retries can resume once the window passes. The message describes the specific block (e.g. too many declines on the same card, or too many cards from the same IP).

{
  "success": false,
  "message": "Too many declined attempts. Please try again later."
}

Test-mode tagging. When the merchant is in test status, every response branch above (200, 402, 400, 429) additionally carries "test_mode": true at the top level. See Test Mode for the simulator behavior.


Transactions

List Transactions

Retrieve a paginated list of your transactions with optional filters. Useful for reconciliation, reporting, and monitoring payment activity.

Endpoint: GET /transactions

Query Parameters:

Parameter Type Required Description
page number No Page number (default: 1)
limit number No Results per page, max 100 (default: 20)
status string No Filter by status: pending, completed, failed, refunded
currency string No Filter by currency: BZD or USD
start_date string No Filter from date (ISO 8601, e.g., 2026-04-01T00:00:00Z)
end_date string No Filter to date (ISO 8601)
paylink_id string No Filter by paylink UUID
transaction_type string No Filter by type: payment, verification, refund, chargeback

Example Request:

curl -X GET "https://api.openpay.bz/v1/transactions?status=completed&start_date=2026-04-01&limit=50" \
  -H "x-api-key: sk_live_..."

Success Response (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "abc-123-...",
      "display_id": "TX1234567890",
      "amount": 50.00,
      "currency": "BZD",
      "status": "completed",
      "transaction_type": "payment",
      "payment_processor": "plug_n_pay",
      "card_type": "Visa",
      "card_last_four": "1234",
      "reference_number": "TX1234567890",
      "created_at": "2026-04-15T14:30:00.000Z",
      "updated_at": "2026-04-15T14:30:02.000Z",
      "metadata": {
        "customer_name": "John Doe",
        "authorization_code": "AUTH123",
        "gateway_reference": "2026041514300000001"
      }
    }
  ],
  "pagination": {
    "total": 142,
    "page": 1,
    "limit": 50,
    "total_pages": 3
  }
}

Get Transaction

Retrieve details for a single transaction by ID.

Endpoint: GET /transactions/:id

Example Request:

curl -X GET "https://api.openpay.bz/v1/transactions/abc-123-..." \
  -H "x-api-key: sk_live_..."

Success Response (200 OK):

{
  "success": true,
  "data": {
    "id": "abc-123-...",
    "amount": 50.00,
    "currency": "BZD",
    "status": "completed",
    "payment_processor": "plug_n_pay",
    "card_type": "Visa",
    "card_last_four": "1234",
    "verification_required": false,
    "created_at": "2026-04-15T14:30:00.000Z",
    "metadata": {
      "customer_name": "John Doe",
      "authorization_code": "AUTH123",
      "gateway_reference": "2026041514300000001"
    }
  }
}

verification_required is true when the transaction is a card-verification micro-charge awaiting amount confirmation. It is false (or omitted) for completed payments.


Card Verification

For security purposes, new cards must be verified before they can be used for payments. The verification process involves charging a small random amount to the card, which the customer must confirm.

The verification amount depends on the merchant's PlugNPay processing currency:

The customer can submit either the exact amount charged or the approximate equivalent in the other currency (to account for bank FX conversions on international card statements).

Verification Flow

  1. Customer attempts a payment with a new card
  2. API responds with 402 status and VERIFICATION_INITIATED error code
  3. A small random amount is charged to the card in the merchant's processing currency
  4. Customer checks their bank statement for the exact amount
  5. Customer submits the verification amount via the completion endpoint
  6. Upon successful verification, the card can be used for future payments

Initiate Card Verification

Manually initiates the card verification process.

Endpoint: POST /cards/verification/initiate

Request Body:

Field Type Required Description
card_number string Yes Full card number (16 digits)
card_expiry_month string Yes Card expiry month (e.g., "12")
card_expiry_year string Yes Card expiry year (e.g., "2025")
card_cvv string Yes Card CVV/CVC code (3-4 digits)
card_holder_name string Yes Name on the card
customer_name string No Name of the customer
customer_email string No Email of the customer

Example Request:

curl -X POST https://api.openpay.bz/v1/cards/verification/initiate \
  -H "x-api-key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "card_number": "4541250000000001",
    "card_expiry_month": "12",
    "card_expiry_year": "2025",
    "card_cvv": "123",
    "card_holder_name": "John Doe",
    "customer_name": "John Doe",
    "customer_email": "john@example.com"
  }'

Success Response (200 OK):

{
  "success": true,
  "message": "Verification initiated. A small random amount has been charged to your card."
}

Complete Card Verification

Completes the card verification by submitting the verification amount.

Endpoint: POST /cards/verification/complete

Request Body:

Field Type Required Description
card_number string Yes Full card number (16 digits)
card_expiry_month string Yes Card expiry month (e.g., "12")
card_expiry_year string Yes Card expiry year (e.g., "2025")
amount number Yes The verification amount from the bank statement (e.g., 3.42 for BZD, 1.71 for USD)

Example Request:

curl -X POST https://api.openpay.bz/v1/cards/verification/complete \
  -H "x-api-key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "card_number": "4541250000000001",
    "card_expiry_month": "12",
    "card_expiry_year": "2025",
    "amount": 3.42
  }'

Success Response (200 OK):

{
  "success": true,
  "message": "Card verified successfully."
}

Error Response - Incorrect Amount (400 Bad Request):

{
  "success": false,
  "message": "Incorrect amount. Please try again.",
  "remaining_attempts": 1
}

Error Response - Card Blocked (400 Bad Request):

After 2 failed verification attempts, the card is blocked:

{
  "success": false,
  "message": "Too many failed attempts. Card blocked.",
  "remaining_attempts": 0
}

Errors

The API uses standard HTTP status codes to indicate the success or failure of requests.

Status Code Description
200 OK - Request succeeded
201 Created - Resource created successfully
400 Bad Request - Invalid parameters or missing fields
401 Unauthorized - Invalid or missing API Key
402 Payment Required - Card verification required
403 Forbidden - Access denied to the resource
404 Not Found - Resource does not exist
429 Too Many Requests - Abuse-detection block (card/IP/merchant velocity)
500 Internal Server Error - Something went wrong on our end

Error Response Body:

{
  "success": false,
  "message": "Description of the error"
}

Test Mode

Merchants with status test can use all API endpoints normally, but no real charges are processed. All gateway calls are simulated and transactions are tagged with test_mode: true in their metadata.

How it works

Controlling simulated outcomes

Use specific card number suffixes to trigger different gateway responses:

Card number suffix Simulated result
Default (e.g., 4111111111111111) Approved
*1000 (e.g., 4111111111111000) Insufficient Funds
*2000 (e.g., 4111111111112000) Declined
*3000 (e.g., 4111111111113000) CVV Mismatch
*4000 (e.g., 4111111111114000) Expired Card
*5000 (e.g., 4111111111115000) Processing Error

Example test-mode response

{
  "success": true,
  "test_mode": true,
  "data": {
    "transaction_id": "abc-123-...",
    "status": "completed",
    "message": "Payment processed successfully",
    "gateway_reference": "TEST-1713200000000",
    "response_code": "APPROVED"
  }
}

Notes