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. Some wallets accept only the exact preset amounts listed below. |
| pay_way | string | ✅ Yes | cashapp, ecashapp, ecashapp2, applepay, applepay2, googlepay, googlepay2, card2, chime, btcpay, paypal, venmo, paypal3, cashapp3, applepay3, googlepay3 |
| 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": "ach_payout",
"recipient": {
"accountNumber": "123456789",
"routingNumber": "021000021"
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | numeric | ✅ Yes | Per-wallet min/max may apply (see below). |
| pay_way | string | ✅ Yes | cashapp_payout, cashapp_payout2, paypal_payout, paypal_payout3, ach_payout3, chime_payout2, chime_payout3 |
| recipient | object | ✅ Yes | Fields depend on the wallet (table below). Single-field wallets also accept a plain account_info string. |
| pay_way | Wallet | recipient fields | Processing | Limits |
|---|---|---|---|---|
| cashapp_payout | Cash App | cashtag Cashtag ($) | Automatic (sent at once, final status by webhook) | |
| cashapp_payout2 | Cash App 2 | cashtag Cashtag ($) | Automatic (sent at once, final status by webhook) | |
| paypal_payout | PayPal | email PayPal email | Automatic (sent at once, final status by webhook) | |
| paypal_payout3 | PayPal M | email PayPal email | Manual (admin approval) | |
| ach_payout3 | ACH | accountNumber Account number, routingNumber Routing number | Manual (admin approval) | |
| chime_payout2 | Chime 2 | chimeSign Chime sign ($) | Automatic (sent at once, final status by webhook) | |
| chime_payout3 | Chime | chimeSign Chime sign ($) | Manual (admin approval) |
{
"success": true,
"data": {
"payout_id": 456,
"transaction_id": "POU-20260901-A1B2C3D4E5F6-1788264000",
"amount": "50.00",
"fee": "3.50",
"total_deducted": "53.50",
"pay_way": "ach_payout",
"recipient": "ACH ****6789 / 021000021",
"status": "processing",
"reason": null,
"created_at": "2026-09-01 10:00:00",
"message": "Payout sent to the provider. Final status comes by webhook."
}
}
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 amount: outside the preset list (response includes allowed_amounts) or outside the wallet min/max |
| PAYIN_008 | 403 | Payment method is locked for this account (limited account). Contact support to unlock it. |
| 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 | Invalid recipient, amount outside the wallet limits, or insufficient balance (see errors) |
| PAYOUT_007 | 500 | Payout could not be created. Retry with the same Idempotency-Key. |
| FEE_001 | 422 | Fee not configured for this wallet. Contact support. |
| 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