---
title: "Verify Otp"
method: POST
path: "/api/auth/verify-otp"
---

# Verify Otp

`POST /api/auth/verify-otp`

Verify the 6-digit code the user typed into the SPA's inline
OTP input. On success, flip `is_active=1`, clear the OTP columns,
and return a session token + user payload — same shape as
`/api/auth/login` so the SPA can drop straight into the
authenticated experience without a second round-trip.

Failure modes, distinguished by `detail.code` so the SPA can
show targeted error copy:
  - `invalid_code`           — wrong digits, attempts now bumped
  - `code_expired`           — TTL elapsed
  - `too_many_attempts`      — attempt counter ≥ OTP_MAX_ATTEMPTS,
    the code is invalidated; user must request a new one
  - `no_pending_activation`  — no outstanding code (already
    active, or user never registered)

Anti-enumeration: when the email doesn't exist we return the
SAME `invalid_code` shape as a wrong-digits attempt so an
attacker can't probe which addresses are registered by watching
for differently-shaped errors.

## Request body

- VerifyOtpIn
  - `email` string, required
  - `code` string, required

## Response `200`

Successful Response

- object

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/omicos/apis/omicos-server.md) · [All operations](https://skmtc.dev/omicos/apis/omicos-server/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/omicos/omicos-server/revisions/a00b94573ffe/schema)
