Skip to main content

Replacing Checkout

Use this approach when you want your server to redirect users to Simpler Checkout at the point where they would normally enter your CMS's native checkout.

No Authentication Required

This endpoint does not require any authentication headers. You only need your merchant_id (App ID).

Overview​

The flow has three steps:

  1. Build a Cart Request object describing the user's cart.
  2. POST it to the Simpler endpoint.
  3. Forward the redirect response to the user's browser.

After the redirect, the user lands on the Simpler Checkout page where they complete their purchase. Simpler will then call your Platform Interface APIs to price the cart, resolve shipping, and submit the order.

Cart Request Schema​

The Cart Request is sent as form fields. items and metadata are JSON-encoded strings; every other field is a plain string.

FieldTypeRequiredDescription
merchant_idstringYesYour App ID.
currencystringYesISO 4217 currency code (e.g. EUR, USD, GBP). Any valid ISO 4217 code is accepted.
localestringYesIETF language tag per RFC 5646 (e.g. en, el, fr). Any valid tag is accepted.
itemsJSON stringYesJSON-encoded array of one or more line items (must not be empty). See below.
couponstringNoA coupon code to pre-apply in the Simpler checkout form.
remote_loyalty_couponstringNoA remote loyalty coupon code, pre-selected on your own site, to pre-apply in the Simpler checkout form. Independent of coupon — both can be sent together. See Remote loyalty coupons.
remote_session_idstringNoA token identifying a shopper logged in to your store, so they arrive at checkout signed in. See Cross-Login.
metadataJSON stringNoJSON-encoded object of string key-value pairs, passed through to your backend on every subsequent Platform Interface call for this session. Intended for read-only attribution or tracking (A/B test buckets, internal references). Do not use it as a mutable state store — see Cart Metadata.

items[]​

FieldTypeRequiredDescription
idstringYesProduct identifier as used in your Platform Interface product catalog.
quantityintegerYesNumber of units. Integer, minimum 1.
attributesobjectNoKey-value pairs identifying a specific product variant (e.g. {"color": "blue", "size": "L"}). For products with variants, keys must match a catalog variant definition in your Platform Interface. Omit for simple products with no variants.

Sending the Request​

POST the cart data as application/x-www-form-urlencoded to:

https://checkout.simpler.so/v1/carts

JSON request bodies are not supported. Encode items and metadata as JSON strings before form-encoding the payload — bracket notation (items[0][id]=…) is not understood, and such a request arrives with no items. For example, a single item serialises on the wire as:

merchant_id=YOUR_APP_ID&currency=EUR&locale=en&items=%5B%7B%22id%22%3A%22PRODUCT_ID%22%2C%22quantity%22%3A1%2C%22attributes%22%3A%7B%22color%22%3A%22blue%22%7D%7D%5D

On success, the server responds with a 303 See Other status and a Location header pointing to the Simpler Checkout page. Your server should forward this redirect to the user's browser:

HTTP/1.1 303 See Other
Location: https://checkout.simpler.so/carts/<uuid>
Content-Length: 0

The Location URL is reusable and does not expire. Note that each request creates a new checkout session — re-POSTing the same cart produces a duplicate session, and there is no idempotency key, so avoid blindly retrying this call on the redirect path.

Fallback

If the request does not return a 303, you can redirect the shopper to a checkout URL built from the same cart instead, or render your native checkout. Note that checkout URLs use the shorter item field names qty and attrs.

PHP + cURL Example​

$url = 'https://checkout.simpler.so/v1/carts';
$data = [
'merchant_id' => 'YOUR_APP_ID',
'currency' => 'EUR',
'locale' => 'en',
'items' => json_encode([
[
'id' => 'PRODUCT_ID',
'quantity' => 1,
'attributes' => [
'color' => 'blue',
'size' => 'L'
]
]
]),
'coupon' => 'WELCOME10',
'metadata' => json_encode([
'source' => 'cart_page'
])
];

$ch = curl_init($url);

curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_FOLLOWLOCATION => false,
]);

$response = curl_exec($ch);
$info = curl_getinfo($ch);

if ($info['http_code'] == 303) {
preg_match('/^Location:\s+(.*)$/mi', $response, $matches);
$location = trim($matches[1]);

curl_close($ch);
header("Location: $location", true, 303);
exit;
}

// The request did not result in a redirect — something went wrong.
$headerSize = $info['header_size'];
$body = substr($response, $headerSize);
curl_close($ch);

error_log("Cart request failed with status {$info['http_code']}: $body");

The example sets CURLOPT_FOLLOWLOCATION => false on purpose: you want to capture the Location header and forward the redirect to the shopper's browser, not follow it server-side. Re-emitting it with header("Location: $location", true, 303) preserves the 303 status so the browser performs the redirect.

curl Example​

curl -i -X POST https://checkout.simpler.so/v1/carts \
--data-urlencode 'merchant_id=YOUR_APP_ID' \
--data-urlencode 'currency=EUR' \
--data-urlencode 'locale=en' \
--data-urlencode 'items=[{"id":"PRODUCT_ID","quantity":1,"attributes":{"color":"blue","size":"L"}}]' \
--data-urlencode 'coupon=WELCOME10' \
--data-urlencode 'metadata={"source":"cart_page"}'

The -i flag includes the response headers in the output, so you can see the 303 status and the Location header.

Error Responses​

All error responses return a JSON body with a message field describing the issue.

Status CodeMeaning
400Invalid request body.
404Invalid App ID / Store not found.
500Internal server error.