Reference

Adapter protocol

The three signed endpoints your user database implements, with request and response formats and the signature scheme.

View .md llms.txt

The adapter protocol (version 2) is how 9in talks to your own user database. You implement three endpoints under a base URL; 9in calls them with signed JSON POST requests and expects signed responses. JSON Schemas: user, /authenticate request, /user request, event.

#Requests

Header
Content-Typeapplication/json
9in-signaturet=<unix seconds>,v1=<hex HMAC-SHA256>
9in-request-idA unique id for this request

The signature covers <t>.POST.<path>.<raw body> with the shared secret from the console. Reject requests more than 5 minutes off, or with a wrong signature (compare in constant time).

#Responses

Sign every response with your own 9in-signature header, computed the same way over <t>.POST.<path>#<request id>.<response body>, so a response can't be reused for another request. 9in rejects unsigned or wrongly signed responses. 9in waits up to the configured timeout (3 seconds by default).

#POST /authenticate

Check a password.

json
{ "identifier": { "type": "email", "value": "jane@acme.com" }, "password": "…" }

type is email, username or phone.

StatusBody
200{ "user": <user> }
401{ "error": "invalid_credentials" } (wrong password or unknown user: don't tell them apart)
403{ "error": "blocked" }

#POST /user

Look a user up.

json
{ "id": "42" }

or

json
{ "identifier": { "type": "phone", "value": "+447700900123" } }
StatusBody
200{ "user": <user> }
404{ "error": "not_found" }

#POST /event

json
{ "id": "evt_…", "type": "otp.requested", "createdAt": "2026-11-09T08:00:00.000Z", "data": { … } }

Answer any 2xx (204 is fine).

Typedata
otp.requesteduserId, channel (email or sms), to, code, purpose (login or password_reset), expiresAt (ISO 8601)
user.updateduserId, fields
user.password_changeduserId, fields

userId is your id. Passwords are never sent.

#The user object

FieldType
idstring, requiredYour user id (up to 256 characters)
emailstring or null
email_verifiedboolean or null
phone_numberstring or nullE.164
phone_number_verifiedboolean or null
usernamestring or null
name, given_name, family_namestring or null
picturestring or nullhttps URL
locale, zoneinfostring or null
birthdatestring or nullYYYY-MM-DD
blockedboolean or nulltrue refuses sign-in
metadataobject or nullStored on the 9in user

Unknown fields are ignored.