# SarangAI Authentication

This document describes how bots, CLI agents, and LLM-driven tools authenticate
against SarangAI (https://sarangai.id). There are two supported flows:

1. **API key (Bearer token)** — for direct gateway calls.
2. **Device code flow (`SA-XXXXXXXX`)** — for the official CLI (`sarangai-cli`)
   to obtain an API key without manual copy-paste.

- Gateway base URL: `https://sarangai.id/api/gateway/v1`
- CLI repository: https://github.com/sarangpenyamun/sarangai-cli

---

## 1. Bearer token (API key)

All gateway endpoints expect an HTTP header:

```
Authorization: Bearer <API_KEY>
```

### Key format

```
sk-sarang-<48 lowercase hex characters>
```

Example: `sk-sarang-9f2c1a7b4e8d3f60a1b2c3d4e5f60718293a4b5c6d7e8f90`

- Keys are hashed (SHA-256) server-side; only the prefix is ever shown again.
- Each key is scoped to one account and has its own rate-limit quota
  (10 requests / 10 seconds).
- Create and manage keys in the dashboard: https://sarangai.id/user/api-keys

### Example request

```bash
curl https://sarangai.id/api/gateway/v1/chat/completions \
  -H "Authorization: Bearer sk-sarang-..." \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-4o", "messages": [{"role": "user", "content": "Hello SarangAI!"}]}'
```

### Check a key works

```bash
curl https://sarangai.id/api/gateway/v1/balance \
  -H "Authorization: Bearer sk-sarang-..."
```

Returns `balance`, `email`, `tier`, `accountId` (dashboard format `SA-XXXXXXXX`),
and `currency: "CREDIT"`.

### Error responses

| Status | Meaning |
| ------ | ------- |
| `401` | Missing, malformed, or inactive key (`{"error": {"message": "Invalid API key", "type": "auth_error"}}`) |
| `402` | Key valid but wallet balance insufficient (`insufficient_balance`) |
| `429` | Rate limit exceeded; retry after 10 seconds (`Retry-After: 10`) |

---

## 2. Device code flow (CLI / bots)

Used by `sarang login` in the official CLI. The user approves the session in a
browser; the CLI receives a fresh API key. The session code format is
`SA-XXXXXXXX` — the literal prefix `SA-` followed by 8 characters (the dashboard
account ID uses the same display format).

### Step 1 — CLI generates a session code

The CLI generates a random session code, e.g. `SA-7QK2M9XZ`, prints it, and
starts polling.

### Step 2 — CLI polls the poll endpoint

```
GET https://sarangai.id/api/auth/cli/poll?code=SA-7QK2M9XZ
```

Responses while waiting:

- `200 {"status": "PENDING"}` — not yet approved, keep polling.
- `200 {"apiKey": "sk-sarang-..."}` — approved; the raw key is returned
  **exactly once** and the server session is deleted immediately afterwards.
- `404 {"error": "Session not found"}` — unknown or already-consumed code.

### Step 3 — User approves in the browser

The CLI prints:

```
https://sarangai.id/auth/cli?code=SA-7QK2M9XZ
```

The user opens the URL, logs into their sarangai.id account, and clicks
**Izinkan Akses CLI** (Allow CLI Access). This triggers:

```
POST https://sarangai.id/api/auth/cli/approve
Content-Type: application/json
Cookie: <sarangai.id session cookie>

{"code": "SA-7QK2M9XZ"}
```

Approving requires an authenticated browser session (HTTP 401 otherwise).
The server mints a dedicated API key named **SarangAI CLI Key** and marks the
device session `APPROVED`.

### Step 4 — CLI stores the key

The next poll returns the key once:

```json
{"apiKey": "sk-sarang-9f2c1a7b..."}
```

The CLI persists it locally and uses it for all subsequent gateway calls:

```
Authorization: Bearer sk-sarang-...
```

### Sequence summary

```
CLI                                 Browser (logged-in user)          Server
 |  code = SA-7QK2M9XZ                 |                               |
 |  GET /api/auth/cli/poll?code=...    |                               |
 |------------------------------------>------------------------------>|
 |  {"status": "PENDING"}              |                               |
 |<------------------------------------<------------------------------|
 |                                     |  open /auth/cli?code=...      |
 |                                     |  POST /api/auth/cli/approve   |
 |                                     |------------------------------>|
 |                                     |  {"success": true}            |
 |                                     |<------------------------------|
 |  GET /api/auth/cli/poll?code=...    |                               |
 |------------------------------------>------------------------------>|
 |  {"apiKey": "sk-sarang-..."}  (once, session deleted)               |
 |<------------------------------------<------------------------------|
 |  Authorization: Bearer sk-sarang-... on /api/gateway/v1/*           |
```

---

## 3. Security notes for bot implementers

- Never log or persist the raw `Authorization` header value in plaintext.
- The device-code key is delivered once; if the poll result is lost, start a new
  session with a fresh code.
- Polling intervals shorter than ~2 seconds add no benefit; approval is
  user-driven.
- Do not share keys between machines — create one key per device from the
  dashboard, or run `sarang login` per device.
- Revoke compromised keys immediately at https://sarangai.id/user/api-keys.

## 4. Related resources

- Full API reference: https://sarangai.id/docs
- Full LLM-optimized documentation: https://sarangai.id/llms-full.txt
- Machine-readable endpoint catalog: https://sarangai.id/.well-known/api-catalog.json
- Models & rates: https://sarangai.id/models
