curl --request POST \
--url https://api2.endstate.io/v1/wallet/sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"publishable_key": "end_pk_live_0123456789abcdef0123456789abcdef"
}
'import requests
url = "https://api2.endstate.io/v1/wallet/sessions"
payload = { "publishable_key": "end_pk_live_0123456789abcdef0123456789abcdef" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({publishable_key: 'end_pk_live_0123456789abcdef0123456789abcdef'})
};
fetch('https://api2.endstate.io/v1/wallet/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api2.endstate.io/v1/wallet/sessions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'publishable_key' => 'end_pk_live_0123456789abcdef0123456789abcdef'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api2.endstate.io/v1/wallet/sessions"
payload := strings.NewReader("{\n \"publishable_key\": \"end_pk_live_0123456789abcdef0123456789abcdef\"\n}")
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(string(body))
}HttpResponse<String> response = Unirest.post("https://api2.endstate.io/v1/wallet/sessions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"publishable_key\": \"end_pk_live_0123456789abcdef0123456789abcdef\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api2.endstate.io/v1/wallet/sessions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"publishable_key\": \"end_pk_live_0123456789abcdef0123456789abcdef\"\n}"
response = http.request(request)
puts response.read_body{
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...",
"session_token": "end_wsess_AbCd_example_token",
"expires_at": 1755640000,
"chain_id": 8453
}{
"error": {
"code": "validation.failed",
"message": "The request failed schema validation. See `error.details` for per-field issues.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/validation-failed"
}
}{
"error": {
"code": "auth.unauthorized",
"message": "Credential is missing or malformed.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/auth-unauthorized"
}
}{
"error": {
"code": "auth.forbidden",
"message": "Credential is valid but does not have access to the requested resource or action.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/auth-forbidden"
}
}{
"error": {
"code": "rate_limit.exceeded",
"message": "Per-key rate limit exceeded.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/rate-limit-exceeded"
}
}{
"error": {
"code": "internal.error",
"message": "An unexpected server error occurred. Retry with exponential backoff and include `request_id` in any support request.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/internal-error"
}
}Start a wallet session
Exchanges the single-use identity credential presented in the Authorization: Bearer header for a wallet session belonging to the customer it identifies. Once the exchange accepts the credential it is spent, whether or not the rest of the exchange succeeds. Customers who have not verified an email address have no wallet and are refused. The Endstate wallet frame calls this endpoint; your own code does not.
curl --request POST \
--url https://api2.endstate.io/v1/wallet/sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"publishable_key": "end_pk_live_0123456789abcdef0123456789abcdef"
}
'import requests
url = "https://api2.endstate.io/v1/wallet/sessions"
payload = { "publishable_key": "end_pk_live_0123456789abcdef0123456789abcdef" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({publishable_key: 'end_pk_live_0123456789abcdef0123456789abcdef'})
};
fetch('https://api2.endstate.io/v1/wallet/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api2.endstate.io/v1/wallet/sessions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'publishable_key' => 'end_pk_live_0123456789abcdef0123456789abcdef'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api2.endstate.io/v1/wallet/sessions"
payload := strings.NewReader("{\n \"publishable_key\": \"end_pk_live_0123456789abcdef0123456789abcdef\"\n}")
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(string(body))
}HttpResponse<String> response = Unirest.post("https://api2.endstate.io/v1/wallet/sessions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"publishable_key\": \"end_pk_live_0123456789abcdef0123456789abcdef\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api2.endstate.io/v1/wallet/sessions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"publishable_key\": \"end_pk_live_0123456789abcdef0123456789abcdef\"\n}"
response = http.request(request)
puts response.read_body{
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...",
"session_token": "end_wsess_AbCd_example_token",
"expires_at": 1755640000,
"chain_id": 8453
}{
"error": {
"code": "validation.failed",
"message": "The request failed schema validation. See `error.details` for per-field issues.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/validation-failed"
}
}{
"error": {
"code": "auth.unauthorized",
"message": "Credential is missing or malformed.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/auth-unauthorized"
}
}{
"error": {
"code": "auth.forbidden",
"message": "Credential is valid but does not have access to the requested resource or action.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/auth-forbidden"
}
}{
"error": {
"code": "rate_limit.exceeded",
"message": "Per-key rate limit exceeded.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/rate-limit-exceeded"
}
}{
"error": {
"code": "internal.error",
"message": "An unexpected server error occurred. Retry with exponential backoff and include `request_id` in any support request.",
"request_id": "req_8e1a7f50-90ab-4cde-f012-3456789abcde",
"doc_url": "https://docs.endstate.io/errors/internal-error"
}
}Authorizations
Use Authorization: Bearer <identity token> - a single-use, short-lived token identifying the customer, issued by your own sign-in.
Body
The publishable key of the site the wallet is embedded in.
1Response
The session was started.
Credential the wallet presents to establish the customer's session.
Credential the wallet presents when resolving an operation to sign.
Unix seconds at which session_token lapses. token is shorter-lived and the wallet refreshes it on its own; do not treat this as its expiry.
Network the session operates on.

