> ## Documentation Index
> Fetch the complete documentation index at: https://developer.sanas.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API

> HTTP endpoints for account management, device registration, language listing, and Twilio video integration

The REST API service provides HTTP endpoints for account management, device registration, language listing, and Twilio video integration for the Sanas Translate platform.

## Base URL

```
https://api.sanaslt.com/v2
```

## Authentication

All `/v2/*` endpoints require authentication via one of:

| Method     | Header          | Value                |
| ---------- | --------------- | -------------------- |
| JWT Bearer | `Authorization` | `Bearer <jwt_token>` |
| API Key    | `x-api-key`     | `<api_key>`          |

JWT tokens are issued by Supabase and validated using HS256 (shared secret) or ES256 (JWKS). The `aud` claim must be `authenticated`.

On authentication failure, the server returns HTTP 401:

```json theme={null}
{
  "success": false,
  "error": {
    "code": 1002,
    "message": "Unauthorized"
  }
}
```

## Response Format

All v2 endpoints return JSON in a standard envelope.

**Success (HTTP 200):**

```json theme={null}
{
  "success": true,
  "data": { ... }
}
```

**Error:**

```json theme={null}
{
  "success": false,
  "error": {
    "code": 1100,
    "message": "Bad request",
    "data": null
  }
}
```

The HTTP status code matches the error type (400, 401, 404, 500, etc.).

***

## Common Headers

Optional headers that some endpoints use for localization:

| Header       | Default | Description                                             |
| ------------ | ------- | ------------------------------------------------------- |
| `x-lang`     | `en-US` | Locale for localized responses (e.g., `es-ES`, `fr-FR`) |
| `x-version`  | (none)  | Client app version                                      |
| `x-platform` | (none)  | Client platform (`ios`, `android`, `web`)               |

***

## Endpoints

### Health Check

```
GET /health
```

No authentication required. Returns service health status.

**Response:**

```json theme={null}
{
  "status": "healthy",
  "service": "api"
}
```

***

### Error Codes

```
GET /v2/errors
```

Returns the complete error code catalog for client-side error handling.

**Response:**

```json theme={null}
{
  "success": true,
  "data": [
    {
      "name": "NO_TOKEN_PROVIDED",
      "code": 1000,
      "message": "No token provided",
      "http_status": 401
    },
    ...
  ]
}
```

**Error code ranges:**

| Range     | Category                  |
| --------- | ------------------------- |
| 1000-1099 | Authentication errors     |
| 1100-1199 | Request validation errors |
| 1200-1299 | Language errors           |
| 1300-1399 | Resource errors           |
| 1400-1499 | Session errors            |
| 1500-1599 | Rate limiting             |
| 1900-1999 | Server errors             |
| 2000-2099 | Device management errors  |
| 2100-2199 | Twilio errors             |
| 2200-2299 | Account management errors |
| 2400-2499 | Languages mobile errors   |

***

### Languages

```
GET  /v2/languages/list
POST /v2/languages/list
```

Returns the available language list with names localized to the `x-lang` header value. Supports both GET and POST.

**Request headers:**

| Header   | Required | Description                                              |
| -------- | -------- | -------------------------------------------------------- |
| `x-lang` | No       | Locale for language name localization (default: `en-US`) |

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "languages": [
      {
        "code": "en-US",
        "name": "English",
        "native_name": "English"
      },
      {
        "code": "es-ES",
        "name": "Spanish",
        "native_name": "Espanol"
      }
    ]
  }
}
```

**Cache headers:**

* `Cache-Control: public, max-age=86400, stale-while-revalidate=3600`
* `Vary: x-lang, Accept-Encoding`

CloudFront caches one entry per `x-lang` value. First request per locale hits origin; subsequent requests are served from edge cache.

***

### Languages (Mobile)

```
GET  /v2/languages-mobile/list
POST /v2/languages-mobile/list
```

Returns the language list enriched with mobile-specific fields (`listening_text`, `ready_text`).

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "languages": [
      {
        "code": "en-US",
        "name": "English",
        "native_name": "English",
        "listening_text": "Listening...",
        "ready_text": "Ready to translate"
      }
    ]
  }
}
```

Same cache headers as the standard languages endpoint.

***

### Device Registration

```
POST /v2/device/register
Content-Type: application/json
```

Registers or updates a mobile device for push notifications.

**Request body:**

```json theme={null}
{
  "device_name": "iPhone 15",
  "device_platform": "ios",
  "push_token": "abc123..."
}
```

| Field             | Type   | Values           | Description                |
| ----------------- | ------ | ---------------- | -------------------------- |
| `device_name`     | string |                  | Human-readable device name |
| `device_platform` | string | `ios`, `android` | Device platform            |
| `push_token`      | string |                  | Push notification token    |

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device-uuid",
    "device_platform": "ios",
    "device_name": "iPhone 15",
    "is_active": true
  }
}
```

***

### Device Deactivation

```
POST /v2/device/deactivate
Content-Type: application/json
```

Deactivates a registered mobile device.

**Request body:**

```json theme={null}
{
  "push_token": "abc123..."
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "id": "device-uuid",
    "is_active": false
  }
}
```

***

### Twilio Video Token

```
POST /v2/twilio/token/create
Content-Type: application/json
```

Creates a Twilio access token for joining a video room. Verifies the room exists and is in-progress before issuing the token.

**Request body:**

```json theme={null}
{
  "room_name": "1234567890"
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "token": "<twilio_jwt_token>"
  }
}
```

**Errors:**

* 404 (code 2102): Room not found or not in-progress
* 500 (code 2100): Token creation failure

***

### Twilio Video Room

```
POST /v2/twilio/room/create
```

Creates a new Twilio video room. No request body required.

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "room_name": "1234567890",
    "status": "in-progress",
    "max_participant_duration": 3600
  }
}
```

Room properties:

* Type: group
* Max participants: 2
* Max participant duration: 3600 seconds
* Unused room timeout: 1 minute

***

### Account: Opt In

```
POST /v2/account/opt-in
```

Opts the authenticated user in to data sharing. No request body required.

**Response:**

```json theme={null}
{
  "success": true,
  "data": {}
}
```

***

### Account: Opt Out

```
POST /v2/account/opt-out
```

Opts the authenticated user out of data sharing. No request body required.

**Response:**

```json theme={null}
{
  "success": true,
  "data": {}
}
```

***

### Account: Check Opted Out

```
POST /v2/account/check-opted-out
```

Returns the user's current data sharing opt-out status. No request body required.

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "opted_out": false
  }
}
```

***

### Account: Query

```
POST /v2/account/query
```

Returns the authenticated user's account details. No request body required.

**Response:**

```json theme={null}
{
  "success": true,
  "data": {
    "id": "user-uuid",
    "opted_out": false,
    "privacy_agreed": true,
    "onboard_finished": true,
    "my_lang": "en-US",
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-06-01T00:00:00Z"
  }
}
```

***

### Account: Update Privacy Agreed

```
POST /v2/account/privacy-agreed/update
Content-Type: application/json
```

Updates the authenticated user's privacy agreement status.

**Request body:**

```json theme={null}
{
  "privacy_agreed": true
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "data": {}
}
```

***

### Account: Update Onboarding

```
POST /v2/account/onboard/update
Content-Type: application/json
```

Marks onboarding as finished and sets the user's preferred language.

**Request body:**

```json theme={null}
{
  "my_lang": "es-ES"
}
```

**Response:**

```json theme={null}
{
  "success": true,
  "data": {}
}
```

***

### Account: Delete

```
POST /v2/account/delete
```

Permanently deletes the authenticated user's account and associated data. This includes:

1. Supabase auth user deletion
2. PostHog person cleanup (best-effort)
3. S3 file cleanup (best-effort)

Cleanup failures for PostHog and S3 are logged but do not cause the request to fail.

**Response:**

```json theme={null}
{
  "success": true,
  "data": {}
}
```

**Errors:**

* 404 (code 2204): User not found in Supabase auth
* 500 (code 2203): Deletion failure

***

## Service Configuration

The API service is configured via environment variables. See `services/api/AGENTS.md` for the complete list.

Key variables:

* `SUPABASE_URL`, `SUPABASE_JWT_SECRET`, `SUPABASE_SERVICE_ROLE_KEY` for Supabase integration
* `TWILIO_ACCOUNT_SID`, `TWILIO_API_KEY`, `TWILIO_API_SECRET` for Twilio video
* `GATEWAY_API_KEYS` for API key authentication
* `LANGUAGES_CONFIG_PATH` for language list configuration
