There are several integration points between your system and Express Checkout (XCO) when you want to benefit from the XCO checkout within your checkout experience.
The main integration point is located at customer signup. Depending on whether the customer already has an XCO account, two distinct flows apply:
- No existing XCO account → You create a new XCO account for the customer alongside their account in your system.
- Existing XCO account → You link the existing XCO account via a passwordless authentication flow.
This guide walks you through the full signup integration, step by step:
- Check if your customer already has an XCO account
- Create a new XCO user (if no account exists)
- Authenticate an existing XCO user via passwordless OTP
- Link the XCO account to your customer record via consent
Prerequisites
Before starting, ensure you have:
- Your Purse API account with XCO access, including your API credentials (
API_KEY, CLIENT_ID, CLIENT_SECRET).
- Your
MERCHANT_ID (UUID) as provided by the Purse Integration Team.
- A server with HTTPS enabled for secure transactions.
- A valid OAuth2 Access Token with the
xco-api scope.
Before making any XCO API calls, you must authenticate by obtaining an OAuth2 Access Token.
See the Authentication Guide for details on generating your token.
TLDR : Summary of API Calls
| Step | Condition | Endpoint | Method |
|---|
| 1. Check user exists | Always | /v1/users/exists?email={email} | GET |
| 2A. Create user | No XCO account | /v1/merchants/{merchantId}/users | POST |
| 2B1. Start passwordless | XCO account exists | /v1/merchants/{merchantId}/users/passwordless/start | POST |
| 2B2. Verify passwordless | XCO account exists | /v1/merchants/{merchantId}/users/passwordless/verify | POST |
| 2B3. Create consent | XCO account exists | /v1/merchants/{merchantId}/users/{customerReference}/consents | POST |
1. Check if XCO User Exists
Your first step is to check whether your customer already has an XCO account. The response determines which flow you should follow.
You can search by email or phone number:
Example Request (by email)
curl -X GET 'https://xco-api.purse-sandbox.com/v1/users/[email protected]' \
--header "Authorization: Bearer ${ACCESS_TOKEN}"
Example Request (by phone number)
curl -X GET 'https://xco-api.purse-sandbox.com/v1/users/exists?phone_number=%2B331234567890' \
--header "Authorization: Bearer ${ACCESS_TOKEN}"
Example Responses
User exists
{
"exists": true,
"token_count": 2
}
User does not exist
{
"exists": false,
"token_count": 0
}
You must pass a caller_id query parameter (e.g., the browser IP address or any unique identifier) to enable granular rate limiting. Without it, rate limiting is applied solely based on your clientId, which may lead to blocking legitimate requests from your customers in production.
Based on the response, proceed to Step 2A (no account) or Step 2B (existing account).
2A. No Existing XCO Account — Create User
If your customer does not have an XCO account ("exists": false), you need to collect their data and create an XCO account alongside their account in your system.
Flow Overview
Create User with Consent
Once you have created the customer account on your side, send their data to the XCO API.
Example Request
curl -X POST 'https://xco-api.purse-sandbox.com/v1/merchants/${MERCHANT_ID}/users' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-raw '{
"customer_reference": "customer_12345",
"user": {
"email": "[email protected]",
"phone_number": "+33612345678",
"first_name": "John",
"last_name": "Doe",
"gender": "male",
"birthdate": "1990-01-15",
"addresses": [
{
"address_type": "billing",
"street_address": "123 Main Street",
"address_complement": "Apt 4B",
"locality": "Paris",
"postal_code": "75001",
"country": "FRANCE"
}
]
}
}'
Example Response
{
"customer_reference": "customer_12345",
"user": {
"email": "[email protected]",
"phone_number": "+33612345678",
"first_name": "John",
"last_name": "Doe",
"gender": "male",
"birthdate": "1990-01-15",
"addresses": [
{
"address_type": "billing",
"street_address": "123 Main Street",
"address_complement": "Apt 4B",
"locality": "Paris",
"postal_code": "75001",
"country": "FRANCE"
}
]
}
}
customer_reference → Your own customer identifier. Used to link the XCO account to your system.
user → The customer profile data. At minimum, an email is required.
The XCO account and your consent are now created. Your customer can benefit from Express Checkout on future payments. ✅
2B. Existing XCO Account — Passwordless Flow
If your customer already has an XCO account ("exists": true), you must authenticate them using a passwordless OTP flow before linking the accounts.
Flow Overview
This flow consists of three sub-steps:
2B1. Start Passwordless Authentication
Initiate the passwordless flow by sending an OTP to the customer's email or phone number.
- Endpoint:
/v1/merchants/{merchantId}/users/passwordless/start
- Method:
POST
- XCO API Reference
Example Request (by email)
curl -X POST 'https://xco-api.purse-sandbox.com/v1/merchants/${MERCHANT_ID}/users/passwordless/start' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-raw '{
"email": "[email protected]"
}'
Example Request (by phone number)
curl -X POST 'https://xco-api.purse-sandbox.com/v1/merchants/${MERCHANT_ID}/users/passwordless/start' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-raw '{
"phone_number": "+33623456789"
}'
A successful request returns a 204 No Content response. The customer receives an OTP code via email or SMS.
You must include a caller_id field in the request body (e.g., the browser IP address or any unique identifier) to enable granular rate limiting. Without it, rate limiting is applied solely based on your clientId, which may lead to blocking legitimate requests from your customers in production.
2B2. Verify Passwordless Authentication
Once the customer provides the OTP code, verify it against the XCO API.
- Endpoint:
/v1/merchants/{merchantId}/users/passwordless/verify
- Method:
POST
- XCO API Reference
Example Request
curl -X POST 'https://xco-api.purse-sandbox.com/v1/merchants/${MERCHANT_ID}/users/passwordless/verify' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-raw '{
"email": "[email protected]",
"verification_code": "123456"
}'
Example Response
{
"consent_challenge_id": "ae900e3c-91df-4e71-ba49-60985827c258",
"user": {
"email": "[email protected]",
"phone_number": "+331234567890",
"first_name": "John",
"last_name": "Doe",
"gender": "male",
"birthdate": "1990-01-01",
"addresses": [
{
"address_type": "billing",
"street_address": "123 Main St",
"address_complement": "Apt 4B",
"locality": "Paris",
"postal_code": "75001",
"country": "FRANCE"
}
]
}
}
If the OTP code is invalid, the API returns an error. The customer should be prompted to retry entering the code.
consent_challenge_id → Required for the next step to finalize the consent. Store this value.
user → The existing XCO customer profile. Use this data to pre-fill your account creation form for a better user experience.
2B3. Create User Consent
After successful OTP verification, create the customer account on your side, then finalize the link between the XCO account and your customer record by submitting the consent challenge.
- Endpoint:
/v1/merchants/{merchantId}/users/{customerReference}/consents
- Method:
POST
- XCO API Reference
Example Request
curl -X POST 'https://xco-api.purse-sandbox.com/v1/merchants/${MERCHANT_ID}/users/customer_12345/consents' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-raw '{
"consent_challenge_id": "ae900e3c-91df-4e71-ba49-60985827c258"
}'
A successful request returns a 204 No Content response. The XCO account is now linked to the merchant account. ✅
The customerReference path parameter must be your own customer identifier — the reference you use to identify the customer in your system.
Next Steps
- Explore the Key Concepts to understand payment flows, session management, and authentication in depth.
- Check the complete XCO API Reference for all available endpoints.