Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/own-pay/OwnPay-Documentation/llms.txt

Use this file to discover all available pages before exploring further.

OwnPay exposes a full-featured HTTP/JSON API that lets you initiate payment intents, query transactions, issue refunds, manage customer profiles, rotate API keys, and inspect webhook delivery logs — all from any language or platform without any proprietary SDK. Every brand operates on its own isolated subdomain, so your API traffic never touches another brand’s data.

Base URL

The API is served from your brand’s own custom domain, configured in Admin → System → Domains:
https://{your_brand_domain}/api/v1
Replace {your_brand_domain} with the domain you configured (e.g. pay.yourbrand.com). Every brand gets a completely isolated API endpoint.

Authentication

All endpoints (except GET /health) require a Bearer API key in the Authorization header:
Authorization: Bearer op.xxxxxxxxxxxxx
API keys carry one or more scopes that control what the key is permitted to do:
ScopeAccess level
readQuery transactions, customers, refunds, delivery logs
writeCreate payments, issue refunds, create customers
adminKey management (must be combined with write)
API keys are shown exactly once at creation time. Copy and store them in a secrets manager (e.g. AWS Secrets Manager, HashiCorp Vault, or a .env file outside version control) immediately. There is no way to retrieve the full key value again.
Key management endpoints (GET /api-keys, POST /api-keys, DELETE /api-keys/{id}) require both the write and admin scopes, plus the X-Super-Admin-Email request header.

Response Format

All responses are JSON. Successful responses wrap the result in a data envelope:
{
  "success": true,
  "data": { ... }
}
Error responses include a human-readable error string, an optional errors array with per-field details, and a request_id for support correlation:
{
  "success": false,
  "error": "amount must be a positive number",
  "errors": [
    {
      "code": "INVALID_AMOUNT",
      "message": "amount must be a positive number",
      "field": "amount"
    }
  ],
  "request_id": "8f5a2e9b0c7d4e5f"
}

HTTP Status Codes

CodeMeaning
200OK — request succeeded
201Created — resource was created
400Bad request or business rule violation
401Missing or invalid API key
403Insufficient scope or permission
404Resource not found (or belongs to another brand)
409Conflict (e.g. duplicate email on customer create)
422Validation failure — check the errors array
500Internal server error
503System degraded — retry with exponential back-off

Endpoints

Health Check

GET /health
endpoint
Returns system status including database connectivity, active gateway count, paired mobile devices, and the running version. No authentication required.
status
string
"healthy" (HTTP 200) or "degraded" (HTTP 503).
version
string
Currently running OwnPay version string.
db
string
Database connection state — "connected" or "error".
mobile
object
Mobile device pairing info.
gateways
integer
Number of active payment gateways configured for the brand.
customers
integer
Total number of customer profiles in the brand.
time
string
ISO 8601 server timestamp at the time of the request.
GET /api/v1/health
{
  "success": true,
  "data": {
    "status": "healthy",
    "version": "0.1.0",
    "db": "connected",
    "mobile": {
      "connected": true,
      "active_devices": 2
    },
    "gateways": 3,
    "customers": 142,
    "time": "2026-06-23T14:15:45Z"
  }
}

Payments

Initiate a Payment Intent

POST /api/v1/payments
Creates a new payment session and returns a secure, white-labeled checkout URL to redirect your customer to. The session remains valid until the customer completes or cancels payment. Request fields:
amount
string
required
Positive numeric string with exactly 2 decimal places. Example: "500.00".
currency
string
required
ISO 4217 currency code supported by your brand. Example: "BDT", "USD".
callback_url
string
Webhook URL for payment.completed callbacks. Must be a valid HTTP or HTTPS URI.
redirect_url
string
Where to send the customer after a successful payment.
cancel_url
string
Where to send the customer if they cancel during checkout.
customer_email
string
Customer email address for identity mapping and masked display.
customer_name
string
Customer full name. Maximum 150 characters.
customer_phone
string
Customer phone number. Maximum 30 characters.
reference
string
Your internal order or invoice identifier. Example: "INV-10029". Stored and returned on the transaction for reconciliation.
gateway
string
Route this payment to a specific gateway by its slug. Example: "bkash-merchant". Omit to let OwnPay auto-select.
metadata
object
Arbitrary key-value map for your own data. Stored on the transaction and returned as-is.
Response fields (201):
payment_id
string
UUID of the created payment intent. Use this to poll status via GET /payments/{payment_id}.
token
string
Short-lived session token embedded in the checkout URL.
checkout_url
string
Fully-formed URL to redirect your customer to. The URL uses your brand’s custom domain.
status
string
Always "created" on a fresh intent.
POST /api/v1/payments
Authorization: Bearer op.xxxxxxxxxxxxx
Content-Type: application/json

{
  "amount": "500.00",
  "currency": "BDT",
  "callback_url": "https://my-store.com/webhooks/ownpay",
  "redirect_url": "https://my-store.com/checkout/success",
  "cancel_url": "https://my-store.com/checkout/cancel",
  "customer_email": "customer@example.com",
  "customer_name": "John Doe",
  "reference": "INV-10029",
  "metadata": {
    "store_id": "dhaka-branch"
  }
}
Redirect your customer to checkout_url immediately after receiving the 201 response. Store the payment_id in your session so you can verify the outcome when the customer returns or when you receive the webhook.

Retrieve Payment Details

GET /api/v1/payments/{payment_id}
Looks up a payment intent by its UUID. If a transaction has been completed, full transaction details are returned; otherwise the pending intent state is returned.
payment_id
string
required
UUID of the payment intent returned by POST /payments.
id
integer
Internal transaction integer ID. null if the payment has not completed.
trx_id
string
OwnPay transaction reference (e.g. "OP-481029304"). null if not completed.
gateway_trx_id
string
Gateway’s own transaction identifier. null if not completed.
amount
string
Transaction amount as a decimal string.
currency
string
ISO 4217 currency code.
fee
string
Gateway fee deducted from the transaction.
status
string
Transaction status: completed, pending, failed, cancelled, or processing.
gateway
string
Gateway slug that processed the payment.
method
string
Payment method used (e.g. "app", "card", "ussd").
reference
string
Your internal order/invoice ID passed at payment creation.
created_at
string
ISO 8601 timestamp when the payment intent was created.
completed_at
string
ISO 8601 timestamp when the payment was completed. null if not completed.
customer
object
Customer identity snapshot.
{
  "success": true,
  "data": {
    "id": 45,
    "trx_id": "OP-481029304",
    "gateway_trx_id": "A8K9D2J3S",
    "amount": "500.00",
    "currency": "BDT",
    "fee": "7.50",
    "status": "completed",
    "gateway": "bkash",
    "method": "app",
    "reference": "INV-10029",
    "created_at": "2026-06-23T14:15:45Z",
    "completed_at": "2026-06-23T14:17:12Z",
    "customer": {
      "name": "John Doe",
      "email": "customer@example.com"
    }
  }
}

Transactions

List Transactions

GET /api/v1/transactions
Returns a paginated list of all completed and in-progress transactions for your brand.
page
integer
Page number. Defaults to 1.
per_page
integer
Records per page. Maximum 100, default 25.
status
string
Filter by status: completed, pending, failed, cancelled, or processing.
gateway
string
Filter by gateway slug (e.g. "bkash", "nagad").
from
string
Start date boundary in YYYY-MM-DD format.
to
string
End date boundary in YYYY-MM-DD format.
GET /api/v1/transactions?status=completed&from=2026-06-01&to=2026-06-30&per_page=50
Authorization: Bearer op.xxxxx

Retrieve a Transaction

GET /api/v1/transactions/{trx_id}
Looks up a single transaction by OwnPay reference (e.g. OP-481029304) or by the gateway’s own transaction ID. OwnPay IDs are matched first.
trx_id
string
required
OwnPay transaction reference (OP-XXXXXXX) or gateway transaction ID.
Returns the same shape as a single item from the list response above.

Refunds

List Refunds

GET /api/v1/refunds
Returns a paginated list of refunds for your brand.
page
integer
Page number, default 1.
per_page
integer
Max 100, default 25.
status
string
Filter: completed, pending, or failed.
trx_id
string
Filter by OwnPay or gateway transaction reference.
transaction_id
integer
Filter by internal transaction integer ID.
from
string
Start date boundary (YYYY-MM-DD).
to
string
End date boundary (YYYY-MM-DD).

Request a Refund

POST /api/v1/refunds
Issues a full or partial refund on a completed transaction. The refund amount cannot exceed the remaining refundable balance on the transaction.
trx_id
string
required
OwnPay transaction reference (OP-12345) or gateway transaction ID. Exactly one of trx_id or transaction_id must be provided.
transaction_id
integer
Alternative identifier: the internal integer transaction ID.
amount
string
Partial refund amount as a decimal string. Omit to issue a full refund for the entire remaining balance.
reason
string
Human-readable reason for the refund. Stored on the refund record.
id
integer
Internal refund integer ID.
uuid
string
Refund UUID.
transaction_id
integer
Internal ID of the parent transaction.
trx_id
string
OwnPay transaction reference.
gateway_trx_id
string
Gateway transaction ID.
amount
string
Refunded amount as a decimal string.
reason
string
Reason provided at refund creation.
status
string
Refund status: completed, pending, or failed.
processed_at
string
ISO 8601 timestamp when the refund was processed by the gateway.
created_at
string
ISO 8601 timestamp when the refund record was created.
POST /api/v1/refunds
Authorization: Bearer op.xxxxx
Content-Type: application/json

{
  "trx_id": "OP-481029304",
  "amount": "150.00",
  "reason": "Customer requested return"
}

Retrieve a Refund

GET /api/v1/refunds/{trx_id}
Returns the latest refund record for a transaction, identified by OwnPay or gateway transaction ID.
trx_id
string
required
OwnPay transaction reference or gateway transaction ID.

Customers

Customer PII (name, email, phone) is stored AES-256-GCM encrypted at rest. Decryption happens only on explicit single-record retrieval — the list endpoint returns masked values for safe display.

List Customers

GET /api/v1/customers
Returns masked PII in the list (email_masked, phone_masked). Full values require a dedicated lookup via GET /customers/{identifier}.
page
integer
Page number, default 1.
per_page
integer
Records per page, default 25.
{
  "success": true,
  "data": [
    {
      "id": 58,
      "uuid": "83b9c9d2-b2f4-4df1-bc1e-b810d1c810d1",
      "name": "Alice Smith",
      "email_masked": "a***e@example.com",
      "phone_masked": "+88018******00",
      "created_at": "2026-06-23T14:15:45Z"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 98
  }
}

Create a Customer

POST /api/v1/customers
Creates a new customer profile. Email must be unique within the brand. Returns the new record’s id and uuid — full PII is not echoed back.
name
string
required
Customer full display name.
email
string
Customer email address. Must be unique per brand. Returns 409 on duplicate.
phone
string
Customer phone number.
{
  "success": true,
  "data": {
    "id": 58,
    "uuid": "83b9c9d2-b2f4-4df1-bc1e-b810d1c810d1"
  }
}

Retrieve a Customer

GET /api/v1/customers/{identifier}
Looks up a customer by email address or phone number (URL-encoded). Returns fully decrypted PII. If the identifier contains @ it is resolved via email hash; otherwise via phone number hash.
identifier
string
required
URL-encoded email address (e.g. customer%40example.com) or phone number.
GET /api/v1/customers/customer%40example.com
Authorization: Bearer op.xxxxxx

API Keys

All key management endpoints require both the write and admin scopes on your API key, plus the X-Super-Admin-Email header set to the super-admin email address of the brand.

List API Keys

GET /api/v1/api-keys
X-Super-Admin-Email: admin@yourdomain.com
Returns metadata for all brand API keys. Key secrets are never returned in any response.
{
  "success": true,
  "data": [
    {
      "id": 4,
      "name": "POS-System-Integration",
      "prefix": "op.xxx",
      "status": "active",
      "last_used": "2026-06-23T14:18:22Z",
      "expires_at": null,
      "created_at": "2026-06-21T09:00:00Z"
    }
  ]
}

Generate an API Key

POST /api/v1/api-keys
X-Super-Admin-Email: admin@yourdomain.com
name
string
Friendly label for the key to help identify its purpose (e.g. "POS-System-Integration").
scopes
string[]
Array of scopes to grant. Valid combinations: ["read"], ["read","write"], or ["read","write","admin"].
The full key value is returned exactly once in the 201 response. It cannot be retrieved again. Store it immediately in your secrets manager.
{
  "success": true,
  "data": {
    "key": "op.xxxxx.xxxxxx",
    "prefix": "op.xxxxxx",
    "warning": "Store this key securely. It cannot be retrieved again."
  }
}

Revoke an API Key

DELETE /api/v1/api-keys/{id}
X-Super-Admin-Email: admin@yourdomain.com
Revokes a key immediately by its integer ID. All subsequent requests using the revoked key will receive 401 Unauthorized.
id
integer
required
Integer ID of the API key to revoke (see id from the list response).

Webhooks

Dispatch a Test Webhook

POST /api/v1/webhooks/tests
Fires a sample payment.completed payload to your configured brand callback URL. Useful for verifying that your endpoint is reachable and returns a 2xx status.
status_code
integer
HTTP status code returned by your webhook endpoint.
response_time_ms
integer
Round-trip time in milliseconds from OwnPay’s server to your endpoint.
{
  "success": true,
  "data": {
    "status_code": 200,
    "response_time_ms": 245
  }
}

Webhook Delivery Log

GET /api/v1/webhooks/deliveries
Returns the 50 most recent webhook delivery attempts for your brand, including the full payload sent, the HTTP status received, retry count, and delivery status.
id
integer
Internal delivery attempt ID.
transaction_id
integer
ID of the transaction that triggered the delivery.
event
string
Event type — currently always "payment.completed".
url
string
Webhook URL the payload was delivered to.
payload
string
JSON string of the payload that was sent.
response_status
integer
HTTP status code returned by your endpoint.
response_body
string
First portion of the response body from your endpoint.
attempts
integer
Number of delivery attempts made so far.
status
string
Delivery status: "success" or "failed".
created_at
string
ISO 8601 timestamp of the first delivery attempt.
{
  "success": true,
  "data": [
    {
      "id": 1024,
      "transaction_id": 45,
      "event": "payment.completed",
      "url": "https://my-store.com/webhooks/ownpay",
      "payload": "{\"event\":\"payment.completed\",\"data\":{\"trx_id\":\"OP-481029304\",\"amount\":\"500.00\"}}",
      "response_status": 200,
      "response_body": "OK",
      "attempts": 1,
      "status": "success",
      "created_at": "2026-06-23T14:17:15Z"
    }
  ]
}

Webhook Events

OwnPay POSTs a JSON payload to your callback_url when a payment is completed. Your endpoint must return an HTTP 2xx status within 10 seconds. Failed deliveries are retried automatically — check the delivery log for retry history.

payment.completed Payload

{
  "event": "payment.completed",
  "data": {
    "trx_id": "OP-481029304",
    "gateway_trx_id": "A8K9D2J3S",
    "amount": "500.00",
    "currency": "BDT",
    "status": "completed",
    "reference": "INV-10029",
    "gateway": "bkash"
  }
}
Always verify a webhook by querying GET /payments/{payment_id} or GET /transactions/{trx_id} before fulfilling an order. Never trust the webhook payload alone — it could be replayed or forged by a third party.

Quick Reference

EndpointMethodRequired Scope
GET /healthSystem healthNone
POST /paymentsInitiate payment intentwrite
GET /payments/{id}Payment detailsread
GET /transactionsList transactionsread
GET /transactions/{id}Single transactionread
GET /refundsList refundsread
POST /refundsRequest a refundwrite
GET /refunds/{id}Single refundread
GET /customersList customersread
POST /customersCreate customerwrite
GET /customers/{id}Customer detailsread
GET /api-keysList API keyswrite + admin
POST /api-keysGenerate API keywrite + admin
DELETE /api-keys/{id}Revoke API keywrite + admin
POST /webhooks/testsTest webhook deliverywrite
GET /webhooks/deliveriesDelivery logread

Build docs developers (and LLMs) love