Create Checkout
Overview
Create a hosted checkout session where customers can complete their payment. This is the primary endpoint for accepting payments through SyncPay.
When you create a checkout:
- You specify the amount and currency
- SyncPay generates a secure, hosted checkout URL
- You redirect your customer to this URL
- Customer completes payment on SyncPay's hosted page
- Customer is redirected back to your site
- You receive a webhook notification about the payment status
Use this endpoint when: You want SyncPay to handle the entire payment flow, including the payment form and processing.
Authentication
Type: API Key (required)
This endpoint requires API key authentication.
Required Headers
| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Format: Bearer sk_test_... or Bearer sk_live_... |
Content-Type |
Yes | Must be application/json |
Request
Method & Path
POST /api/v1/payments/checkouts
Request Body
The request body defines your pricing strategy and customer information.
Minimum Required Fields
{
"pricing": {
"base_currency": "USD",
"amount": "50.00"
},
"customer_email": "customer@example.com"
}
Full Request Example
{
"pricing": {
"base_currency": "USD",
"amount": "50.00",
"local_pricing": {
"NGN": "75000.00",
"GHS": "620.00"
}
},
"customer_email": "customer@example.com",
"customer_name": "John Doe",
"success_url": "https://yoursite.com/payment/success",
"cancel_url": "https://yoursite.com/payment/cancelled",
"metadata": {
"order_id": "ORD-12345",
"user_id": "user_789",
"items": "Premium Plan - Annual"
},
"expires_in_minutes": 60
}
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
pricing |
object | Yes | Pricing configuration for the checkout |
pricing.base_currency |
string | Yes | Base currency code (e.g., USD, NGN) |
pricing.amount |
string | Yes | Amount in base currency (decimal string) |
pricing.local_pricing |
object | No | Currency-specific amounts (only when base_currency is USD) |
customer_email |
string | Yes | Customer's email address |
customer_name |
string | No | Customer's full name |
success_url |
string | No | URL to redirect after successful payment (must use https:// or http://) |
cancel_url |
string | No | URL to redirect if customer cancels (must use https:// or http://) |
metadata |
object | No | Custom metadata (max 20 keys, max 10KB total) |
expires_in_minutes |
integer | No | Checkout expiration time in minutes (1-1440, default: 60) |
Pricing Strategies
SyncPay supports three pricing strategies for checkouts:
1. Global Pricing (Recommended)
Set a single base currency and let customers pay in any enabled currency. SyncPay handles real-time conversion.
{
"pricing": {
"base_currency": "USD",
"amount": "50.00"
}
}
How it works:
- You set $50 USD
- Customer sees all your enabled payment methods
- If customer chooses NGN bank transfer, SyncPay calculates the NGN equivalent
- Customer pays the NGN amount
- You receive the NGN settlement
Best for: Global businesses accepting payments from multiple regions.
2. Local Pricing Overrides
Set USD as base, but specify exact amounts for specific currencies. Provides control over pricing in different regions.
{
"pricing": {
"base_currency": "USD",
"amount": "50.00",
"local_pricing": {
"NGN": "75000.00",
"GHS": "620.00"
}
}
}
How it works:
- You set $50 USD base and specify NGN 75,000 and GHS 620
- Nigerian customers see NGN 75,000 (no conversion)
- Ghanaian customers see GHS 620 (no conversion)
- Other customers see USD $50 or converted to their currency
- Settlement is in the currency the customer paid
Best for: Businesses with region-specific pricing strategies.
Important: Local pricing is only allowed when base_currency is USD. You cannot use local pricing with other base currencies.
3. Single Currency Only
Lock the checkout to a single currency. Customers can only pay in that currency.
{
"pricing": {
"base_currency": "NGN",
"amount": "75000.00"
}
}
How it works:
- Checkout only shows NGN payment methods
- No currency conversion offered
- Customer must pay exactly NGN 75,000
Best for: Region-specific businesses or when you want to avoid currency conversion.
Dependencies & Prerequisites
This endpoint requires:
- Active API Key: Obtain from your dashboard (see Getting Started)
- Enabled Payment Methods: At least one payment method must be enabled in your dashboard
- Supported Currency: The currency must be in Supported Currencies
Optional but Recommended:
- Configure webhook endpoint to receive payment notifications
- Set up
success_urlandcancel_urlfor better user experience
Example Use Case
Scenario: Your e-learning platform offers online courses priced at $49 USD. You want to accept payments from students worldwide while offering region-specific pricing for students in Nigeria and Ghana to account for local purchasing power. The system should automatically show the correct price based on the student's location and handle currency conversion seamlessly.
Implementation:
const response = await fetch('https://api.usesyncpay.com/api/v1/payments/checkouts', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_abc123xyz...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
pricing: {
base_currency: 'USD',
amount: '49.00',
local_pricing: {
NGN: '70000.00', // ₦70,000 (special price for Nigeria)
GHS: '580.00' // GH₵580 (special price for Ghana)
}
},
customer_email: 'student@university.edu',
customer_name: 'Jane Smith',
success_url: 'https://myelearning.com/courses/thank-you',
cancel_url: 'https://myelearning.com/courses/web-development',
metadata: {
course_id: 'WEB-101',
course_name: 'Web Development Fundamentals',
enrollment_type: 'standard'
},
expires_in_minutes: 30
})
});
const checkout = await response.json();
console.log('Checkout URL:', checkout.checkout_url);
// Redirect customer to checkout.checkout_url
window.location.href = checkout.checkout_url;
Response
200 – Success
Returns the created checkout details with a hosted checkout URL.
{
"checkout_id": "chk_1a2b3c4d5e6f",
"organization_id": "org_abc123",
"checkout_url": "https://checkout.usesyncpay.com/c/chk_1a2b3c4d5e6f",
"status": "PENDING",
"expires_at": "2026-01-24T15:30:00.000Z",
"created_at": "2026-01-24T14:30:00.000Z"
}
Response Fields
| Field | Type | Description |
|---|---|---|
checkout_id |
string | Unique identifier for this checkout session |
organization_id |
string | Your organization ID |
checkout_url |
string | Hosted checkout URL - redirect your customer here |
status |
string | Checkout status (always PENDING for new checkouts) |
expires_at |
string | ISO 8601 timestamp when checkout expires |
created_at |
string | ISO 8601 timestamp when checkout was created |
Next Step: Redirect your customer to the checkout_url to complete payment.
400 – Bad Request
Validation errors or invalid request format.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": {
"pricing.amount": "Amount must be a positive decimal string",
"customer_email": "Invalid email format"
}
}
}
Common causes:
- Missing required fields (
pricing,customer_email) - Invalid amount format (must be decimal string like
"50.00", not number) - Invalid currency code (not in supported currencies)
- Local pricing used with non-USD base currency
- Invalid URL format for
success_urlorcancel_url(must includehttp://orhttps://) - Metadata too large (> 10KB) or too many keys (> 20)
- Invalid
expires_in_minutes(must be 1-1440)
401 – Unauthorized
Invalid or missing API key.
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}
Solution: Verify your API key is correct and included in the Authorization header.
403 – Forbidden
API key doesn't have permission or payment methods not enabled.
{
"error": {
"code": "FORBIDDEN",
"message": "No payment methods enabled for this organization"
}
}
Solution: Enable at least one payment method in your dashboard settings.
Checkout Lifecycle
1. Created
- Status:
PENDING - Checkout URL is generated
- Customer can access the checkout page
2. Customer Completes Payment
- Customer selects payment method and currency
- Customer enters payment details
- Payment is submitted to provider
3. Payment Processing
- Status changes based on payment result
- Possible statuses:
COMPLETED,FAILED,EXPIRED
4. Webhook Notification
- You receive webhook with final payment status
- See Webhook Documentation
5. Customer Redirect
- On success: Redirected to
success_url - On cancel: Redirected to
cancel_url
Important Notes
Amount Format
Always use string format for amounts, not numbers:
- Correct:
"50.00" - Incorrect:
50.00(number) - Incorrect:
50(integer)
Why? Strings preserve decimal precision and avoid floating-point errors.
Currency Precision
Different currencies have different decimal places:
- Most currencies: 2 decimals (e.g.,
"50.00") - Zero-decimal currencies (JPY, KRW): No decimals (e.g.,
"5000")
SyncPay automatically handles precision for each currency.
Checkout Expiration
Checkouts expire after the specified time (default: 60 minutes). After expiration:
- Checkout URL becomes invalid
- Customer cannot complete payment
- Status changes to
EXPIRED
Recommendation: Set expiration based on your use case:
- Quick purchases: 15-30 minutes
- Standard checkout: 60 minutes (default)
- Invoice-style: 24 hours (1440 minutes)
Metadata Best Practices
Use metadata to store context about the purchase:
{
"metadata": {
"order_id": "ORD-12345",
"customer_id": "cust_789",
"product_sku": "PREMIUM-ANNUAL",
"campaign": "summer-sale-2026"
}
}
Benefits:
- Metadata is returned in webhooks
- Helps you reconcile payments
- Useful for analytics and reporting
Limitations:
- Maximum 20 keys
- Maximum 10KB total size
- Keys and values must be strings
Idempotency
This endpoint does not currently support idempotency keys. If you need to prevent duplicate checkouts:
- Generate a unique identifier in your system
- Store it in metadata
- Check for duplicates before creating a new checkout
Testing
Test Mode Behavior
When using a test API key (sk_test_...):
- Checkouts are created in test mode
- No real money is processed
- You can simulate different payment scenarios
- Test cards and payment methods are available on the checkout page
Test Scenarios
To test different outcomes:
- Successful payment: Complete checkout with test payment method
- Failed payment: Use test card
4000 0000 0000 0002(if testing cards) - Expired checkout: Wait for expiration time or set
expires_in_minutes: 1 - Cancelled payment: Click "Cancel" on checkout page
Related Endpoints
- Create Quote - Get pricing before creating checkout
- Create Whitelabel Checkout - Create and complete checkout in one request
- Get Charge Status - Check payment status after checkout
- List Payins - Retrieve all payments
Next Steps
After creating a checkout:
- Redirect customer to the
checkout_url - Set up webhooks to receive payment notifications (see Webhook Documentation)
- Handle redirects from
success_urlandcancel_url - Monitor payments using Get Charge Status