Browser checkout API
/sessionsCreate a browser checkout session
Starts a browser-defined checkout with a publishable key. The browser can change the amount, so reconcile against your server order. Success/cancel URL hosts must match the request Origin. Prefer server-created checkout for trusted pricing.
Endpoint
POST https://api.veyqo.org/checkout/v1/sessions
Send your Veyqo publishable key using Authorization: Bearer or X-Veyqo-Key. This is the browser checkout surface, not the secret-key payments API.
Example request
Examples use illustrative IDs and provider URLs. Replace path variables with IDs returned by your own requests. Never paste a live secret into client code or a public tool.
curl --request POST "https://api.veyqo.org/checkout/v1/sessions" \
--header "Authorization: Bearer $VEYQO_PUBLISHABLE_KEY" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"amount": 50000,
"currency": "NGN",
"reference": "ORDER-1001",
"provider": "paystack",
"customer": {
"email": "customer@example.com"
}
}'Request body
| Field | Type | Presence | Description |
|---|---|---|---|
| amount | integer | Required | Integer minor-unit amount. NGN 500.00 is 50000; JPY 500 is 500. Minimum 1. |
| currency | string | Required | Three-letter currency supported by the selected provider. Maximum 3 characters. |
| reference | string | null | Optional | Order reference; a session can create multiple uniquely referenced payment attempts. Maximum 100 characters. |
| description | string | null | Optional | Maximum 500 characters. |
| customer | object | Optional | See the JSON example. |
| customer.email | string | null | Optional | Maximum 255 characters. Format: email. |
| customer.name | string | null | Optional | Maximum 255 characters. |
| metadata | object | array | null | Optional | Your non-sensitive JSON metadata. Objects are recommended; do not store secrets or card details. Maximum 20 entries. |
| provider | string | null | Optional | Gateway selected by your server or project default; the customer chooses a payment method, not the gateway. Maximum 40 characters. |
| success_url | string | null | Optional | HTTP or HTTPS return URL. Use HTTPS in production. Maximum 2048 characters. Format: uri. |
| cancel_url | string | null | Optional | HTTP or HTTPS cancellation URL. Use HTTPS in production. Maximum 2048 characters. Format: uri. |
Successful response · 201
HTTP success means the request was accepted. A pending payment or refund is not completed merely because the response is 200 or 201.
{
"success": true,
"data": {
"id": "cs_01M6EB66SC61Q3RQYAN0693DGM",
"object": "checkout_session",
"url": "https://veyqo.org/pay/cs_01M6EB66SC61Q3RQYAN0693DGM",
"status": "open",
"source": "browser",
"provider": "paystack",
"amount": 50000,
"currency": "NGN",
"reference": "ORDER-1001",
"description": "Order 1001",
"customer_email": "customer@example.com",
"payment": null,
"success_url": "https://shop.example.com/thanks",
"cancel_url": "https://shop.example.com/cart",
"expires_at": "2026-11-02T13:00:00+00:00",
"completed_at": null,
"created_at": "2026-11-02T12:00:00+00:00"
}
}Response fields
| Field in data | Type | Presence | Description |
|---|---|---|---|
| id | string | Required | Checkout session ID (cs_ prefix). |
| object | "checkout_session" | Required | See the JSON example. |
| url | string | Required | Hosted Veyqo URL; redirect here or open this session using VeyqoCheckout. Format: uri. |
| status | string | Required | Values: open, completed, expired. |
| source | string | Required | Values: api, browser, link. |
| provider | string | Required | Selected provider slug; this field is an object on the browser session detail endpoint. |
| amount | integer | Required | Server-defined amount in minor units. |
| currency | string | Required | Three-letter currency. |
| reference | string | null | Required | Your order reference, when supplied. |
| description | string | null | Required | Checkout description. |
| customer_email | string | null | Required | Customer email if already supplied. |
| payment | object | null | Required | Current payment attempt, if any. A session can have multiple attempts over time. |
| success_url | string | null | Required | Configured return URL. A redirect is not proof of payment. |
| cancel_url | string | null | Required | Configured cancellation URL. |
| expires_at | string | Required | Session expiry time. Format: date-time. |
| completed_at | string | null | Required | ISO 8601 timestamp. Format: date-time. |
| created_at | string | null | Required | ISO 8601 timestamp. Format: date-time. |
Errors and recovery
| Code | HTTP | Recovery | Retry policy |
|---|---|---|---|
| VALIDATION_FAILED | 422 | Read error.details when present, correct the named fields and retry only after correction. Validation messages may describe state/capability errors without field details. | No automatic retry. |
| RESOURCE_NOT_FOUND | 404 | Check the ID, project and environment. Do not guess another project’s IDs. An inactive payment link is also not-found. | No blind retry. |
| RATE_LIMIT_EXCEEDED | 429 | Honor Retry-After, use bounded exponential backoff with jitter, and reduce concurrent requests. Read X-RateLimit headers. | Yes, after Retry-After; preserve write idempotency. |
| PROVIDER_UNAVAILABLE | 503 | Check the existing payment and verify its state before starting another attempt. Retry safe reads with backoff; preserve operation identity for retried writes. | Conditional: reconcile unknown outcomes first. |
| INTERNAL_ERROR | 500 | Record X-Request-Id, timestamp and sanitized request context. Reconcile unknown payment outcomes before retrying a write; contact support if it persists. | Safe reads: bounded backoff. Writes: reconcile first. |
| INVALID_API_KEY | 401 | Use a current kc_test_ or kc_live_ secret key on /api/v1. Use a pk_test_ or pk_live_ publishable key only on browser checkout. | After fixing credentials. |