POST /v1/sessions
curl --request POST \
--url https://api.agentscore.com/v1/sessionsconst options = {method: 'POST'};
fetch('https://api.agentscore.com/v1/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.agentscore.com/v1/sessions"
response = requests.post(url)
print(response.text)API Reference
POST /v1/sessions
Create a verification session for identity bootstrapping. Available on all tiers, gated by monthly quota.
POST
/
v1
/
sessions
POST /v1/sessions
curl --request POST \
--url https://api.agentscore.com/v1/sessionsconst options = {method: 'POST'};
fetch('https://api.agentscore.com/v1/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.agentscore.com/v1/sessions"
response = requests.post(url)
print(response.text)This endpoint is available on all tiers, gated by monthly quota (pricing).
Overview
Verification sessions let merchants bootstrap identity for agents that don’t have a wallet or operator credential. When an agent tries to perform a gated action without identity, the merchant creates a session and returns the verification URL to the agent. The session returns two secrets:session_id: goes in the verification URL (user-facing)poll_secret: given to the agent for polling (never in URLs)
Request
Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | Your API key (any tier, including Free) |
Content-Type | Yes | application/json |
Body
{
"context": "wine_purchase",
"product_name": "2022 Martin Estate Rose"
}
| Field | Type | Required | Description |
|---|---|---|---|
context | string | No | Freeform context label (e.g., “wine_purchase”) |
product_name | string | No | Product name shown during verification (max 200 chars) |
GET /v1/sessions/:token. There is no browser redirect back to the merchant; this API does not accept return_url or any payment-method metadata.
Response
{
"session_id": "sess_abc123...",
"poll_secret": "poll_xyz789...",
"verify_url": "https://www.agentscore.com/verify?session=sess_abc123...",
"poll_url": "https://api.agentscore.com/v1/sessions/sess_abc123...",
"expires_at": "2026-04-09T13:00:00Z",
"next_steps": {
"action": "deliver_verify_url_and_poll",
"poll_interval_seconds": 5,
"poll_secret_header": "X-Poll-Secret",
"steps": [
"Deliver verify_url to the end user so they can complete identity verification in the browser.",
"Poll poll_url every 5 seconds, sending poll_secret in the X-Poll-Secret header.",
"When status becomes verified, the operator_token is returned in that poll response exactly once, save it and retry the original merchant request with X-Operator-Token."
],
"user_message": "Share verify_url with the user so they can verify identity, then poll poll_url with X-Poll-Secret until an operator_token is issued."
},
"agent_memory": {
"pattern_summary": "...",
"identity_check_endpoint": "...",
"identity_paths": { "...": "..." },
"bootstrap": { "...": "..." },
"do_not_persist_in_memory": ["operator_token", "poll_secret"],
"persist_in_credential_store": ["operator_token"]
}
}
Response fields
| Field | Type | Description |
|---|---|---|
session_id | string | Opaque session identifier, shown in verify_url (user-facing) |
poll_secret | string | Agent-only secret for the X-Poll-Secret header when polling |
verify_url | string | Ready-to-open URL the end user visits to complete KYC |
poll_url | string | Polling endpoint for session status |
expires_at | string | ISO 8601 session expiry (1 hour TTL) |
next_steps | object | Structured agent instructions for consuming the session (action: "deliver_verify_url_and_poll", polling cadence, step-by-step) |
agent_memory | object | Cross-merchant pattern hint: LLM-hosted agents should persist the pattern (never secrets) so future AgentScore merchants skip the cold-start flow. Also emitted on POST /v1/credentials success and on first-mint missing_identity denials |
Polling
GET /v1/sessions/{session_id}
X-Poll-Secret: poll_xyz789...
| Status | Meaning |
|---|---|
pending | User hasn’t completed verification yet |
verified | User verified: operator_token included in response |
consumed | Token already issued to a previous poll |
expired | Session expired (1 hour TTL) |
failed | Stripe Identity verification did not succeed (unreadable ID, selfie mismatch, etc.) |
flagged | Identity verified but sanctions screening flagged a potential match: credential issuance is blocked pending manual review |
Poll response by status
Pending; user hasn’t completed verification yet:{
"session_id": "sess_abc123...",
"status": "pending",
"retry_after_seconds": 5,
"next_steps": {
"action": "continue_polling",
"poll_interval_seconds": 5,
"eta_message": "Users typically complete identity verification in 2-5 minutes. Continue polling every 5 seconds until status becomes verified, consumed, or expired."
}
}
operator_token included:
{
"session_id": "sess_abc123...",
"status": "verified",
"operator_token": "opc_newtoken...",
"completed_at": "2026-04-09T12:30:00Z",
"token_ttl_seconds": 86400,
"next_steps": {
"action": "retry_merchant_request_with_operator_token",
"header_name": "X-Operator-Token",
"user_message": "Verification complete. Retry the original merchant request with X-Operator-Token set to the operator_token value."
}
}
consumed without the token.
Consumed; token already issued to a previous poll:
{
"session_id": "sess_abc123...",
"status": "consumed",
"next_steps": {
"action": "use_stored_operator_token",
"user_message": "The operator_token was already delivered on a previous poll. If you did not save it, ask the merchant to create a new session."
}
}
{
"session_id": "sess_abc123...",
"status": "expired",
"next_steps": {
"action": "create_new_session",
"user_message": "This verification session has expired."
}
}
{
"session_id": "sess_abc123...",
"status": "failed",
"next_steps": {
"action": "verification_failed",
"user_message": "Identity verification was not successful. The user may need to try again with a clearer photo or different ID. Create a new purchase to start a fresh verification session."
}
}
{
"session_id": "sess_abc123...",
"status": "flagged",
"next_steps": {
"action": "contact_support",
"support_email": "support@agentscore.com",
"support_subject": "Sanctions screening dispute",
"user_message": "Identity was verified, but sanctions screening flagged a potential match. Credentials cannot be issued automatically. If you believe this is in error, contact support@agentscore.com to dispute."
}
}
Poll response fields
| Field | Type | When present | Description |
|---|---|---|---|
next_steps | object | Always | Action guidance that varies by status |
retry_after_seconds | number | pending | Recommended poll interval in seconds |
token_ttl_seconds | number | verified | TTL of the issued operator token in seconds |
Rate limits
The poll endpoint is rate-limited to 30 requests per minute per IP. Responses includeX-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.