Skip to main content

Documentation Index

Fetch the complete documentation index at: https://archie.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

Archie Auth exposes its full surface as REST endpoints on the platform gateway. Use them when you’d rather call HTTP directly than go through GraphQL — anywhere a curl or a thin HTTP client is the right tool. For the equivalent GraphQL operations, see the GraphQL API reference.

Required headers

HeaderRequiredDefaultDescription
X-Project-IdYesYour project identifier.
environmentNomasterTarget environment name.
Content-TypeYesapplication/json.
AuthorizationProtected endpoints onlyBearer <accessToken>.
Base URL: https://your-gateway.example.com

Public endpoints

These don’t require authentication — they’re the way unauthenticated visitors enter the system.

POST /auth/signup

Register a new user account. Request:
{
  "email": "user@example.com",
  "password": "SecureP@ss1",
  "firstName": "John",
  "lastName": "Doe",
  "roleId": "optional-role-id"
}
Responses:
StatusBodyWhen
201{ "userId": "uuid", "message": "Verification email sent" }Created.
400{ "error": "VALIDATION_ERROR", "violations": [...] }Invalid input or weak password.
409{ "error": "AUTH_EMAIL_EXISTS" }Email already registered.
404{ "error": "AUTH_NOT_CONFIGURED" }Auth not enabled for this project + environment.
429{ "error": "RATE_LIMIT_EXCEEDED" }Too many signups (10/min per IP).
If email verification is disabled, the user is auto-verified and can log in immediately.

POST /auth/login

Authenticate and receive an access/refresh token pair. Request:
{
  "email": "user@example.com",
  "password": "SecureP@ss1"
}
Successful response (200):
{
  "accessToken": "eyJhbGciOiJSUzI1NiIs...",
  "refreshToken": "base64-encoded-token...",
  "user": {
    "id": "a1b2c3d4-e5f6-...",
    "email": "user@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "roles": ["Member"]
  }
}
Error responses:
StatusBodyWhen
401{ "error": "AUTH_INVALID_CREDENTIALS" }Wrong email or password.
403{ "error": "AUTH_EMAIL_NOT_VERIFIED" }Email not yet confirmed.
423{ "error": "AUTH_ACCOUNT_LOCKED", "lockedUntil": "..." }Locked from failed attempts.
429{ "error": "RATE_LIMIT_EXCEEDED" }Too many logins (20/min per IP).
When JWE encryption is enabled, the accessToken is a 5-part JWE string instead of a 3-part JWS. Both formats are accepted on inbound requests.

POST /auth/confirm-signup

Confirm an email with the 6-digit code. Request:
{
  "email": "user@example.com",
  "code": "123456"
}
Responses:
StatusBodyWhen
200{ "accessToken": "...", "refreshToken": "...", "user": {...} }Confirmed and logged in.
400{ "error": "AUTH_INVALID_CODE" }Code wrong, expired, or attempt limit hit.
Codes expire after 1 hour. Up to 5 attempts are allowed before the code is invalidated.

POST /auth/recover-password

Request a password recovery email. Always returns 200, regardless of whether the email exists, to prevent enumeration. Request:
{
  "email": "user@example.com"
}
Response (always 200):
{
  "message": "If account exists, recovery email sent"
}
Rate-limited to 5 / minute per email.

POST /auth/reset-password

Reset a password using the recovery code. Request:
{
  "email": "user@example.com",
  "newPassword": "NewSecureP@ss2",
  "code": "654321"
}
Responses:
StatusBodyWhen
200{ "message": "Password reset successfully" }Updated.
400{ "error": "AUTH_INVALID_CODE" }Code wrong or expired.
A successful reset clears any active account lockout.

POST /auth/refresh-token

Exchange a refresh token for a new access/refresh pair. Request:
{
  "refreshToken": "base64-encoded-token..."
}
Responses:
StatusBodyWhen
200{ "accessToken": "...", "refreshToken": "..." }New token pair.
401{ "error": "AUTH_TOKEN_INVALID" }Invalid or already-used refresh token.
Refresh tokens rotate on every use. The previous refresh token is invalidated; store the new one from the response. Reusing an old refresh token returns AUTH_TOKEN_INVALID and triggers a session-wide invalidation as a token-theft signal.

GET /auth/.well-known/jwks.json

Public JWKS endpoint for external services validating Archie-issued tokens. No authentication required. Response (200):
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "abc12345",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    }
  ]
}
When JWE encryption is enabled, two keys are returned — one for signing and one for encryption:
{
  "keys": [
    {
      "kty": "RSA", "kid": "abc12345", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB"
    },
    {
      "kty": "RSA", "kid": "enc-def67890", "use": "enc", "alg": "RSA-OAEP-256", "n": "...", "e": "AQAB"
    }
  ]
}
The response is cached in-memory for 5 minutes. External services should refresh on kid mismatch.

Protected endpoints

Require Authorization: Bearer <accessToken>.

POST /auth/logout

Revoke the current access token and invalidate the associated refresh token.
curl -X POST https://your-gateway.example.com/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "X-Project-Id: your-project-id" \
  -H "environment: master"
Responses:
StatusBodyWhen
200{ "message": "Logged out successfully" }Token revoked.
401{ "error": "AUTH_TOKEN_INVALID" }Missing or invalid token.
Revoked tokens are tracked in a distributed blacklist until their natural expiry, so re-presenting the access token after logout fails with 401.

Error codes reference

CodeHTTPMeaning
AUTH_EMAIL_EXISTS409Email already registered.
AUTH_INVALID_CREDENTIALS401Wrong email or password.
AUTH_EMAIL_NOT_VERIFIED403Email not yet confirmed.
AUTH_ACCOUNT_LOCKED423Too many failed attempts; account temporarily locked.
AUTH_INVALID_CODE400Verification or recovery code wrong, expired, or out of attempts.
AUTH_TOKEN_EXPIRED401Access token has expired.
AUTH_TOKEN_INVALID401Token malformed, revoked, or tampered.
AUTH_NOT_CONFIGURED404Auth not enabled for this project + environment.
RATE_LIMIT_EXCEEDED429Too many requests; honor Retry-After.
VALIDATION_ERROR400Request body validation failed (see violations).

Rate limits

EndpointLimitScope
POST /auth/signup10 / minutePer IP
POST /auth/login20 / minutePer IP
POST /auth/recover-password5 / minutePer email
429 responses include a Retry-After header indicating seconds to wait.

FAQ

To prevent email enumeration. If the response distinguished “exists” from “doesn’t exist”, an attacker could probe a list of emails and learn which are registered. Returning 200 either way removes that signal.
Fetch the JWKS from /auth/.well-known/jwks.json and validate signatures locally. Cache the JWKS on your edge service; refresh on kid mismatch (which signals key rotation). Don’t call Archie on every request to validate.
Most likely a revocation. Archie checks a distributed token blacklist on every request, so logged-out and force-logged-out tokens fail even if the signature is valid. The local-only validation can’t see the blacklist.
Surface a clear “account temporarily locked” message and either show the countdown from lockedUntil or offer a password reset link — a successful reset clears the lockout.
Put a Custom API in front of /auth/login with a tighter rate-limit policy. The auth endpoint defaults are platform-wide; per-route Custom API config lets you go stricter.