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:

  1. You specify the amount and currency
  2. SyncPay generates a secure, hosted checkout URL
  3. You redirect your customer to this URL
  4. Customer completes payment on SyncPay's hosted page
  5. Customer is redirected back to your site
  6. 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:

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:

  1. Active API Key: Obtain from your dashboard (see Getting Started)
  2. Enabled Payment Methods: At least one payment method must be enabled in your dashboard
  3. Supported Currency: The currency must be in Supported Currencies

Optional but Recommended:

  • Configure webhook endpoint to receive payment notifications
  • Set up success_url and cancel_url for 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_url or cancel_url (must include http:// or https://)
  • 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

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:

  1. Generate a unique identifier in your system
  2. Store it in metadata
  3. 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:

  1. Successful payment: Complete checkout with test payment method
  2. Failed payment: Use test card 4000 0000 0000 0002 (if testing cards)
  3. Expired checkout: Wait for expiration time or set expires_in_minutes: 1
  4. Cancelled payment: Click "Cancel" on checkout page


Next Steps

After creating a checkout:

  1. Redirect customer to the checkout_url
  2. Set up webhooks to receive payment notifications (see Webhook Documentation)
  3. Handle redirects from success_url and cancel_url
  4. Monitor payments using Get Charge Status