Create account-bootstrap session
Create an account-bootstrap session for agent-driven onboarding. Public endpoint (rate limited: 15/min per IP, plus a per-identity budget of 3/hour for the email and SMS channels that no amount of IP rotation avoids).
The session is ALWAYS tagged type="account_creation". It does NOT branch on whether the submitted identity already maps to a User — the response is uniform by design, because a differing shape or timing would answer "does this address have an account here?" to anyone who asks. Completing verification transparently creates a User when none exists or signs the existing one in; an agent that needs to tell those apart calls GET /auth/me afterwards and reads created_at.
THE EMAIL CHANNEL SENDS NOTHING HERE (email_sent: false, send_required: true). Delivering a message from our domain to an address nobody has proven is a separate, explicit act: POST /api/v1/accounts/{id}/send. The other channels are inbound — the user messages us (reverse OTP) — so nothing is dispatched to them at all.
No credential is required. A client that DOES present an API key (Authorization: Bearer pk_…) has it checked: a key the API no longer accepts is refused with 401 invalid_api_key before anything is stored, and a live one is recorded so the session issued on completion is BOUND to it — revoking the key by any path ends that session.
Request
- Base URL: https://api.proof.holdings
- URL: https://api.proof.holdings/api/v1/accounts
- Auth: none declared
Request body
Example request
{
"channel": "telegram",
"phone_number": "+37069199199",
"email": "alex@example.com"
}Response
Account session created
Example response
{
"id": "auth_9c2f...",
"type": "account_creation",
"channel": "telegram",
"status": "pending",
"deep_link": "https://t.me/bot?start=auth_9c2f...",
"expires_at": "2026-04-16T20:10:00Z"
}Changes
No recorded changes to this operation across all 1 revision of this API.