External API — Partner Integration Guide
Create invoices, query status, share payment links, and receive signed webhooks.
| Environment | Base URL |
|---|---|
| Production | https://integration.rsompay.com/api/external/v1 |
| Sandbox | https://demo-integration.rsompay.com/api/external/v1 |
| Environment | Payment URL pattern |
|---|---|
| Production | https://payment.rsompay.com/pay/invoice/{token} |
| Sandbox | https://demo-payment.rsompay.com/pay/invoice/{token} |
| Item | Description |
|---|---|
| External client account | Provisioned by RsomPay for B2B integration |
| Integration API token | Bearer token named client-external-api |
| Webhook signing secret | Provided by RsomPay IT on onboarding — used with header X-Rsom-Signature (see §7.5) |
flowchart TB
subgraph partner [Partner system]
ERP[ERP backend]
WH[Webhook endpoint]
RET[return_url handler]
end
subgraph rsom [RsomPay]
INT[integration.rsompay.com]
PAY[payment.rsompay.com]
end
ERP -->|POST /invoices| INT
INT -->|payment_url| ERP
ERP -->|share link| PAY
PAY -->|browser redirect first| RET
RET -->|GET by-reference| INT
INT -.->|webhook later async| WH
Send the integration token on every request:
Authorization: Bearer YOUR_CLIENT_EXTERNAL_API_TOKEN Content-Type: application/json Accept: application/json
client-external-api.403.client_invoices.create, client_invoices.view.curl -X POST "https://integration.rsompay.com/api/external/v1/invoices" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d @invoice.json
Successful responses:
{
"status": true,
"message": "Mission completed successfully",
"data": { }
}
Paginated GET /transactions adds meta: total, per_page, current_page, last_page.
POST /invoices
| Field | Required | Type | Description |
|---|---|---|---|
external_id | Yes | string | Partner idempotency key. Max 255. Unique per client; duplicates return the same invoice. |
notification_url | Yes | URL | HTTPS webhook endpoint. Publicly reachable; no localhost/private IPs. Max 2048. |
return_url | Yes | URL | HTTPS customer redirect after checkout. Max 2048. |
customer | Yes | object | Customer block — see table below. |
items | Yes | array | Line items — min 1 object; see table below. |
currency_code | No | string | Currency code. Max 8. Default SAR. |
due_date | No | date | Due date YYYY-MM-DD. |
issued_date | No | date | Issue date YYYY-MM-DD. |
notes | No | string | Invoice notes. Max 2000. |
customer)| Field | Required | Type | Description |
|---|---|---|---|
customer.fullname | Yes | string | Full name on payment page. Max 255. |
customer.id | Yes | string | Your stable customer reference (e.g. CUST-9). Max 255. |
customer.email | No | string | Valid email. Max 255. |
customer.phone | No | string | Phone (e.g. +966501234567). Max 32. |
items[])Each array element is one line item. At least one item is required.
| Field | Required | Type | Description |
|---|---|---|---|
items[].description | Yes | string | Line description. Max 255. |
items[].quantity | No | number | Qty. Min 0.001. Default 1. |
items[].unit_price | Yes | number | Unit price before discount and tax. Min 0.01. Invoice total is computed from all lines. |
items[].discount_amount | No | number | Line discount amount. Min 0. |
items[].tax_rate | No | number | Tax % (e.g. 15 = 15% VAT). |
items[].item_type | No | string | Category label (e.g. service). Max 32. |
items[].reference_id | No | string | Your line reference. Max 128. |
external_id → 201, same invoice, no duplicate.issued.amount field — each line requires unit_price. data.amount and data.totals.grand_total are computed from lines (must be > 0).One line: qty 1, unit 100, discount 10, tax 15% → grand_total: 103.5
{
"external_id": "INV-PARTNER-001",
"notification_url": "https://partner.example.com/webhooks/rsom",
"return_url": "https://partner.example.com/payment/return",
"currency_code": "SAR",
"due_date": "2026-12-31",
"issued_date": "2026-05-18",
"notes": "Optional invoice note",
"customer": {
"id": "CUST-9",
"fullname": "Ahmed Ali",
"email": "customer@example.com",
"phone": "+966501234567"
},
"items": [
{
"description": "Service fee",
"item_type": "service",
"quantity": 1,
"unit_price": 100,
"discount_amount": 10,
"tax_rate": 15,
"reference_id": "LINE-1"
}
]
}
{
"status": true,
"message": "Mission completed successfully",
"data": {
"external_id": "INV-PARTNER-001",
"reference_number": "INV-42-001",
"status": "issued",
"amount": 103.5,
"payment_url": "https://payment.rsompay.com/pay/invoice/...",
"customer": {
"id": "CUST-9",
"fullname": "Ahmed Ali",
"email": "customer@example.com",
"phone": "+966501234567"
},
"totals": {
"subtotal": 100,
"discount_total": 10,
"tax_total": 13.5,
"grand_total": 103.5
},
"items": [
{
"description": "Service fee",
"item_type": "service",
"quantity": 1,
"unit_price": 100,
"discount_amount": 10,
"tax_rate": 15,
"tax_amount": 13.5,
"total_amount": 103.5,
"reference_id": "LINE-1"
}
]
}
}
GET /invoices/by-reference?{parameter}={value}
Look up an invoice by your reference. Use this after webhooks or before fulfilling an order.
Provide exactly one query parameter:
| Parameter | Description |
|---|---|
external_id | Your idempotency key (recommended) |
reference_number | RsomPay invoice number (e.g. INV-42-001) |
GET /invoices/by-reference?external_id=INV-PARTNER-001 GET /invoices/by-reference?reference_number=INV-42-001
data object is the same as POST /invoices (create invoice). Only HTTP status differs: 200 OK here vs 201 Created on create. Fields such as status reflect the current invoice state (e.g. issued before payment, paid after).
{
"status": true,
"message": "Mission completed successfully",
"data": {
"external_id": "INV-PARTNER-001",
"reference_number": "INV-42-001",
"status": "paid",
"amount": 103.5,
"payment_url": "https://payment.rsompay.com/pay/invoice/...",
"customer": {
"id": "CUST-9",
"fullname": "Ahmed Ali",
"email": "customer@example.com",
"phone": "+966501234567"
},
"totals": {
"subtotal": 100,
"discount_total": 10,
"tax_total": 13.5,
"grand_total": 103.5
},
"items": [
{
"description": "Service fee",
"item_type": "service",
"quantity": 1,
"unit_price": 100,
"discount_amount": 10,
"tax_rate": 15,
"tax_amount": 13.5,
"total_amount": 103.5,
"reference_id": "LINE-1"
}
]
}
}
| HTTP | Cause |
|---|---|
422 | No query parameter — provide external_id or reference_number |
404 | Invoice not found for your client |
List customer payments across your invoices.
GET /transactions?customer_id={id}&page=1&per_page=20
| Parameter | Required | Default | Max |
|---|---|---|---|
customer_id | Yes | — | 255 |
page | No | 1 | — |
per_page | No | 20 | 100 |
Same envelope as other endpoints (status, message, data). data is an array of payment records; paginated responses include meta. payment_method reflects how the customer paid — e.g. card or tamara.
{
"status": true,
"message": "Mission completed successfully",
"data": [
{
"reference": "TX-REF-1",
"status": "completed",
"amount": 103.5,
"currency_code": "SAR",
"payment_method": "card",
"invoice_external_id": "INV-PARTNER-001",
"captured_at": "2026-05-18 12:00:00",
"created_at": "2026-05-18 11:55:00"
},
{
"reference": "TX-REF-2",
"status": "completed",
"amount": 250,
"currency_code": "SAR",
"payment_method": "tamara",
"invoice_external_id": "INV-PARTNER-002",
"captured_at": "2026-05-17 15:30:00",
"created_at": "2026-05-17 15:28:00"
}
],
"meta": {
"total": 2,
"per_page": 20,
"current_page": 1,
"last_page": 1
}
}
RsomPay POSTs to your notification_url after payment activity. No webhook is sent when the invoice is created. Delivery is asynchronous — respond with HTTP 2xx quickly.
| Event | When |
|---|---|
invoice.status_changed | Status changes after payment (previous_status in payload) |
payment.completed | Payment succeeded |
payment.failed | Payment failed |
POST {notification_url}
Content-Type: application/json
X-Rsom-Signature: a1b2c3d4e5f6...
Event details are in the JSON body. For authenticity, read header X-Rsom-Signature (see §7.5).
{
"event": "payment.completed",
"event_id": "550e8400-e29b-41d4-a716-446655440000",
"occurred_at": "2026-05-18T12:00:00+00:00",
"customer": { "id": "CUST-9", "fullname": "Ahmed Ali", ... },
"totals": { "subtotal": 100, "discount_total": 10, "tax_total": 13.5, "grand_total": 103.5 },
"invoice": {
"external_id": "INV-PARTNER-001",
"reference_number": "INV-42-001",
"status": "paid",
"amount": 103.5,
"payment_url": "https://payment.rsompay.com/pay/invoice/..."
},
"payment": {
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"payment_method": "card",
"status": "completed",
"amount": 103.5,
"paid_at": "2026-05-18 12:00:00"
}
}
payment_method reflects how the customer paid — e.g. card (Mada/Visa/Mastercard), tamara (Tamara BNPL). Card payments may also return a specific brand when available (e.g. mada, visa).
2xx within a few seconds.event_id in the JSON body.X-Rsom-Signature before trusting the body (see §7.5).X-Rsom-Signature)RsomPay includes a signature on every webhook so you can confirm the request is genuine.
| Header | Value |
|---|---|
X-Rsom-Signature |
Signature sent by RsomPay. Read this header from the incoming request and verify it on your server before processing the JSON body. |
Webhook signing secret and how to verify are provided by RsomPay when your integration is set up. Request them from your integration / IT contact or tech@bseeds.sa.
event_id across retries — deduplicate on your side.payment_url.payment.rsompay.com.return_url with query parameters (UX only).GET /invoices/by-reference (primary) — call from your return_url handler or right after redirect.payment.completed / payment.failed arrives later, asynchronously on notification_url (after the redirect).return_url first. RsomPay sends the webhook to notification_url afterward (async). Do not wait for the webhook on the return page — confirm with GET /invoices/by-reference first.
On your return_url page, use GET /invoices/by-reference as your main check before you fulfill an order:
GET /invoices/by-reference?external_id=INV-PARTNER-001
Confirm data.status is paid. Poll briefly if status is still issued or pending (payment may still be confirming).
| Channel | When | Role |
|---|---|---|
return_url | Right after checkout | UX — show success/failure; not proof of payment alone |
GET /invoices/by-reference | On return page (primary) | Authoritative — confirm paid before fulfilling |
Webhook payment.completed | Later (async) | Backup — optional reconciliation; still use by-reference if webhook is delayed |
| Parameter | Description |
|---|---|
status | success, failed, or pending |
external_id | Your invoice id |
reference_number | RsomPay invoice number (e.g. INV-42-001) |
payment_reference | Payment reference (if available) |
amount_paid | Amount for this payment |
currency_code | e.g. SAR |
payment_method | How the customer paid — e.g. card, tamara, or card brand (mada, visa, …) when available |
https://partner.example.com/payment/return?status=success&external_id=INV-PARTNER-001&reference_number=INV-42-001&payment_reference=GW-123&amount_paid=103.5¤cy_code=SAR&payment_method=card
On data.status and webhook invoice.status for external API invoices:
| Status | Meaning |
|---|---|
issued | Issued — awaiting payment |
paid | Paid in full |
canceled | Cancelled — do not collect |
failed | Last payment attempt failed; customer may try again via payment_url |
| HTTP | Typical cause |
|---|---|
401 | Missing or invalid token |
403 | Wrong token type or suspended client |
404 | Invoice not found |
422 | Validation error |
500 | Server error |
| Issue | Fix |
|---|---|
| URL rejected | notification_url / return_url must be HTTPS and publicly reachable |
| by-reference 422 | Provide external_id or reference_number |
customer_id on by-reference | Not supported — use GET /transactions instead |
Validation messages may be localized — rely on HTTP status and field keys.
client-external-api token from RsomPay.X-Rsom-Signature (see §7.5).POST /invoices with a unique external_id — save payment_url.GET /invoices/by-reference?external_id=... — confirm status is issued.payment_url.return_url with query parameters (happens before webhook).GET /invoices/by-reference from your return handler — status is paid.payment.completed webhook on notification_url arrives later (if delivered).Guide version v1.0.1 — API base path /api/external/v1 (unchanged).
| Method | Path | Purpose |
|---|---|---|
POST | /invoices | Create invoice |
GET | /invoices/by-reference | Query status (external_id or reference_number) |
GET | /transactions | Customer transactions (customer_id required) |
| Production | Sandbox | |
|---|---|---|
| Integration API | integration.rsompay.com | demo-integration.rsompay.com |
| Payment page | payment.rsompay.com | demo-payment.rsompay.com |
Download Postman collection (JSON)
customer_id in Postman is only for GET /transactions, not invoice lookup.
Technical support: tech@bseeds.sa
Website: https://rsompay.com
| Date | Notes |
|---|---|
| 2026-05-19 | Guide v1.0.1 — partner-facing fields, payment flow, webhook signature docs |
| 2026-05-18 | Initial partner guide; docs site split to static hosting (docs.rsompay.com) |