Skip to main content

Authentication

The Faces API accepts two authentication methods: JWT tokens (for server-to-server use right after login) and API keys (for long-lived application access). Both are passed as a Bearer token in the Authorization header.
Authorization: Bearer <token>

JWT tokens

JWTs are issued by the /auth/login endpoint after email/password authentication. They expire after a short window and are suitable for immediate use in client-side flows or testing.

Register

curl -X POST https://api.faces.sh/auth/register-email \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Alice",
    "email": "alice@example.com",
    "password": "your-secure-password",
    "username": "alice"
  }'

Login

curl -X POST https://api.faces.sh/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "password": "your-secure-password"
  }'
Response:
{
  "success": true,
  "data": {
    "token": "eyJ...",
    "user_id": "311d4676-effb-4b20-..."
  }
}

Refresh

curl -X POST https://api.faces.sh/auth/refresh \
  -H "Authorization: Bearer YOUR_JWT"
Returns a fresh JWT without requiring re-login.

API keys

API keys are the recommended method for production applications. They support optional budget caps, expiration, and restrictions on which faces and models can be used.

Create an API key

curl -X POST https://api.faces.sh/v1/auth/api-keys \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production",
    "budget_usd": 50.00,
    "allowed_face_ids": ["alice", "bob"],
    "allowed_llm_models": ["gpt-4o-mini"]
  }'
FieldTypeDescription
namestringHuman-readable label
budget_usdfloat (optional)Hard spend cap in USD. Requests fail with 402 once exhausted. Null = unlimited.
expires_in_daysint (optional)Number of days until the key expires. Null = never expires.
scopesarray (optional)Permission scopes. Default: ["v1:*"] (full access).
allowed_face_idsarray (optional)Restrict the key to specific face aliases. Null = all owned faces.
allowed_llm_modelsarray (optional)Restrict the key to specific LLM models. Null = all models.
The response includes the full API key once — it cannot be retrieved again:
{
  "id": "a1b2c3d4-...",
  "key": "sk-faces-abc123...",
  "key_prefix": "sk-faces-abc12345",
  "name": "production"
}

List API keys

curl https://api.faces.sh/v1/auth/api-keys \
  -H "Authorization: Bearer YOUR_KEY"

Update an API key

curl -X PATCH https://api.faces.sh/v1/auth/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "renamed-key" }'

Revoke an API key

curl -X DELETE https://api.faces.sh/v1/auth/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_KEY"

Budget caps

When a budget cap is set on an API key, every chat request checks the remaining budget before proceeding. If the balance is zero or the key is frozen, the API returns:
HTTP 402 Payment Required
{
  "detail": "Insufficient credits"
}
Top up credits via the billing API or the dashboard.

Face and model restrictions

The allowed_face_ids field restricts which faces can be used with a key. Pass face aliases (not UUIDs):
{ "allowed_face_ids": ["alice", "bob"] }
The allowed_llm_models field restricts which LLM models can be used:
{ "allowed_llm_models": ["gpt-4o-mini", "claude-sonnet-4-20250514"] }
Requests using a face or model not in the allowed list are rejected with 403 Forbidden. Null or omitted fields allow all faces/models — appropriate for unrestricted keys.

Error codes

CodeMeaning
401Missing or invalid token
402Insufficient credits
403Face/model not allowed, or permission denied