threshold1

Email OTP

Two endpoints, both live-verified against the real hosted API. No dashboard configuration needed. See Email OTP for the conceptual model and real values (TTL, attempts, rate limits) — this page is call shapes only.

Send a code

POST /api/v1/otp/send
Authorization: Bearer th_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

{ "email": "user@example.com" }

Real response, captured live:

{ "success": true }

This queues a real email — confirmed live by receiving one. (The route's own source comment still says "writes it to stdout instead of sending a real email" — that's stale, left over from an early build; real delivery has been verified repeatedly this session.)

Verify the code

POST /api/v1/otp/verify
Authorization: Bearer th_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

{ "email": "user@example.com", "code": "040602" }

Real response, captured live — richer than you might expect from a quick skim of the route's own comment, which only mentions token/userId:

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "userId": "274f4b7d-34cb-4770-941f-71f60681bd8b",
  "externalUserId": null,
  "user": null,
  "companyId": null,
  "deviceToken": "eyJhbGciOiJIUzI1NiJ9...",
  "isNewUser": true
}

token is the session JWT — use it as Authorization: Bearer <token> on every subsequent user-scoped call (see Account & Session).

Errors

Real captured error, a wrong code:

{ "success": false, "error": "Invalid or expired code.", "code": "INVALID_CODE" }

401

Worth knowing precisely: this route's code field collapses every non-fatal failure — wrong code, expired code, and too-many-attempts lockout — into the same "INVALID_CODE" string. Confirmed by reading the route's own logic, not assumed. Only the human-readable error text actually differs between those three cases (e.g. "Too many attempts. Request a new code." for the lockout). If your integration needs to branch behavior on which of these three happened, you can't do it from code alone — read error, or track your own attempt count client-side.

See Error Reference for the full list of possible codes on both endpoints.

What's next

  • Email OTP (Methods Reference) — the conceptual model, TTL, attempts, rate limits.
  • Account & Session — what to do with the token you get back.