Authentication
Email + password, magic link, and invitation flows for the dashboard.
All endpoints below mint or consume JWT session tokens
(Authorization: Bearer <jwt>) and also set oligon_access /
oligon_refresh HttpOnly cookies. For machine-to-machine API key
auth see API keys.
| Method | Path | Auth |
|---|---|---|
POST | /v1/auth/signup | public |
POST | /v1/auth/login | public |
POST | /v1/auth/refresh | refresh token (cookie or body) |
POST | /v1/auth/logout | public |
GET | /v1/auth/me | JWT |
POST | /v1/auth/magic-link | public |
POST | /v1/auth/magic-link/verify | one-shot link token |
POST | /v1/auth/accept-invite | one-shot invite token |
POST | /v1/auth/verify-email/{token} | one-shot link token |
POST /v1/auth/signup
Creates a User, an Org (owner = the new user), a free plan
Subscription, and sends a verify-email link. Returns a session.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | yes | Must not be a disposable domain. |
password | string | yes | 8–128 chars. |
full_name | string | no | ≤255 chars. |
org_name | string | yes | 1–255 chars. Slug derived from it. |
curl https://api.receipts.oligontech.com/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{"email":"ana@example.com","password":"correct-horse","org_name":"Ana Inc"}'Response — 201 Created
{
"access_token": "eyJhbGc...",
"refresh_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 900,
"user_id": "01HQX...",
"org_id": "01HQX..."
}Errors
| Status | Code | Cause |
|---|---|---|
| 400 | validation_error | Disposable email domain. |
| 409 | conflict | Email already registered. |
| 429 | rate_limit_exceeded | Too many signups from this IP in 1 h. |
POST /v1/auth/login
curl https://api.receipts.oligontech.com/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"ana@example.com","password":"correct-horse"}'Returns the same TokenResponse as signup with status 200.
| Status | Code | Cause |
|---|---|---|
| 401 | authentication_failed | Bad credentials or disabled account. |
If the user has 2FA enabled, complete login by posting the code to
/v1/auth/2fa/verify.
POST /v1/auth/refresh
Reads the refresh token from either the oligon_refresh cookie or a
JSON body { "refresh_token": "..." }, then issues a new access +
refresh pair (refresh is rotated).
curl https://api.receipts.oligontech.com/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token":"eyJhbGc..."}'Returns TokenResponse with status 200. 401 authentication_failed
if the token is missing, malformed, expired, or of the wrong type.
POST /v1/auth/logout
Clears the oligon_access and oligon_refresh cookies. Public — does
not require auth, does not invalidate the JWT on the server (JWTs are
stateless).
{ "ok": true }GET /v1/auth/me
Returns the active user + org for the portal frontend.
curl https://api.receipts.oligontech.com/v1/auth/me \
-H "Authorization: Bearer $JWT"{
"user": {
"id": "01HQX...",
"email": "ana@example.com",
"name": null,
"created_at": "2026-06-01T00:00:00+00:00"
},
"org": {
"id": "01HQX...",
"name": "Ana Inc",
"slug": "ana-inc",
"plan": "free",
"billing_email": "ana@example.com"
},
"role": "owner"
}org and role are null if the user has no membership yet.
POST /v1/auth/magic-link
Send a one-shot sign-in link to the email. Always returns 202 with
{"ok": true} whether or not the address exists (no enumeration).
curl https://api.receipts.oligontech.com/v1/auth/magic-link \
-H "Content-Type: application/json" \
-d '{"email":"ana@example.com"}'POST /v1/auth/magic-link/verify
Exchange the token from the email link for a session.
curl https://api.receipts.oligontech.com/v1/auth/magic-link/verify \
-H "Content-Type: application/json" \
-d '{"token":"<from email>"}'Returns TokenResponse. 400 validation_error if the token is
unknown, expired, or already consumed (one-shot).
POST /v1/auth/accept-invite
Same body as magic-link verify ({ "token": "..." }). Looks up the
Invitation, creates the user if they don't exist yet, adds a
Membership with the role baked into the invite, and returns a session
scoped to that org.
| Status | Code | Cause |
|---|---|---|
| 400 | validation_error | Invite unknown, expired, revoked, or already accepted. |
POST /v1/auth/verify-email/{token}
Confirms a verify-email link. One-shot: the token is deleted on the
first redemption. Subsequent requests with the same (already-deleted)
token return 400 validation_error.
curl -X POST https://api.receipts.oligontech.com/v1/auth/verify-email/<token>{ "ok": true, "email": "ana@example.com", "verified": true }