Skip to main content
The checkout API allows you to programmatically create purchase sessions for your customers. This is useful for custom storefronts, integrations, or automated sales flows.
Pay-what-you-want products are not supported via the Public API. For these products, redirect customers to your Chariow store or use the Snap Widget embed on your website.
All sales initiated via the checkout API will have their Channel set to “API” on your store dashboard. This helps you identify and track sales originating from your API integrations separately from other channels like your storefront or Snap Widget.

Repeat Purchases

The ability to purchase a product multiple times depends on the product type:
Product TypeRepeat PurchaseBehaviour
ServiceAlways allowedCustomers can purchase service products unlimited times. Ideal for consultations, memberships, or recurring services.
LicenseAlways allowedCustomers can purchase license products multiple times. Each purchase generates a new unique license key.
DownloadableBlockedReturns already_purchased if customer has an active access grant.
CourseBlockedReturns already_purchased if customer has an active access grant.
BundleBlockedReturns already_purchased if customer has an active access grant.
For blocked product types, if a customer’s access has been revoked (e.g., after a refund), they will be able to purchase the product again. The system checks for active access grants only.

Checkout Flow Overview

The Chariow checkout API handles the complete purchase flow from initiation to completion:
The product must be published before initiating a checkout. Unpublished products will return a 404 error.
1

Initiate Checkout

Call the /checkout endpoint with product ID and customer details
2

Handle Response

Check the step field in the response:
  • awaiting_payment: Redirect customer to checkout_url for payment
  • completed: Sale completed immediately (free products)
  • already_purchased: Customer already owns this product
3

Process Payment

Customer completes payment on the secure Chariow payment page
4

Receive Webhook

Get notified of sale status changes via webhooks (recommended)
5

Deliver Product

Customer receives automatic access to files, licenses, courses, etc.

Product Types Supported

The checkout API supports all Chariow product types:
  • Downloadable Products: Digital files (PDFs, software, media)
  • Services: Consultation, memberships, subscriptions
  • Courses: Educational content with lessons and chapters
  • Licenses: Software license keys with activation management
  • Bundles: Collections of multiple products
All product types except pay-what-you-want pricing are supported via the Public API.

Initiating a Checkout

Create a new checkout session:
curl -X POST "https://api.chariow.com/v1/checkout" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_abc123",
    "email": "[email protected]",
    "first_name": "John",
    "last_name": "Doe",
    "phone": {
      "number": "1234567890",
      "country_code": "US"
    },
    "discount_code": "SAVE20"
  }'

Request Parameters

ParameterTypeRequiredDescription
product_idstringYesProduct public ID or slug (e.g., prd_abc123xyz or premium-course)
emailstringYesCustomer email address (max 255 characters)
first_namestringYesCustomer first name (max 50 characters)
last_namestringYesCustomer last name (max 50 characters)
phone.numberstringYesPhone number (numeric only)
phone.country_codestringYesISO country code (e.g., “US”, “FR”, “GB”)
discount_codestringNoDiscount code to apply (max 100 characters)
campaign_idstringNoCampaign public ID or tracking code
custom_fieldsobjectNoCustom field values (key-value pairs)
payment_currencystringNoCurrency code (ISO 4217, e.g., “USD”, “EUR”)
redirect_urlstringNoCustom redirect URL after payment completion (max 2048 characters)
custom_metadataobjectNoCustom key-value metadata to store with the sale (max 10 keys, 255 chars per value). Included in Pulse webhook payloads.

Shipping Address Fields

When the product has “Require shipping address” enabled, you must include shipping address fields in your checkout request:
ParameterTypeRequiredDescription
addressstringConditionalStreet address for shipping (max 255 characters)
citystringConditionalCity for shipping (max 100 characters)
statestringConditionalState or region for shipping (max 100 characters)
countrystringConditionalCountry code (ISO 3166-1 alpha-2, e.g., “US”, “FR”)
zipstringConditionalPostal/ZIP code for shipping (max 20 characters)
These fields are required only when the product has shipping enabled. If shipping is not required, these fields are ignored.

Example with Shipping Address

{
  "product_id": "prd_abc123xyz",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "address": "123 Main Street",
  "city": "New York",
  "state": "NY",
  "country": "US",
  "zip": "10001"
}

Checkout Response States

The checkout response includes a step field indicating the current state:

Awaiting Payment

For paid products, you’ll receive a payment URL:
{
  "data": {
    "step": "awaiting_payment",
    "message": null,
    "purchase": {
      "id": "sal_xyz789",
      "status": "awaiting_payment",
      "amount": {
        "amount": 7920,
        "currency": "USD"
      }
    },
    "payment": {
      "checkout_url": "https://payment.chariow.com/checkout?token=abc123",
      "transaction_id": "txn_def456"
    }
  }
}
Redirect the customer to checkout_url to complete their payment.

Completed (Free Products)

For free products, the sale completes immediately:
{
  "data": {
    "step": "completed",
    "message": null,
    "purchase": {
      "id": "sal_xyz789",
      "status": "completed"
    },
    "payment": {
      "checkout_url": null,
      "transaction_id": null
    }
  }
}

Already Purchased

If the customer already owns the product:
{
  "data": {
    "step": "already_purchased",
    "message": "You have already purchased this product",
    "purchase": null,
    "payment": null
  }
}

Custom Redirect URLs

You can specify a custom redirect URL to send customers to your own thank-you page after payment completion:
curl -X POST "https://api.chariow.com/v1/checkout" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_abc123xyz",
    "email": "[email protected]",
    "first_name": "John",
    "last_name": "Doe",
    "phone": {
      "number": "1234567890",
      "country_code": "US"
    },
    "redirect_url": "https://yoursite.com/thank-you?sale={sale_id}"
  }'
The redirect URL must be a valid active URL (max 2048 characters). When not provided, customers will be redirected to the default Chariow post-purchase page.

Multi-Currency Support

Specify the payment currency to charge customers in a different currency from your store’s default:
{
  "product_id": "prd_abc123xyz",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "payment_currency": "EUR"
}
The response will include exchange rate information when currency conversion is applied.

Applying Discount Codes

Pass a discount code to apply savings:
{
  "product_id": "prd_abc123xyz",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "discount_code": "SAVE20"
}
The response will show the discounted amount:
{
  "data": {
    "purchase": {
      "original_amount": {
        "amount": 9900,
        "currency": "USD",
        "formatted": "$99.00"
      },
      "amount": {
        "amount": 7920,
        "currency": "USD",
        "formatted": "$79.20"
      },
      "discount_amount": {
        "amount": 1980,
        "currency": "USD",
        "formatted": "$19.80"
      },
      "discount": {
        "id": "dis_xyz789",
        "code": "SAVE20",
        "type": "percentage",
        "value": 20
      }
    }
  }
}

Custom Fields

If your product has custom fields configured, you can collect and validate them during checkout:
{
  "product_id": "prd_abc123xyz",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "custom_fields": {
    "company_name": "Acme Corp",
    "job_title": "Developer",
    "team_size": "10-50"
  }
}
Custom fields must match the product’s configured custom field definitions. Invalid or missing required custom fields will result in validation errors.

Campaign Tracking

Track the source of sales by including a campaign ID:
{
  "product_id": "prd_abc123xyz",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "campaign_id": "camp_summer2024"
}
This helps you:
  • Track which marketing campaigns drive the most sales
  • Attribute revenue to specific channels
  • Analyse campaign performance in your Chariow dashboard

Custom Metadata

Store custom data with the sale for your own tracking and integration purposes:
{
  "product_id": "prd_abc123xyz",
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": {
    "number": "1234567890",
    "country_code": "US"
  },
  "custom_metadata": {
    "order_ref": "ORD-123",
    "source": "landing_page",
    "utm_campaign": "summer_sale"
  }
}

Important Notes

  • Maximum 10 keys allowed per sale
  • Each value is limited to 255 characters
  • Keys should be strings with alphanumeric characters and underscores
  • Custom metadata is included in Pulse webhook payloads
Use custom metadata to link Chariow sales with your CRM, analytics platform, or internal systems. The metadata is returned in all sale-related webhooks.

Error Handling

Common checkout errors and how to handle them:
HTTP StatusErrorCauseSolution
401UnauthorisedInvalid or missing API keyCheck your API key is correct and included in the Authorization header
404Product not foundInvalid product ID or unpublished productVerify the product ID/slug exists and is published
422Validation failedMissing or invalid required fieldsCheck all required fields are provided with correct formats
422Pay-what-you-want not supportedProduct uses pay-what-you-want pricingRedirect customers to your Chariow store or use the Snap Widget
422Invalid discount codeDiscount code expired, invalid, or already usedVerify the discount code is active and applicable
422Missing shipping addressProduct requires shipping but address fields are missingInclude address, city, state, country, and zip fields

Example Error Response

{
  "message": "The email field must be a valid email address.",
  "data": [],
  "errors": {
    "email": [
      "The email field must be a valid email address."
    ],
    "phone.number": [
      "The phone.number field is required."
    ]
  }
}
Always check the errors object for field-specific validation messages to help users correct their input.

Best Practices

Handle All Response Steps

Always check the step field and handle all possible states:
const response = await fetch('https://api.chariow.com/v1/checkout', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(checkoutData)
});

const result = await response.json();

switch (result.data.step) {
  case 'awaiting_payment':
    // Redirect to payment URL
    window.location.href = result.data.payment.checkout_url;
    break;

  case 'completed':
    // Show success message for free products
    showSuccessMessage(result.data.purchase);
    break;

  case 'already_purchased':
    // Inform customer they already own this product
    showAlreadyPurchasedMessage(result.data.message);
    break;
}

Use Pulses for Sale Updates

Don’t rely solely on redirect URLs to track sale completion. Set up Pulses (webhooks) to receive reliable notifications:
  • Sale completed
  • Payment received
  • Refund processed
See the Pulses Guide for setup instructions.

Validate Before Checkout

Reduce failed checkouts by validating data before calling the API:
  • Email format validation
  • Phone number format validation
  • Required field checks
  • Custom field validation

Handle Network Errors

Implement proper error handling for network issues:
try {
  const response = await fetch('https://api.chariow.com/v1/checkout', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(checkoutData)
  });

  if (!response.ok) {
    const error = await response.json();
    handleCheckoutError(error);
    return;
  }

  const data = await response.json();
  handleCheckoutSuccess(data);

} catch (error) {
  // Handle network errors
  console.error('Checkout failed:', error);
  showErrorMessage('Unable to process checkout. Please try again.');
}

Store Sale IDs

Always store the returned sale ID (purchase.id) for:
  • Customer service inquiries
  • Refund processing
  • Access management
  • Analytics tracking

Test with Different Scenarios

Test your integration with:
  • Free products (immediate completion)
  • Paid products (payment flow)
  • Products with discount codes
  • Products with custom fields
  • Invalid product IDs
  • Invalid discount codes

Next Steps