Two-factor auth
TOTP enrollment, verification, and one-time recovery codes. The flow:
authenticate normally via /v1/auth/login, then —
if 2FA is enabled — finish with POST /v1/auth/2fa/verify.
| Method | Path | Auth |
|---|---|---|
POST | /v1/auth/2fa/enroll | JWT |
POST | /v1/auth/2fa/enroll/verify | JWT |
POST | /v1/auth/2fa/verify | public (body has user_id) |
POST | /v1/auth/2fa/disable | JWT |
POST | /v1/auth/2fa/recovery/use | public (body has user_id) |
GET | /v1/auth/2fa/recovery | JWT |
POST /v1/auth/2fa/enroll
Generates a TOTP secret + a PNG QR code (base64) the user can scan in
Google Authenticator, 1Password, etc. The secret is stored tentatively
and is not active until enroll/verify succeeds.
curl -X POST https://api.receipts.oligontech.com/v1/auth/2fa/enroll \
-H "Authorization: Bearer $JWT"Response — 200 OK
{
"secret": "JBSWY3DPEHPK3PXP",
"provisioning_uri": "otpauth://totp/Oligon%20Receipts:ana@example.com?secret=...&issuer=Oligon%20Receipts",
"qr_png_base64": "iVBORw0KGgoAAAANSUhEUgAA..."
}409 conflict if 2FA is already enabled — call /disable first.
POST /v1/auth/2fa/enroll/verify
Confirm enrollment by submitting the first 6–8 digit code from the authenticator app. On success: 2FA is activated and ten recovery codes are returned once.
curl https://api.receipts.oligontech.com/v1/auth/2fa/enroll/verify \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"123456"}'Response — 200 OK
{
"enabled": true,
"recovery_codes": [
"ABCD-1234-EFGH",
"..."
]
}| Status | Code | Cause |
|---|---|---|
| 400 | validation_error | /enroll not called yet. |
| 401 | authentication_failed | Wrong TOTP code (±1 step window). |
POST /v1/auth/2fa/verify
Second-factor check during login. The caller already passed
email+password; they now post their user_id and the current TOTP
code.
curl https://api.receipts.oligontech.com/v1/auth/2fa/verify \
-H "Content-Type: application/json" \
-d '{"user_id":"01HQX...","code":"123456"}'{ "ok": true }401 authentication_failed if 2FA is not enabled for that user or the
code is wrong.
POST /v1/auth/2fa/disable
Turn off 2FA. Requires the current TOTP code (recovery codes do not
work here — use /recovery/use to log in, then disable).
curl https://api.receipts.oligontech.com/v1/auth/2fa/disable \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"123456"}'{ "ok": true }Wipes the TOTP secret and deletes all recovery codes for the user.
POST /v1/auth/2fa/recovery/use
Burn a recovery code instead of a TOTP code (lost phone scenario). Each code works exactly once.
curl https://api.receipts.oligontech.com/v1/auth/2fa/recovery/use \
-H "Content-Type: application/json" \
-d '{"user_id":"01HQX...","code":"ABCD-1234-EFGH"}'{ "ok": true }401 authentication_failed if the code is unknown or already used.
GET /v1/auth/2fa/recovery
How many recovery codes you have left.
curl https://api.receipts.oligontech.com/v1/auth/2fa/recovery \
-H "Authorization: Bearer $JWT"{ "total": 10, "unused": 7 }