Accept and send payments programmatically
Create a key request from the merchant dashboard and wait for admin approval. The API Secret is shown only once when created or regenerated, so store it securely.
Choose which endpoints your API key can access. Minimum one permission required.
Optionally restrict the API key to your server's public outbound IP address. Do not enter a customer, browser, or CDN address.
Test PayIn and Payout status updates with small amounts, then scale up. Always use HTTPS.
Whitelist the public outbound IP address of the server that sends requests to OESPay. Do not use the customer's IP, browser IP, domain IP, or a CDN/proxy IP.
To check a Linux server's public IPv4 address:
curl -4 -s https://api.ipify.org
Multiple server IP addresses may be added to the same API key. Each API key has its own independent whitelist.
Required Headers:
X-API-Key: oes_your_api_key_here
X-API-Secret: sk_your_secret_here
Each API key can have one or more permissions. The all permission grants full access.
| Permission | Description | Endpoints |
|---|---|---|
| payin | Create and manage payment invoices | /create-invoice, /check-status, /merchant/payins |
| payout | Create and manage payout requests | /payout/create, /merchant/payouts |
| balance | Check balance and statistics | /merchant/balance, /merchant/stats |
| all | Full access to all endpoints | All endpoints |
https://cashwanna.com/api
All endpoints are relative to this base URL.
/create-invoice
Requires: payin
Required Headers:
Content-Type: application/json
X-API-Key: oes_your_api_key_here
X-API-Secret: sk_your_secret_here
{
"amount": 100.00,
"pay_way": "cashapp",
"customer_email": "customer@example.com",
"customer_name": "John Doe",
"redirect_url": "https://merchant.example/payment/return"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | numeric | ✅ Yes | Normally Min: 1, Max: 10000. eCashApp, Apple Pay and Google Pay accept only the exact preset amounts listed below. |
| pay_way | string | ✅ Yes | cashapp, ecashapp, applepay, googlepay, chime, btcpay, paypal, venmo |
| customer_email | string | ❌ No | Valid customer email, maximum 255 characters |
| customer_name | string | ❌ No | Customer name, maximum 255 characters |
| redirect_url | URL | ❌ No | HTTPS return URL after checkout, maximum 2048 characters |
Fee and net values vary according to the authenticated merchant's effective rate.
{
"success": true,
"data": {
"order_id": 123,
"order_no": "API_1788264000_abc123",
"amount": "99.99",
"fee": "14.80",
"net": "85.19",
"pay_way": "applepay",
"payment_url": "https://provider.example/checkout/xxx",
"expires_at": "2026-09-01T12:00:00Z",
"status": "processing"
}
}
{
"success": true,
"data": {
"order_id": 124,
"order_no": "API_1788264000_def456",
"amount": "100.00",
"fee": "10.30",
"net": "89.70",
"pay_way": "chime",
"manual_code": "W6X-F1",
"wallet_address": "$ExampleTag",
"checkout_url": "https://cashwanna.com/checkout/124",
"expires_at": "2026-09-01T20:00:00Z",
"status": "pending_manual"
}
}
/check-status/{order_id}
Requires: payin
{
"success": true,
"data": {
"order_id": 123,
"order_no": "API_1788264000_abc123",
"amount": "99.99",
"real_amount": "99.99",
"fee": "14.80",
"net": "85.19",
"pay_way": "applepay",
"payment_url": "https://provider.example/checkout/xxx",
"manual_code": null,
"status": "success",
"created_at": "2026-09-01T10:00:00Z",
"success_time": "2026-09-01T10:05:00Z",
"expires_at": "2026-09-01T12:00:00Z"
}
}
/merchant/balance
Requires: balance
{
"success": true,
"data": {
"balance": "1500.00",
"bonus_balance": "50.00",
"currency": "USD"
}
}
/merchant/payins
Requires: payin
Query Parameters:
?limit=20&status=success&pay_way=cashapp
limit accepts 1–100 and defaults to 20. Results are returned newest first.
{
"success": true,
"data": {
"total": 45,
"payins": [
{
"id": 123,
"order_no": "API_1706000000_abc123",
"merchant_order_no": "MCH_1706000000_xyz789",
"pay_way": "cashapp",
"amount": "100.00",
"real_amount": "100.00",
"fee": "11.00",
"net": "89.00",
"status": "success",
"cashier_url": "https://provider.example/checkout/xxx",
"created_at": "2026-01-15 10:00:00",
"success_time": "2026-01-15 10:05:00",
"expire_time": "2026-01-15 12:00:00"
}
]
}
}
/merchant/payouts
Requires: payout
Query Parameters:
?limit=20&status=approved&pay_way=chime_payout
limit accepts 1–100 and defaults to 20. Results are returned newest first.
{
"success": true,
"data": {
"total": 12,
"payouts": [
{
"id": 456,
"payout_id": 456,
"transaction_id": "POU-123456",
"amount": "50.00",
"fee": "3.50",
"total_deducted": "53.50",
"pay_way": "chime_payout",
"recipient": "$ExampleTag",
"status": "approved",
"rejection_reason": null,
"invoice_number": "INV-20260906-000456",
"completion_image": "payouts/completed/example.jpg",
"created_at": "2026-09-06 12:49:35",
"approved_at": "2026-09-06 12:52:00",
"completed_at": "2026-09-06 12:52:00"
}
]
}
}
/merchant/stats
Requires: balance
{
"success": true,
"data": {
"balance": "1500.00",
"bonus_balance": "50.00",
"payin": {
"total_count": 45,
"total_amount": "5000.00",
"total_success": "4500.00",
"total_pending": "500.00",
"total_failed": "0.00"
},
"payout": {
"total_count": 12,
"total_amount": "1200.00",
"total_approved": "1100.00",
"total_pending": "100.00",
"total_failed": "0.00"
}
}
}
/merchant/profile
Requires: all
{
"success": true,
"data": {
"id": 12,
"name": "Example Merchant",
"email": "merchant@example.com",
"status": "active"
}
}
/payout/create
Requires: payout
Content-Type: application/json
X-API-Key: oes_your_api_key
X-API-Secret: sk_your_secret
Idempotency-Key: unique_request_id_123
{
"amount": 50.00,
"pay_way": "paypal_payout",
"account_info": "merchant@example.com"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | numeric | ✅ Yes | Min: 10, Max: 5000 |
| pay_way | string | ✅ Yes | cashapp_payout, paypal_payout, ach_payout, card_payout, chime_payout |
| account_info | string | ✅ Yes | Email, tag, or handle |
{
"success": true,
"data": {
"order_id": 456,
"transaction_id": "POU-20260901-A1B2C3D4E5F6-1788264000",
"amount": "50.00",
"fee": "3.50",
"total_deducted": "53.50",
"pay_way": "paypal_payout",
"recipient": "merchant@example.com",
"status": "pending",
"created_at": "2026-09-01 10:00:00"
}
}
Open Merchant Dashboard → API Keys, configure an HTTPS webhook URL, enable delivery, and securely copy the separately generated webhook signing secret.
The webhook secret is different from the X-API-Secret used to call protected API endpoints. Never expose either secret in client-side code.
Webhook delivery applies only to PayIns and Payouts linked to the API key on which the webhook is enabled.
Content-Type: application/json
X-OESPay-Event-Id: 85d5cb6f-93a9-48d4-a2a7-20a9b271111e
X-OESPay-Timestamp: 1788264000
X-OESPay-Signature: sha256=generated_hmac_signature
{
"event_id": "550e8400-e29b-41d4-a716-446655440000",
"event": "payin.status.updated",
"created_at": "2026-09-07T16:57:02+00:00",
"data": {
"local_order_no": "MCH_1788800033_example",
"order_id": "API_1788800033_example",
"transaction_id": 37050,
"status": "failed",
"amount": "20.00",
"real_amount": null,
"fee": "3.10",
"net": "16.90",
"pay_way": "chime",
"admin_notes": "Payment was not received from the provided account.",
"success_time": null
}
}
{
"event_id": "a3d38cb1-7a89-42dd-8fac-e2e017199edb",
"event": "payout.status.updated",
"created_at": "2026-09-07T17:02:00+00:00",
"data": {
"local_order_no": "POU-LOCAL-EXAMPLE",
"payout_id": 456,
"transaction_id": "POU-20260901-A1B2C3D4E5F6-1788264000",
"amount": "50.00",
"fee": "3.50",
"total_deducted": "53.50",
"pay_way": "paypal_payout",
"recipient": "merchant@example.com",
"status": "approved",
"rejection_reason": null,
"invoice_number": "INV-20260907-ABC123",
"completion_image": "https://cashwanna.com/storage/payout-completions/example.jpg",
"completed_at": "2026-09-07T17:01:30+00:00"
}
}
Verification: Calculate HMAC-SHA256 over the exact raw HTTP request body using the separate webhook signing secret. Compare the hexadecimal result with X-OESPay-Signature using a timing-safe comparison. Accept the optional sha256= prefix.
Important: Read the raw body before decoding JSON. Do not re-encode, reformat, sort, or otherwise modify the JSON before calculating the signature.
Acknowledgement: Return any HTTP 2xx response after safely recording the event.
Duplicate protection: Store X-OESPay-Event-Id and ignore an event that has already been processed.
Retries: Delivery is asynchronous and failed deliveries are retried. Your endpoint should acknowledge quickly and process the event idempotently.
Fallback: If a callback is delayed, use GET /check-status/{order_id} for PayIns or GET /merchant/payouts for Payouts.
| Code | HTTP Status | Message |
|---|---|---|
| AUTH_001 | 401 | API key required |
| AUTH_002 | 401 | Invalid API credentials |
| AUTH_003 | 401 | API key is inactive or expired |
| AUTH_004 | 401 | Invalid API credentials |
| AUTH_005 | 403 | Request IP is not allowed |
| AUTH_006 | 403 | Permission denied for this endpoint |
| AUTH_007 | 401 | API secret required |
| AUTH_008 | 403 | Merchant account is inactive |
| AUTH_009 | 403 | API permission configuration missing |
| AUTH_010 | 401 | Merchant not authenticated |
| PAYIN_001 | 422 | Payment method is unavailable |
| PAYIN_002 | 422 | Calculated fee exceeds the invoice amount |
| PAYIN_003 | 502 | Upstream payment provider could not create the invoice |
| PAYIN_004 | 422 | Unsupported payment method |
| PAYIN_005 | 404 | Order not found for the authenticated merchant |
| PAYIN_006 | 503 | No active manual wallet is available |
| PAYIN_007 | 422 | Invalid restricted amount; response includes allowed_amounts |
| PAYOUT_002 | 500 | Temporary payout processing error. Please retry safely with the same Idempotency-Key. |
| PAYOUT_003 | 400 | Payment method not available for payout |
| PAYOUT_004 | 422 | Valid Idempotency-Key header is required |
| PAYOUT_005 | 409 | Idempotency key was already used with different payout data |
| PAYOUT_006 | 422 | Insufficient balance or merchant inactive |
| RATE_001 | 429 | Rate limit exceeded (5000/min) |
| 500 | 500 | Internal server error |
If you exceed this limit, you will receive a 429 Too Many Requests response.
Rate Limit Headers:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
X-RateLimit-Reset: 1706000000