# Aivoxs Public API v1 — Reference for AI code generators

This document is optimized to be pasted into any LLM (ChatGPT, Claude, Gemini, etc.)
so the model can generate a correct and secure integration with the Aivoxs API.

---

## Summary

Aivoxs exposes a REST API for voice AI: TTS, transcription (STT), voice cloning,
voice changer, dubbing, and multi-speaker dialogue. All long-running operations
return an **asynchronous job** that the client must poll until `completed` or
`failed`.

---

## Base URL

```
Production:  https://api.aivoxs.pro/v1
Fallback:    https://aivoxs.pro/api/public/v1
```

Configure in client `.env`:

```
PUBLIC_API_URL=https://api.aivoxs.pro/v1
AIVOXS_API_TOKEN=aiv_live_xxxxxxxx
```

---

## Authentication

All endpoints (except `/health` and `/openapi.json`) require:

```
Authorization: Bearer aiv_live_xxxxxxxx
```

Rules the AI MUST respect:
- The token belongs to a single user account.
- Token creation requires an active **paid plan** + admin-enabled API flag.
- Trial credits are **never** consumed via the API.
- Revoked tokens stop working immediately.
- **Never** put the token in a browser, mobile app, or any public client — always
  go through a backend.

---

## Rate limits

- **60 requests / minute / token**

Response headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining`,
`X-RateLimit-Reset`, `Retry-After` (only on 429).

---

## Errors

Uniform envelope:

```json
{ "error": { "code": "INVALID_TOKEN", "message": "..." } }
```

| HTTP | Code                  | Meaning                          |
|------|-----------------------|----------------------------------|
| 400  | BAD_REQUEST           | Malformed payload                |
| 401  | MISSING_TOKEN         | Missing Authorization header     |
| 401  | INVALID_TOKEN         | Invalid / expired / revoked      |
| 402  | INSUFFICIENT_CREDITS  | No paid credits available        |
| 403  | FORBIDDEN_SCOPE       | Token lacks required scope       |
| 404  | NOT_FOUND             | Endpoint / resource missing      |
| 429  | RATE_LIMITED          | Per-minute limit exceeded        |
| 500  | INTERNAL              | Unexpected server error          |

---

## Endpoints (implemented)

### GET /v1/health — no auth
```json
{ "status": "ok", "version": "v1", "time": "..." }
```

### GET /v1/credits — scope `credits:read`
```json
{ "balance": 120000, "reserved": 0, "available": 120000, "plan": "pro" }
```

### GET /v1/voices?language=pt-BR&limit=20 — scope `voices:read`
```json
{
  "voices": [
    { "id": "voice_xxx", "name": "...", "provider": "...", "language": "pt-BR" }
  ],
  "count": 1
}
```

### POST /v1/text-to-speech — scope `tts:create`
Body (JSON):
```json
{ "text": "Olá", "voice_id": "voice_xxx", "language": "pt-BR" }
```
Response (`202 Accepted`):
```json
{ "job": { "id": "uuid", "type": "tts", "status": "queued" } }
```

### POST /v1/dialogues — scope `dialogue:create`
```json
{ "lines": [ { "voice_id": "a", "text": "Oi" }, { "voice_id": "b", "text": "Olá" } ] }
```

### POST /v1/transcriptions — scope `transcription:create`
`multipart/form-data`: `file=@audio.mp3`, `language=pt-BR`.
**Audio only** in v1 — video is rejected.

### POST /v1/voice-clones — scope `voice_clone:create`
`multipart/form-data`: `audio_file=@sample.wav`, `name=Minha Voz`.

### POST /v1/voice-changer — scope `voice_changer:create`
`multipart/form-data`: `input=@source.mp3`, `voice_id=voice_xxx`.

### POST /v1/dubbing — scope `dubbing:create`
`multipart/form-data`: `input=@audio.mp3`, `target_language=en`.

### GET /v1/jobs/{id} — scope `jobs:read`
```json
{
  "job": {
    "id": "uuid",
    "type": "tts",
    "status": "completed",
    "credits_used": 1234,
    "result": { "audio_url": "https://.../file.mp3" }
  }
}
```
Statuses: `queued`, `processing`, `completed`, `failed`.

---

## Planned (DO NOT generate code as if implemented)

- `Idempotency-Key` header on POST endpoints.
- `GET /v1/files/{file_id}` for temporary signed URLs.
- Video transcription / dubbing.

---

## Integration checklist (for the AI to follow)

1. Read `AIVOXS_API_TOKEN` from environment — never hardcode.
2. Build all requests against `PUBLIC_API_URL`.
3. POST endpoints return `202` with `{ job: { id, status } }`.
4. Poll `GET /v1/jobs/{id}` with backoff (2s → 5s → 10s) until terminal status.
5. On `completed`, read `result.audio_url`.
6. Handle errors: 401 (token), 402 (credits), 403 (scope), 429 (backoff + retry).
7. Don't log tokens or full payloads.
8. Run only in backend; expose a thin wrapper to the frontend.

---

## Ready-to-use prompt

> You are a developer AI. Build a secure integration with the Aivoxs API.
>
> Base URL: `https://api.aivoxs.pro/v1`
> Auth: `Authorization: Bearer AIVOXS_API_TOKEN` (env var, backend only).
>
> Implement:
> 1. `getCredits()` → GET /v1/credits.
> 2. `listVoices(lang)` → GET /v1/voices.
> 3. `createTTS(text, voice_id)` → POST /v1/text-to-speech, returns `job.id`.
> 4. `waitJob(id)` → polls GET /v1/jobs/{id} with backoff 2s/5s/10s until
>    `completed` or `failed`.
> 5. Surface `result.audio_url` to the caller.
>
> Constraints:
> - Never expose the token in frontend code.
> - Handle 401, 402, 403, 429 explicitly.
> - Do not invent endpoints beyond the ones listed above.
> - Do not send video to /v1/transcriptions (audio only in v1).
> - Use only well-typed JSON or multipart bodies as specified.
