Cross-Login
A shopper who is already logged in to your store can arrive at Simpler Checkout already signed in, with their name, email and saved addresses filled in. Your integration hands Simpler a token identifying the shopper, and Simpler exchanges it for the shopper's profile by calling your /customer endpoint.
Simpler finds the shopper by the email you return, or creates them as a Simpler customer if they are new, and imports your saved addresses. The shopper then has a Simpler session for this checkout and future ones.
Prerequisites
- You have implemented Replacing Checkout, checkout URLs or the JavaScript SDK. The token travels with the cart.
- Cross-login is enabled for your store in Simpler. Without it, Simpler ignores the token and the shopper checks out as a guest.
Overview
Step 1: Issue a Session Token
When a logged-in shopper proceeds to checkout, create a token that your /customer endpoint can later resolve back to that shopper. Simpler treats the token as opaque: it never reads it, and only passes it back to you.
- Make it unguessable and short-lived. Anyone holding a valid token can sign in to Simpler Checkout as that shopper. Use a random value mapped to the customer on your side, and let it expire. A token sent with a server-side redirect is used within seconds, so minutes are enough. A token rendered into a page for the button or a checkout link must outlive the page view, so a few hours is reasonable. If a token has expired by the time it is used, the shopper checks out as a guest.
- Issue a fresh token per page or checkout. Simpler resolves each token at most once per checkout, so you can invalidate it after the first lookup.
- Skip it for guests. Without a token, the shopper checks out as a guest, as before.
Do not use a value that never expires, such as the customer ID or a reversible encryption of it.
Step 2: Pass the Token with the Cart
Send the token with the cart:
| Flow | Where the token goes |
|---|---|
| Replacing Checkout | Form field remote_session_id |
| Checkout URL | Query parameter sessid |
| JavaScript SDK | sessionId option of Simpler.checkout() |
merchant_id=YOUR_APP_ID¤cy=EUR&locale=en&items=...&remote_session_id=8f14e45f-ceea-467a-9f5b-3a2d8c1e6b70
Step 3: Resolve the Token
When the shopper opens checkout, Simpler calls your /customer endpoint with the token:
{
"request_id": "d1280b05-ca5c-4af2-8dcb-6ae81572dcba",
"session_id": "8f14e45f-ceea-467a-9f5b-3a2d8c1e6b70"
}
If the token belongs to a registered customer, respond with their profile:
{
"request_id": "d1280b05-ca5c-4af2-8dcb-6ae81572dcba",
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com"
},
"addresses": [
{
"first_name": "John",
"last_name": "Doe",
"phone": "+4412345678",
"street": "128 City Road",
"city": "London",
"postcode": "EC1V 2NX",
"country": "GB"
}
]
}
emailmust be the shopper's real email. Simpler matches the shopper to an existing Simpler customer by it.- Invalid addresses are skipped. Each needs
street,city,postcodeand a two-letter ISO 3166-1countrycode. - For Spanish addresses, a
dnifield is saved as the shopper's DNI.
If the token is unknown, expired or belongs to a guest account, respond with an HTTP 400 and the USER_NOT_FOUND code (see Error Codes):
{
"request_id": "d1280b05-ca5c-4af2-8dcb-6ae81572dcba",
"code": "USER_NOT_FOUND",
"message": "user not found"
}
Whatever goes wrong, the shopper is never blocked: they continue checkout as a guest.
Signing In by Email
The same endpoint also serves shoppers who reach Simpler Checkout without a token. When a shopper signs in with an email Simpler does not know yet, Simpler calls /customer with that email instead of a token:
{
"request_id": "d1280b05-ca5c-4af2-8dcb-6ae81572dcba",
"email": "john@example.com"
}
Respond exactly as in step 3. If you return a profile, Simpler imports it and sends a one-time sign-in code to that email, so only the owner of the inbox can sign in.
PHP Example
Issue a token on proceed to checkout. $cache is any store with expiry, such as Redis or APCu:
const TOKEN_TTL = 600;
if ($customer_id = current_customer_id()) {
$token = bin2hex(random_bytes(16));
$cache->set('simpler_session_' . $token, $customer_id, TOKEN_TTL);
$cart_request['remote_session_id'] = $token;
}
// POST $cart_request to /v1/carts and forward the 303 — see Replacing Checkout.
Resolve it in your /customer endpoint:
function handle_customer(array $request, CacheInterface $cache): array
{
if (!empty($request['session_id'])) {
$key = 'simpler_session_' . $request['session_id'];
$customer = find_customer_by_id($cache->get($key));
$cache->delete($key);
} else {
$customer = find_customer_by_email($request['email'] ?? '');
}
if (!$customer || $customer->is_guest) {
http_response_code(400);
return ['request_id' => $request['request_id'], 'code' => 'USER_NOT_FOUND', 'message' => 'user not found'];
}
return [
'request_id' => $request['request_id'],
'customer' => [
'first_name' => $customer->first_name,
'last_name' => $customer->last_name,
'email' => $customer->email,
],
'addresses' => array_map(fn ($a) => [
'first_name' => $a->first_name,
'last_name' => $a->last_name,
'phone' => $a->phone,
'street' => $a->street,
'city' => $a->city,
'postcode' => $a->postcode,
'region' => $a->region,
'country' => $a->country,
], $customer->addresses),
];
}