Create an Elements session
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");curl_easy_setopt(hnd, CURLOPT_URL, "https://example.com/api/sessions");
struct curl_slist *headers = NULL;headers = curl_slist_append(headers, "Authorization: Bearer <token>");headers = curl_slist_append(headers, "Content-Type: application/json");curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{ \"currency\": \"EUR\", \"total\": 100000, \"methods\": [ { \"method\": \"card\", \"partialAuth\": true } ], \"orderId\": \"EP-123456\", \"statementDescriptor\": \"SEJOUR MONTAGNE\" }");
CURLcode ret = curl_easy_perform(hnd);using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Post, RequestUri = new Uri("https://example.com/api/sessions"), Headers = { { "Authorization", "Bearer <token>" }, }, Content = new StringContent("{ \"currency\": \"EUR\", \"total\": 100000, \"methods\": [ { \"method\": \"card\", \"partialAuth\": true } ], \"orderId\": \"EP-123456\", \"statementDescriptor\": \"SEJOUR MONTAGNE\" }") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://example.com/api/sessions"
payload := strings.NewReader("{ \"currency\": \"EUR\", \"total\": 100000, \"methods\": [ { \"method\": \"card\", \"partialAuth\": true } ], \"orderId\": \"EP-123456\", \"statementDescriptor\": \"SEJOUR MONTAGNE\" }")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com/api/sessions")) .header("Authorization", "Bearer <token>") .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("{ \"currency\": \"EUR\", \"total\": 100000, \"methods\": [ { \"method\": \"card\", \"partialAuth\": true } ], \"orderId\": \"EP-123456\", \"statementDescriptor\": \"SEJOUR MONTAGNE\" }")) .build();HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.body());OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{ \"currency\": \"EUR\", \"total\": 100000, \"methods\": [ { \"method\": \"card\", \"partialAuth\": true } ], \"orderId\": \"EP-123456\", \"statementDescriptor\": \"SEJOUR MONTAGNE\" }");Request request = new Request.Builder() .url("https://example.com/api/sessions") .post(body) .addHeader("Authorization", "Bearer <token>") .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();import axios from 'axios';
const options = { method: 'POST', url: 'https://example.com/api/sessions', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, data: { currency: 'EUR', total: 100000, methods: [{method: 'card', partialAuth: true}], orderId: 'EP-123456', statementDescriptor: 'SEJOUR MONTAGNE' }};
try { const { data } = await axios.request(options); console.log(data);} catch (error) { console.error(error);}const url = 'https://example.com/api/sessions';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"currency":"EUR","total":100000,"methods":[{"method":"card","partialAuth":true}],"orderId":"EP-123456","statementDescriptor":"SEJOUR MONTAGNE"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}val client = OkHttpClient()
val mediaType = MediaType.parse("application/json")val body = RequestBody.create(mediaType, "{ \"currency\": \"EUR\", \"total\": 100000, \"methods\": [ { \"method\": \"card\", \"partialAuth\": true } ], \"orderId\": \"EP-123456\", \"statementDescriptor\": \"SEJOUR MONTAGNE\" }")val request = Request.Builder() .url("https://example.com/api/sessions") .post(body) .addHeader("Authorization", "Bearer <token>") .addHeader("Content-Type", "application/json") .build()
val response = client.newCall(request).execute()use serde_json::json;use reqwest;
#[tokio::main]pub async fn main() { let url = "https://example.com/api/sessions";
let payload = json!({ "currency": "EUR", "total": 100000, "methods": ( json!({ "method": "card", "partialAuth": true }) ), "orderId": "EP-123456", "statementDescriptor": "SEJOUR MONTAGNE" });
let mut headers = reqwest::header::HeaderMap::new(); headers.insert("Authorization", "Bearer <token>".parse().unwrap()); headers.insert("Content-Type", "application/json".parse().unwrap());
let client = reqwest::Client::new(); let response = client.post(url) .headers(headers) .json(&payload) .send() .await;
let results = response.unwrap() .json::<serde_json::Value>() .await .unwrap();
dbg!(results);}curl --request POST \ --url https://example.com/api/sessions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "currency": "EUR", "total": 100000, "methods": [ { "method": "card", "partialAuth": true } ], "orderId": "EP-123456", "statementDescriptor": "SEJOUR MONTAGNE" }'wget --quiet \ --method POST \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --body-data '{ "currency": "EUR", "total": 100000, "methods": [ { "method": "card", "partialAuth": true } ], "orderId": "EP-123456", "statementDescriptor": "SEJOUR MONTAGNE" }' \ --output-document \ - https://example.com/api/sessionsServer-to-server, behind a client_credentials access token (POST /oauth/token). The merchantId comes from the TOKEN, never from the body. Replies with the opaque session token used in your payment page.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
ISO 4217 code. ONE currency per session — every amount below is in it, and no conversion happens.
What the order costs, in the MINOR unit (1000_00 = one thousand euros).
The methods this order offers, in the order to display them. One entry per method — or per INSTANCE, when the same method is offered twice under different terms (a plain card and Amex).
object
Which method this entry configures — it selects the shape of the object.
The issuer may authorize LESS than requested (partial approval). Enable only if your acquirer contract carries the option — the payer is then offered to accept the lower hold (and pay the rest another way) or refuse it. Omitted or false, a lower grant is refused by the orchestrator.
Card networks this entry accepts, in the order to display them. Omitted, the ones your contract carries. Listing one your acquirer does not serve earns a refusal at the till.
Asks the PSP to register the card for later payments. The payer’s consent is the merchant’s business, collected upstream. Requires the 3-D Secure challenge: combined with threeDSecure: "frictionless", session creation is refused.
object
oneclick: the payer picks the stored card again. subscription: the merchant initiates.
Days between two recurring payments.
Last day the registration may be used, ISO date (YYYY-MM-DD).
Preferred 3-D Secure outcome: sca asks for the challenge, frictionless asks to be spared it. The issuer decides either way. Defaults to sca — requesting frictionless requests an exemption, which moves the fraud liability to the requester.
Ask the payer for the cardholder’s name. Off by default — one field fewer is one abandonment fewer, and few acquirers need it.
Instance key, when the same method appears twice under different terms (a plain card and an Amex-only one). Omitted, the method name serves. It is what the page passes back to start a attempt, so it must be unique within the session.
Name to display instead of the method’s own — for a promoted instance.
Which PSP charges this method. OPTIONAL: leave it out and the one your account is contracted with for this method is used. Several would fit and the call is refused, naming them — the choice is yours, never a default of ours. Named, it must carry a contract for THIS method: an account with us is not an account for everything.
Tranche window for this method: refuse anything outside it. Omitted, the method takes any amount up to the remaining balance.
object
Smallest amount this method accepts, in minor units (inclusive).
Largest amount this method accepts, in minor units (inclusive).
ISO 4217 code — always the session’s own.
object
Which method this entry configures — it selects the shape of the object.
Instance key, when the same method appears twice under different terms (a plain card and an Amex-only one). Omitted, the method name serves. It is what the page passes back to start a attempt, so it must be unique within the session.
Name to display instead of the method’s own — for a promoted instance.
Which PSP charges this method. OPTIONAL: leave it out and the one your account is contracted with for this method is used. Several would fit and the call is refused, naming them — the choice is yours, never a default of ours. Named, it must carry a contract for THIS method: an account with us is not an account for everything.
Tranche window for this method: refuse anything outside it. Omitted, the method takes any amount up to the remaining balance.
object
Smallest amount this method accepts, in minor units (inclusive).
Largest amount this method accepts, in minor units (inclusive).
ISO 4217 code — always the session’s own.
object
Which method this entry configures — it selects the shape of the object.
Instance key, when the same method appears twice under different terms (a plain card and an Amex-only one). Omitted, the method name serves. It is what the page passes back to start a attempt, so it must be unique within the session.
Name to display instead of the method’s own — for a promoted instance.
Which PSP charges this method. OPTIONAL: leave it out and the one your account is contracted with for this method is used. Several would fit and the call is refused, naming them — the choice is yours, never a default of ours. Named, it must carry a contract for THIS method: an account with us is not an account for everything.
Tranche window for this method: refuse anything outside it. Omitted, the method takes any amount up to the remaining balance.
object
Smallest amount this method accepts, in minor units (inclusive).
Largest amount this method accepts, in minor units (inclusive).
ISO 4217 code — always the session’s own.
object
Which method this entry configures — it selects the shape of the object.
Instance key, when the same method appears twice under different terms (a plain card and an Amex-only one). Omitted, the method name serves. It is what the page passes back to start a attempt, so it must be unique within the session.
Name to display instead of the method’s own — for a promoted instance.
Which PSP charges this method. OPTIONAL: leave it out and the one your account is contracted with for this method is used. Several would fit and the call is refused, naming them — the choice is yours, never a default of ours. Named, it must carry a contract for THIS method: an account with us is not an account for everything.
Tranche window for this method: refuse anything outside it. Omitted, the method takes any amount up to the remaining balance.
object
Smallest amount this method accepts, in minor units (inclusive).
Largest amount this method accepts, in minor units (inclusive).
ISO 4217 code — always the session’s own.
object
Which method this entry configures — it selects the shape of the object.
Shop this payment is billed under, at the PSP serving ANCV. Omit it to use the shop configured for your account — name it per session only if you have several.
Instance key, when the same method appears twice under different terms (a plain card and an Amex-only one). Omitted, the method name serves. It is what the page passes back to start a attempt, so it must be unique within the session.
Name to display instead of the method’s own — for a promoted instance.
Which PSP charges this method. OPTIONAL: leave it out and the one your account is contracted with for this method is used. Several would fit and the call is refused, naming them — the choice is yours, never a default of ours. Named, it must carry a contract for THIS method: an account with us is not an account for everything.
Tranche window for this method: refuse anything outside it. Omitted, the method takes any amount up to the remaining balance.
object
Smallest amount this method accepts, in minor units (inclusive).
Largest amount this method accepts, in minor units (inclusive).
ISO 4217 code — always the session’s own.
object
Which method this entry configures — it selects the shape of the object.
Which instalment plans THIS order offers, by name. Their fee rate, eligibility window and contractual code belong to your contract and are resolved at creation — a plan your contract does not carry is refused here.
object
How many instalments — 3 for a 3× plan.
Whether that plan carries fees. With installments, this NAMES the plan: the pair must be unique in the list.
Instance key, when the same method appears twice under different terms (a plain card and an Amex-only one). Omitted, the method name serves. It is what the page passes back to start a attempt, so it must be unique within the session.
Name to display instead of the method’s own — for a promoted instance.
Which PSP charges this method. OPTIONAL: leave it out and the one your account is contracted with for this method is used. Several would fit and the call is refused, naming them — the choice is yours, never a default of ours. Named, it must carry a contract for THIS method: an account with us is not an account for everything.
YOUR order reference — required. Every PSP operation carries it, the confirmation screen shows it, and it is what you (or support) search on to reconcile. A split payment sends several operations under this one reference. Max 31 characters: the PSP’s field is 40 and we append a 9-character per-operation suffix.
Filters your methods are matched against. A method restricted to countries or channels is NOT served when this says nothing of it — a whitelist does not contain “unknown”, and that is the first thing to check when a method you expect is missing.
object
ISO 3166-1 alpha-2 — WHERE this order is sold. What a method’s availability may depend on: an Amex contract opened for some countries, a lender financing in others.
YOUR sales channel, free text — a method or a financing plan may be reserved to some of them. The vocabulary is yours: we never validate it against a list, we only match it against what your contracts declare.
This order will be followed by payments YOU initiate later, so the payer’s means must be registered now. Two consequences: only methods able to register stay offered, and the order cannot be split (a mandate covers the order — two registrations would leave you guessing which one carries it). Asking for it with no method able to honour it is refused here.
The order lines, shown to the payer. REQUIRED — fully itemized — when the session offers a BNPL method: the lender reads every field of every line.
object
What the buyer reads for this line — shown as-is on the payment page.
How many units of it.
Price of the LINE — unit price × quantity, in minor units.
object
Amount in the MINOR unit of the currency — 1000_00 is one thousand euros, never 1000.
ISO 4217 code, uppercase. One currency per session.
PSP-facing itemization of this line. REQUIRED, in full, on a session that offers a BNPL method: the lender reads every field. Never shown to the payer — the payment page carries the label, the quantity and the amount, nothing of this block.
object
Your own catalogue reference. Required on a session that offers a BNPL method.
What this line IS, from the lender’s closed list. REQUIRED on every line of a session that offers a BNPL method — the platform has no default for what a shop sells.
Required on a session that offers a BNPL method.
Discount already applied to this line, in minor units.
Tax included in this line, in minor units.
How this line is delivered. Every field of it is required on a session that offers a BNPL method: the lender reads them, and the platform substitutes nothing.
object
How the goods reach the buyer. Required on a BNPL session.
Required on a BNPL session.
Required on a BNPL session.
In days. Required on a BNPL session.
Required on a BNPL session.
Free-form data echoed back by the PSP in its notifications and reporting (reconciliation). Never shown to the payer. Up to 255 characters.
The label that will appear on the payer’s BANK STATEMENT. Display-only on our side (the confirmation screen reassures with it); it is your acquirer contract that puts it on the line.
Where the customer returns after an off-site redirect (the PSP contract’s return_url) — the merchant’s payment page. Required only to use redirected methods.
Where the customer returns after cancelling or being refused off-site. Optional: absent, returnUrl serves for both outcomes.
Where to call this merchant back when the session ends — paid, abandoned or expired. Optional: absent, the address configured on your account is used, and if you have none the ending is not announced. Must be https (the agreed secret is a bearer token); plain http is accepted only for hosts that cannot exist on the public internet (localhost, a container name), which is what makes local development and the demo possible. Your endpoint must answer 200 with the body OK in text/plain, and be idempotent: a delivery may be repeated if your acknowledgement is lost.
How long the session stays open, in milliseconds. At the end, every hold is released and nothing was taken. Omitted, the platform default applies (15 minutes).
Who is paying. Required by BNPL contracts, which build a credit file from it.
object
The buyer’s activity with your shop, handed to the 3-D Secure risk assessment (more history means a better chance of a frictionless authentication). Send what you know.
object
Purchases in the last 24 hours.
Purchases in the last 12 months.
Purchases in the last 6 months.
Merchant-side unique customer identifier.
The buyer’s e-mail — where the PSP and the lender write, when they do.
The buyer’s own name. Used as the cardholder name when the card form does not collect one.
The buyer’s family name.
Billing address — the payer’s own. Optional in general, REQUIRED as soon as the order offers financing: a lender lends to a person (identity, address, one phone). A financed order without it is refused (BnplNeedsBillingAddress), naming the missing field. It is a separate question from WHERE you sell: this address never drives which methods are offered, and the root country never stands in for it.
object
Company at this address, when there is one. Oney requires it on the shipping block.
Given name of the person at this address.
Family name of the person at this address.
Civility, PSP-normalized.
Street line — number, street, complement.
Postal code as the country writes it.
City or town.
ISO 3166-1 alpha-2.
International format.
International format.
Delivery address, when goods are shipped. BNPL contracts read it.
object
Company at this address, when there is one. Oney requires it on the shipping block.
Given name of the person at this address.
Family name of the person at this address.
Civility, PSP-normalized.
Street line — number, street, complement.
Postal code as the country writes it.
City or town.
ISO 3166-1 alpha-2.
International format.
International format.
Travel itemization — what some BNPL contracts demand when the order is a stay or a trip.
object
Who travels — the lead traveller, when the contract asks for one.
object
Given name of the lead traveller.
Family name of the lead traveller.
Date of birth, YYYY-MM-DD.
One entry per stay of the trip.
object
Where the stay takes place — resort, city, site.
Arrival, YYYY-MM-DD.
Departure, YYYY-MM-DD.
What kind of stay it is, in your own words.
How many rooms or units.
How many people travel.
Whether the order includes travel insurance.
Whether the order includes a vehicle rental.
The terms your customer must see AND accept before paying — every one of them, in one gesture. Rendered by <payplug-terms>; the consent is recorded once, with the first tranche, the whole list as it stood.
object
Your wording, shown as-is — never translated, like statementDescriptor.
Where the full document lives — required: your customer must be able to read what they accept.
Example
{ "currency": "EUR", "total": 100000, "methods": [ { "method": "card", "partialAuth": true } ], "orderId": "EP-123456", "statementDescriptor": "SEJOUR MONTAGNE"}Responses
Section titled “Responses”Created — the opaque session token, the only handle the browser ever holds.
object
The opaque handle of the session — hand it to the payment page and nothing else. It is the ONLY client-side credential: the session id never leaves the server, and this token dies with the session.
Example
{ "elementsToken": "pst_Vv9c2QpQ0oJ5m1n8zR7lYkX4bH6sT3wA2dF1gK0jN5c"}InvalidRequest — the request could not be read: a missing or malformed field, a bad pattern, or a property this door does not declare (the message names it). Every door with a schema can answer this, before any business rule is consulted.
object
Stable machine-readable code — the one thing to branch on. Never parse the message.
English sentence for logs and operators. Wording may change; the code will not.
Example
{ "code": "InvalidRequest", "message": "body/<field> failed validation"}Unauthorized — the only code this response carries: no usable access token (absent, malformed, expired, or not a machine’s — a contact, even admin, cannot create a session). One answer for every failure shape.
object
Stable machine-readable code — the one thing to branch on. Never parse the message.
English sentence for logs and operators. Wording may change; the code will not.
Example
{ "code": "Unauthorized", "message": "a valid access token is required"}The session was refused, and the code says by which rule — every one of them.
Routing — which PSP serves each method you declared:
UnknownProvider: theprovideryou named is not one this platform carries.ProviderNotContracted: it is, but your account holds no contract for THAT method with it.AmbiguousProvider: you named none and several of your contracts would fit — the message lists them, pick one.NoProviderForMethod: you named none and none of your contracts serves that method at all.
The order itself:
InvalidOrderReference:orderIdis empty or longer than what a PSP will carry.DuplicateMethodId: two entries ofmethodsresolve to the same instance key, so one of them could never be started.InvalidNotificationUrl: the callback address cannot be called back — plain http on a public host, or not a URL at all.
BNPL:
UnknownBnplPlan: a plan you named is not one the lender’s contract offers.DuplicatePlan: the same plan appears twice on one method.BnplRequiresItemizedCart: a financed order must carry its cart lines — the lender demands them.BnplNeedsBillingAddress: a financed order must carry the payer’sbillingfile — a lender lends to a person, and that address’scountryis what decides which national contract prices the loan. The message names the first missing field.
Registering the payer’s means (mustCreateAlias):
AliasNeedsRegistrableMethod: none of the declared methods can register one.AliasRequiresChallenge: the method that would register it cannot carry the authentication such a mandate needs.
object
Stable machine-readable code — the one thing to branch on. Never parse the message.
English sentence for logs and operators. Wording may change; the code will not.
Example
{ "code": "ProviderNotContracted", "message": "no contract for this provider on this merchant"}