Create a new verification session
curl --request POST \
--url http://127.0.0.1:8787/v1/sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"redirect_url": "<string>",
"share_fields": {},
"webhook_endpoint_id": "<string>"
}
'import requests
url = "http://127.0.0.1:8787/v1/sessions"
payload = {
"redirect_url": "<string>",
"share_fields": {},
"webhook_endpoint_id": "<string>"
}
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({redirect_url: '<string>', share_fields: {}, webhook_endpoint_id: '<string>'})
};
fetch('http://127.0.0.1:8787/v1/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_PORT => "8787",
CURLOPT_URL => "http://127.0.0.1:8787/v1/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([
'redirect_url' => '<string>',
'share_fields' => [
],
'webhook_endpoint_id' => '<string>'
]),
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 := "http://127.0.0.1:8787/v1/sessions"
payload := strings.NewReader("{\n \"redirect_url\": \"<string>\",\n \"share_fields\": {},\n \"webhook_endpoint_id\": \"<string>\"\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("http://127.0.0.1:8787/v1/sessions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"redirect_url\": \"<string>\",\n \"share_fields\": {},\n \"webhook_endpoint_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://127.0.0.1:8787/v1/sessions")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"redirect_url\": \"<string>\",\n \"share_fields\": {},\n \"webhook_endpoint_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "vs_mza7vecksrtyfw193ekcvl5vnws3bt1lz96buu3iw7zidckf8dga2zx2echb3t16",
"status": "created",
"failure_code": null,
"nfc_tries_used": 0,
"liveness_tries_used": 0,
"contract_version": 1,
"share_fields": {
"document_type_code": {
"required": false,
"reason": "Needed to know the document type code",
"source": "rc"
},
"date_of_birth": {
"required": true,
"reason": "Needed to verify age eligibility",
"source": "rc"
},
"kayle_document_id": {
"required": true,
"reason": "Sharing \"Kayle Document ID\"",
"source": "default"
}
},
"redirect_url": "https://example.com/redirect",
"webhook_endpoint_id": null,
"verification_url": "https://verify.kayle.id/vs_mza7vecksrtyfw193ekcvl5vnws3bt1lz96buu3iw7zidckf8dga2zx2echb3t16",
"expires_at": "2025-01-01T00:00:00Z",
"completed_at": null,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
},
"error": null
}{
"data": null,
"error": {
"code": "UNKNOWN_CLAIM_KEY",
"message": "Unknown claim key.",
"hint": "Use a supported claim key from the share contract allowlist.",
"docs": "https://kayle.id/docs/api/sessions#create"
}
}{
"data": null,
"error": {
"code": "<string>",
"message": "<string>",
"hint": "<string>",
"docs": "<string>"
}
}{
"data": null,
"error": {
"code": "ORG_NOT_VERIFIED_LIMIT_EXCEEDED",
"message": "Unverified organizations are limited to 5 identity-revealing sessions per 24 hours.",
"hint": "Verify the organization in the platform settings, or wait until the rolling window resets. Age-gate-only sessions remain available.",
"docs": "https://kayle.id/docs/api/sessions#create"
}
}{
"data": null,
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "Internal server error.",
"hint": "The server encountered an error.",
"docs": "https://kayle.id/docs/api/errors"
}
}Sessions
Create a new verification session
POST
/
v1
/
sessions
Create a new verification session
curl --request POST \
--url http://127.0.0.1:8787/v1/sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"redirect_url": "<string>",
"share_fields": {},
"webhook_endpoint_id": "<string>"
}
'import requests
url = "http://127.0.0.1:8787/v1/sessions"
payload = {
"redirect_url": "<string>",
"share_fields": {},
"webhook_endpoint_id": "<string>"
}
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({redirect_url: '<string>', share_fields: {}, webhook_endpoint_id: '<string>'})
};
fetch('http://127.0.0.1:8787/v1/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_PORT => "8787",
CURLOPT_URL => "http://127.0.0.1:8787/v1/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([
'redirect_url' => '<string>',
'share_fields' => [
],
'webhook_endpoint_id' => '<string>'
]),
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 := "http://127.0.0.1:8787/v1/sessions"
payload := strings.NewReader("{\n \"redirect_url\": \"<string>\",\n \"share_fields\": {},\n \"webhook_endpoint_id\": \"<string>\"\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("http://127.0.0.1:8787/v1/sessions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"redirect_url\": \"<string>\",\n \"share_fields\": {},\n \"webhook_endpoint_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://127.0.0.1:8787/v1/sessions")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"redirect_url\": \"<string>\",\n \"share_fields\": {},\n \"webhook_endpoint_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "vs_mza7vecksrtyfw193ekcvl5vnws3bt1lz96buu3iw7zidckf8dga2zx2echb3t16",
"status": "created",
"failure_code": null,
"nfc_tries_used": 0,
"liveness_tries_used": 0,
"contract_version": 1,
"share_fields": {
"document_type_code": {
"required": false,
"reason": "Needed to know the document type code",
"source": "rc"
},
"date_of_birth": {
"required": true,
"reason": "Needed to verify age eligibility",
"source": "rc"
},
"kayle_document_id": {
"required": true,
"reason": "Sharing \"Kayle Document ID\"",
"source": "default"
}
},
"redirect_url": "https://example.com/redirect",
"webhook_endpoint_id": null,
"verification_url": "https://verify.kayle.id/vs_mza7vecksrtyfw193ekcvl5vnws3bt1lz96buu3iw7zidckf8dga2zx2echb3t16",
"expires_at": "2025-01-01T00:00:00Z",
"completed_at": null,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
},
"error": null
}{
"data": null,
"error": {
"code": "UNKNOWN_CLAIM_KEY",
"message": "Unknown claim key.",
"hint": "Use a supported claim key from the share contract allowlist.",
"docs": "https://kayle.id/docs/api/sessions#create"
}
}{
"data": null,
"error": {
"code": "<string>",
"message": "<string>",
"hint": "<string>",
"docs": "<string>"
}
}{
"data": null,
"error": {
"code": "ORG_NOT_VERIFIED_LIMIT_EXCEEDED",
"message": "Unverified organizations are limited to 5 identity-revealing sessions per 24 hours.",
"hint": "Verify the organization in the platform settings, or wait until the rolling window resets. Age-gate-only sessions remain available.",
"docs": "https://kayle.id/docs/api/sessions#create"
}
}{
"data": null,
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "Internal server error.",
"hint": "The server encountered an error.",
"docs": "https://kayle.id/docs/api/errors"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
Optional URL to redirect the user to after the verification session is completed. Must use https:// (http:// is only accepted for localhost in development).
Maximum string length:
2048Optional map of requested share fields keyed by claim key. Each entry must include required (boolean) and reason (non-empty string, max 200).
Show child attributes
Show child attributes
Optional webhook endpoint ID or endpoint ID list to target for this session. When omitted, events fan out to every enabled subscribed endpoint.
Required string length:
1 - 128Pattern:
^[A-Za-z0-9_-]+$Response
Successful operation. Returns the newly created verification session.
Show child attributes
Show child attributes
Example:
{ "id": "vs_mza7vecksrtyfw193ekcvl5vnws3bt1lz96buu3iw7zidckf8dga2zx2echb3t16", "status": "created", "failure_code": null, "nfc_tries_used": 0, "liveness_tries_used": 0, "contract_version": 1, "share_fields": { "document_type_code": { "required": false, "reason": "Needed to know the document type code", "source": "rc" }, "date_of_birth": { "required": true, "reason": "Needed to verify age eligibility", "source": "rc" }, "kayle_document_id": { "required": true, "reason": "Sharing \"Kayle Document ID\"", "source": "default" } }, "redirect_url": "https://example.com/redirect", "webhook_endpoint_id": null, "verification_url": "https://verify.kayle.id/vs_mza7vecksrtyfw193ekcvl5vnws3bt1lz96buu3iw7zidckf8dga2zx2echb3t16", "expires_at": "2025-01-01T00:00:00Z", "completed_at": null, "created_at": "2025-01-01T00:00:00Z", "updated_at": "2025-01-01T00:00:00Z" }
⌘I