API Reference
Complete reference for the CoverPay REST API. All endpoints accept and return JSON. Every response includes a request_id for tracing and support.
Base URLs
https://sandbox.coverpayme.com/v1https://api.coverpayme.com/v1Authentication
Authenticate every request with a Bearer token in the Authorization header. API keys are prefixed by environment:
cp_test_...for sandboxcp_live_...for production
All requests must include Content-Type: application/json.
curl https://api.coverpayme.com/v1/bnpl/offers \
-H "Authorization: Bearer cp_live_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{"amount": 15000, "currency": "USD"}'BNPL Offers
Query available BNPL offers for a given purchase amount. The smart router ranks providers by availability, APR, and approval likelihood.
/v1/bnpl/offersReturns ranked BNPL offers from all available providers for the given amount.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| amount | integer | Yes | Purchase amount in cents (e.g. 15000 = $150.00) |
| currency | string | Yes | ISO 4217 currency code (currently only USD) |
| customerEmail | string | No | Pre-fill customer email for faster checkout |
Example request
curl -X POST https://api.coverpayme.com/v1/bnpl/offers \
-H "Authorization: Bearer cp_test_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"amount": 15000,
"currency": "USD",
"customerEmail": "jane@example.com"
}'Example response
{
"request_id": "req_8f3a1b2c4d5e",
"offers": [
{
"provider": "klarna",
"plan_type": "pay_in_4",
"installments": 4,
"per_installment": 3750,
"total": 15000,
"apr": 0,
"currency": "USD",
"min_amount": 3500,
"max_amount": 150000,
"score": 92.4
},
{
"provider": "affirm",
"plan_type": "monthly",
"installments": 12,
"per_installment": 1336,
"total": 16032,
"apr": 15.0,
"currency": "USD",
"min_amount": 5000,
"max_amount": 1750000,
"score": 87.1
},
{
"provider": "afterpay",
"plan_type": "pay_in_4",
"installments": 4,
"per_installment": 3750,
"total": 15000,
"apr": 0,
"currency": "USD",
"min_amount": 100,
"max_amount": 200000,
"score": 84.6
},
{
"provider": "coverpay",
"plan_type": "pay_in_4",
"installments": 4,
"per_installment": 3750,
"total": 15000,
"apr": 0,
"currency": "USD",
"min_amount": 1000,
"max_amount": 50000,
"score": 80.2
}
]
}Checkout Sessions
Create a checkout session to redirect the customer to a specific provider's payment flow.
/v1/bnpl/sessionsCreates a checkout session for the selected provider. Returns a redirect URL the customer should be sent to.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| provider | string | Yes | Provider slug: klarna, affirm, afterpay, paypal, sezzle, zip, coverpay |
| order | object | Yes | Order details (see below) |
| order.orderId | string | Yes | Your internal order ID |
| order.totalAmount | integer | Yes | Amount in cents |
| successUrl | string | Yes | URL to redirect after successful payment |
| cancelUrl | string | Yes | URL to redirect if customer cancels |
Example request
curl -X POST https://api.coverpayme.com/v1/bnpl/sessions \
-H "Authorization: Bearer cp_test_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"provider": "klarna",
"order": {
"orderId": "order_9f8e7d6c",
"totalAmount": 15000
},
"successUrl": "https://mystore.com/checkout/success",
"cancelUrl": "https://mystore.com/checkout/cancel"
}'Example response
{
"request_id": "req_2c4d6e8f0a1b",
"sessionId": "sess_kl_7a8b9c0d1e2f",
"provider": "klarna",
"redirectUrl": "https://pay.klarna.com/checkout/7a8b9c0d1e2f",
"expiresAt": "2026-01-30T12:30:00Z"
}Eligibility
Verify that a customer is eligible for BNPL before showing checkout options. The eligibility pipeline checks age, residency, KYC status, sanctions, and terms acceptance.
/v1/checkout/verify-eligibilityRuns the full eligibility pipeline and returns pass/fail for each check.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | CoverPay user ID |
| amount | integer | Yes | Requested amount in cents |
Example request
curl -X POST https://api.coverpayme.com/v1/checkout/verify-eligibility \
-H "Authorization: Bearer cp_test_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"userId": "usr_9a8b7c6d5e4f",
"amount": 15000
}'Example response
{
"request_id": "req_3d5f7a9b1c3e",
"eligible": true,
"failureReasons": [],
"checks": {
"age": { "passed": true },
"residency": { "passed": true },
"kyc": { "passed": true, "status": "approved" },
"sanctions": { "passed": true },
"terms": { "passed": true, "version": "2026-01-15" }
}
}Failure reasons
When eligible is false, the failureReasons array contains one or more of: UNDER_18, DATE_OF_BIRTH_MISSING, NON_US_RESIDENT, KYC_NOT_STARTED, KYC_PENDING, KYC_REJECTED, KYC_EXPIRED, SANCTIONS_FLAGGED, TERMS_NOT_ACCEPTED, USER_NOT_FOUND.
/v1/checkout/accept-termsRecords the customer's acceptance of CoverPay legal documents. Must be accepted before a checkout session can be created.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | CoverPay user ID |
| documents | string[] | Yes | Array of accepted document types: user_agreement, privacy_policy, regulatory, third_party |
Example request
curl -X POST https://api.coverpayme.com/v1/checkout/accept-terms \
-H "Authorization: Bearer cp_test_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"userId": "usr_9a8b7c6d5e4f",
"documents": [
"user_agreement",
"privacy_policy",
"regulatory",
"third_party"
]
}'Example response
{
"request_id": "req_4e6g8i0k2m4o",
"accepted": true,
"version": "2026-01-15",
"acceptedAt": "2026-01-29T14:22:31Z"
}/v1/checkout/terms-status/:userIdReturns the current terms acceptance status for a user.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | CoverPay user ID |
Example request
curl https://api.coverpayme.com/v1/checkout/terms-status/usr_9a8b7c6d5e4f \
-H "Authorization: Bearer cp_test_a1b2c3d4..."Example response
{
"request_id": "req_5f7h9j1l3n5p",
"accepted": true,
"version": "2026-01-15",
"documents": [
{ "type": "user_agreement", "acceptedAt": "2026-01-29T14:22:31Z" },
{ "type": "privacy_policy", "acceptedAt": "2026-01-29T14:22:31Z" },
{ "type": "regulatory", "acceptedAt": "2026-01-29T14:22:31Z" },
{ "type": "third_party", "acceptedAt": "2026-01-29T14:22:31Z" }
]
}Business
Manage your business account, settings, and API keys.
/v1/business/registerRegister a new business account. Returns an access token and the created business object.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Business email address | |
| password | string | Yes | Minimum 8 characters |
| businessName | string | Yes | Legal business name |
| website | string | No | Business website URL |
Example request
curl -X POST https://api.coverpayme.com/v1/business/register \
-H "Content-Type: application/json" \
-d '{
"email": "dev@mystore.com",
"password": "secureP@ss123",
"businessName": "My Store Inc.",
"website": "https://mystore.com"
}'Example response
{
"request_id": "req_6a7b8c9d0e1f",
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"business": {
"id": "biz_3e4f5a6b7c8d",
"name": "My Store Inc.",
"email": "dev@mystore.com",
"website": "https://mystore.com",
"tier": "starter",
"createdAt": "2026-01-29T15:00:00Z"
}
}/v1/business/loginAuthenticate and receive an access token.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Business email address | |
| password | string | Yes | Account password |
Example response
{
"request_id": "req_7b8c9d0e1f2a",
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresIn": 86400
}/v1/business/meReturns the currently authenticated user and their associated business.
Example response
{
"request_id": "req_8c9d0e1f2a3b",
"user": {
"id": "usr_1a2b3c4d5e6f",
"email": "dev@mystore.com",
"role": "owner"
},
"business": {
"id": "biz_3e4f5a6b7c8d",
"name": "My Store Inc.",
"website": "https://mystore.com",
"tier": "growth",
"providers": ["klarna", "affirm", "afterpay"],
"createdAt": "2026-01-15T10:00:00Z"
}
}/v1/business/settingsUpdate business settings including enabled providers, branding, and routing preferences.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| businessName | string | No | Updated business name |
| website | string | No | Business website URL |
| providers | string[] | No | Enabled provider slugs |
| brandColor | string | No | Hex color for checkout branding |
Example response
{
"request_id": "req_9d0e1f2a3b4c",
"business": {
"id": "biz_3e4f5a6b7c8d",
"name": "My Store Inc.",
"website": "https://mystore.com",
"providers": ["klarna", "affirm", "afterpay", "coverpay"],
"brandColor": "#f59e0b",
"updatedAt": "2026-01-29T16:15:00Z"
}
}/v1/business/api-keysList all API keys for the authenticated business. Secret keys are masked after creation.
Example response
{
"request_id": "req_0e1f2a3b4c5d",
"keys": [
{
"id": "key_1a2b3c4d",
"name": "Production Key",
"prefix": "cp_live_a1b2...",
"environment": "production",
"createdAt": "2026-01-20T10:00:00Z",
"lastUsedAt": "2026-01-29T14:30:00Z"
},
{
"id": "key_5e6f7a8b",
"name": "Test Key",
"prefix": "cp_test_x9y8...",
"environment": "sandbox",
"createdAt": "2026-01-15T09:00:00Z",
"lastUsedAt": "2026-01-29T12:00:00Z"
}
]
}/v1/business/api-keysCreate a new API key. The full secret is returned only once in the response.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | A label for this key |
| environment | string | Yes | sandbox or production |
Example response
{
"request_id": "req_1f2a3b4c5d6e",
"key": {
"id": "key_9c0d1e2f",
"name": "Mobile App Key",
"secret": "cp_live_sk_7g8h9i0j1k2l3m4n5o6p7q8r9s0t",
"environment": "production",
"createdAt": "2026-01-29T16:30:00Z"
}
}Important: The secret field is only returned at creation time. Store it securely -- you will not be able to retrieve it again.
/v1/business/api-keys/:keyIdPermanently revoke an API key. This action cannot be undone. Any requests using the revoked key will receive a 401 response.
Example response
{
"request_id": "req_2a3b4c5d6e7f",
"deleted": true,
"keyId": "key_1a2b3c4d"
}Webhooks
Manage webhook endpoints to receive real-time event notifications. See the Webhooks Guide for payload schemas, signature verification, and best practices.
/v1/business/webhooksList all webhook endpoints configured for your business.
Example response
{
"request_id": "req_3b4c5d6e7f8a",
"endpoints": [
{
"id": "wh_1a2b3c4d",
"url": "https://mystore.com/webhooks/coverpay",
"events": ["checkout.completed", "payment.success", "payment.failed"],
"enabled": true,
"signingSecret": "whsec_a1b2...d4e5",
"createdAt": "2026-01-20T10:00:00Z"
}
]
}/v1/business/webhooksCreate a new webhook endpoint. The URL must use HTTPS.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | HTTPS endpoint URL |
| events | string[] | Yes | Event types to subscribe to |
Example response
{
"request_id": "req_4c5d6e7f8a9b",
"endpoint": {
"id": "wh_5e6f7a8b",
"url": "https://mystore.com/webhooks/coverpay",
"events": ["checkout.completed", "payment.success"],
"enabled": true,
"signingSecret": "whsec_9x8w7v6u5t4s3r2q1p0o",
"createdAt": "2026-01-29T17:00:00Z"
}
}/v1/business/webhooks/:idUpdate an existing webhook endpoint. You can change the URL, subscribed events, or enabled state.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | No | Updated HTTPS endpoint URL |
| events | string[] | No | Updated event types |
| enabled | boolean | No | Enable or disable the endpoint |
Example response
{
"request_id": "req_5d6e7f8a9b0c",
"endpoint": {
"id": "wh_5e6f7a8b",
"url": "https://mystore.com/webhooks/v2/coverpay",
"events": ["checkout.completed", "payment.success", "refund.completed"],
"enabled": true,
"updatedAt": "2026-01-29T17:30:00Z"
}
}/v1/business/webhooks/:idPermanently delete a webhook endpoint. Pending deliveries will be cancelled.
Example response
{
"request_id": "req_6e7f8a9b0c1d",
"deleted": true,
"endpointId": "wh_5e6f7a8b"
}/v1/business/webhooks/:id/testSend a test event to the webhook endpoint to verify it is reachable and correctly processing payloads.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| eventType | string | No | Event type to simulate (defaults to checkout.completed) |
Example response
{
"request_id": "req_7f8a9b0c1d2e",
"delivered": true,
"statusCode": 200,
"responseTimeMs": 142,
"eventType": "checkout.completed"
}/v1/business/webhooks/:id/deliveriesList recent delivery attempts for a webhook endpoint, including status codes and response times.
Example response
{
"request_id": "req_8a9b0c1d2e3f",
"deliveries": [
{
"id": "dlv_a1b2c3d4",
"eventType": "payment.success",
"statusCode": 200,
"responseTimeMs": 89,
"success": true,
"attempt": 1,
"deliveredAt": "2026-01-29T16:45:12Z"
},
{
"id": "dlv_e5f6a7b8",
"eventType": "checkout.completed",
"statusCode": 500,
"responseTimeMs": 2340,
"success": false,
"attempt": 3,
"deliveredAt": "2026-01-29T15:30:00Z",
"nextRetryAt": "2026-01-29T17:30:00Z"
}
]
}/v1/business/webhooks/eventsList all available webhook event types you can subscribe to.
Example response
{
"request_id": "req_9b0c1d2e3f4a",
"events": [
{ "type": "checkout.completed", "description": "Customer completed checkout" },
{ "type": "checkout.abandoned", "description": "Customer abandoned checkout session" },
{ "type": "payment.success", "description": "Payment was successfully processed" },
{ "type": "payment.failed", "description": "Payment processing failed" },
{ "type": "loan.created", "description": "BNPL loan was originated" },
{ "type": "loan.completed", "description": "All installments paid, loan closed" },
{ "type": "eligibility.failed", "description": "Customer failed eligibility check" },
{ "type": "refund.initiated", "description": "Refund was initiated" },
{ "type": "refund.completed", "description": "Refund was successfully processed" }
]
}Errors
CoverPay uses conventional HTTP status codes. All error responses include a machine-readableerror code and a human-readable message.
Error response format
{
"request_id": "req_0c1d2e3f4a5b",
"error": "invalid_amount",
"message": "Amount must be a positive integer in cents.",
"retryAfter": null
}Error codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | invalid_request | The request body is malformed or missing required fields. |
| 400 | invalid_amount | Amount must be a positive integer in cents. |
| 400 | invalid_provider | The specified provider is not supported or not enabled. |
| 401 | unauthorized | Missing or invalid API key. |
| 401 | token_expired | The access token has expired. Re-authenticate. |
| 403 | forbidden | The API key does not have permission for this action. |
| 404 | not_found | The requested resource does not exist. |
| 409 | duplicate | A resource with this identifier already exists. |
| 422 | eligibility_failed | The customer did not pass eligibility checks. |
| 429 | rate_limited | Too many requests. Check the Retry-After header. |
| 500 | internal_error | An unexpected error occurred on our end. |
| 502 | provider_error | The upstream BNPL provider returned an error. |
| 503 | service_unavailable | CoverPay is temporarily unavailable. Try again shortly. |
Rate Limits
Rate limits are applied per API key and vary by subscription tier. When rate limited, the response includes a Retry-After header with the number of seconds to wait.
| Tier | Requests / minute | Requests / day | Burst |
|---|---|---|---|
| Starter | 60 | 10,000 | 20 |
| Growth | 200 | 50,000 | 50 |
| Scale | 600 | 200,000 | 100 |
| Enterprise | Custom | Custom | Custom |
Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.