> ## Documentation Index
> Fetch the complete documentation index at: https://symphony-docs.fcamara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference

> All endpoints available to integrators using a Symphony API key, with parameters, examples, and responses.

## What it is

This is the reference for **all endpoints available to anyone integrating with Symphony using an API key**. Each endpoint lists the method, path, parameters, a sample call, and the response format.

If it's your first time, start with [Connect via API](/en/desenvolvedores/api/conectar-api). To understand **how to combine** these endpoints in a real project, see [Building projects with the API](/en/desenvolvedores/api/projetos-com-a-api).

## 1. Before you start

### Base URL

```
https://symphony.fcamara.com
```

For testing, see [Environments and support](/en/desenvolvedores/api/ambientes-e-suporte).

### Headers

All endpoints on this page, except those in section **10. Service status**, require:

| Header | Value | When |
| - | - | - |
| `Authorization` | `Bearer sk-...` | Always |
| `X-Enterprise-Id` | Your company ID | Always |
| `Content-Type` | `application/json` | On requests with a JSON body |

Don't send cookies or a CSRF token. They aren't needed with an API key.

### What your key can do

The key has **exactly the same access as your account**: the same models, agents, knowledge bases, flows, permissions, and usage limit. If you can't do something in the interface, you can't do it through the API either.

Some actions depend on permissions granted by the company administrator (for example, creating knowledge bases). Check yours with `GET /api/v1/users/permissions`.

### Conventions

* **Dates** are integers in *epoch* time (seconds since 01/01/1970, UTC), unless stated otherwise.
* **IDs** are strings. Copy them exactly as returned.
* **Cursor pagination:** list endpoints return `{ "items": [...], "next_cursor": "..." }`. To fetch the next page, repeat the call with `?cursor=<next_cursor>`. When `next_cursor` is `null`, you're done. `limit` accepts 1 to 200.
* **Errors** follow a single format, described in [Errors and limits](/en/desenvolvedores/api/erros-e-limites).

## 2. Account and API key

### `GET /api/v1/auths/api_key`

Returns your current API key.

```json theme={null}
{ "api_key": "sk-1a2b3c..." }
```

Returns `404` if you haven't generated a key yet.

### `POST /api/v1/auths/api_key`

Generates a new key. **The previous key stops working immediately.**

```json theme={null}
{ "api_key": "sk-9z8y7x..." }
```

Returns `403` if key generation is disabled in the environment.

### `DELETE /api/v1/auths/api_key`

Revokes your key. Returns `true`. After that, no call with it works.

<Note>
  Generating and revoking are usually done in the interface (**Settings → Account → API keys**). These endpoints exist for anyone who needs to automate rotation.
</Note>

### `GET /api/v1/auths/`

Returns the data of the account that owns the key.

```json theme={null}
{
  "id": "b7c1...",
  "email": "ana.souza@company.com",
  "name": "Ana Souza",
  "role": "user",
  "enterprise_id": "fcamara-0000-0000-0000-000000000001",
  "permissions": { "workspace": { ... }, "chat": { ... }, "features": { ... } }
}
```

<Note>
  The response also includes the `token`, `token_type`, and `expires_at` fields. They're for the browser session and **aren't needed** when using an API key.
</Note>

### `GET /api/v1/users/permissions`

Returns what your account can do.

```json theme={null}
{
  "workspace": {
    "models": false,
    "knowledge": true,
    "prompts": true,
    "tools": false,
    "workflows": true
  },
  "chat": {
    "file_upload": true,
    "stt": true,
    "tts": true
  },
  "features": {
    "web_search": true,
    "image_generation": false,
    "code_interpreter": true
  }
}
```

| Group | What it controls |
| - | - |
| `workspace` | Whether you can **create** agents (`models`), knowledge bases (`knowledge`), prompts, tools, and flows (`workflows`) |
| `chat` | Conversation features: file upload (`file_upload`), transcription (`stt`), speech (`tts`) |
| `features` | Features enabled by the chat `features` field: web search, image generation, and code interpreter |

### `GET /api/v1/consumption/me`

Returns your usage for the month and the status of your limit.

```json theme={null}
{
  "userId": "b7c1...",
  "period": "monthly",
  "tokensUsed": 182340,
  "cost": 12.47,
  "executions": 318,
  "costLimit": 50.0,
  "defaultCostLimit": 50.0,
  "isConsumptionBlocked": false,
  "byModel": [ ... ],
  "byAgent": [ ... ],
  "timeseries": [ ... ],
  "lastConsumptionAt": 1760533200000,
  "peakHour": 15,
  "status": "ok"
}
```

| Field | Meaning |
| - | - |
| `cost` / `costLimit` | Spending this month and your account's monthly cap |
| `status` | `ok` (within limit), `warning` (near limit), `reached` (limit reached), or `blocked` (access blocked by the administrator) |
| `byModel`, `byAgent` | Usage broken down by model and by agent |
| `timeseries` | Usage per day |
| `lastConsumptionAt` | Time of last use, in **milliseconds** |

With `status` at `reached` or `blocked`, chat calls return `402`. Use this endpoint before large batches.

## 3. Models and agents

### `GET /api/models`

Lists the models **and agents** your account can use in the company given in `X-Enterprise-Id`.

```bash theme={null}
curl https://symphony.fcamara.com/api/models \
  -H "Authorization: Bearer sk-..." \
  -H "X-Enterprise-Id: YOUR_COMPANY_ID"
```

```json theme={null}
{
  "data": [
    { "id": "azure.gpt-5-chat", "name": "Azure gpt-5-chat", "owned_by": "openai" },
    {
      "id": "fc-code-assistant",
      "name": "Code Vader",
      "info": { "base_model_id": "azure.gpt-5-chat" }
    }
  ]
}
```

* The `id` is the value that goes in the chat `model` field.
* Items with `info.base_model_id` are **agents**: they come with prompt, bases, and tools already configured on the platform.
* The list is already filtered to what you can use. Disabled models or ones not shared with you don't appear.

## 4. Chat

### `POST /api/chat/completions`

Sends messages to a model or agent and receives the response. **Compatible with OpenAI's chat completions API.**

**Required fields**

| Field | Type | Description |
| - | - | - |
| `model` | string | `id` from `GET /api/models` |
| `messages` | array | List of `{ "role": "...", "content": "..." }`, with `role` set to `system`, `user`, `assistant`, or `tool` |

**Optional fields: generation**

| Field | Type | Description |
| - | - | - |
| `stream` | boolean | `true` returns the response in real time (Server-Sent Events). Default `false` |
| `stream_options` | object | `{ "include_usage": true }` to get the token count when streaming |
| `temperature` | number | Response creativity |
| `top_p` | number | Alternative randomness control |
| `max_tokens` | integer | Maximum response length. Ignored if `0` |
| `stop` | string or array | Sequences that stop generation |
| `response_format` | object | Forces JSON output. See recipe 5.3 in [Building projects with the API](/en/desenvolvedores/api/projetos-com-a-api) |

**Optional fields: tools and context**

| Field | Type | Description |
| - | - | - |
| `tools`, `tool_choice`, `parallel_tool_calls` | — | *Function calling* in the OpenAI pattern. **Your** code runs the function. See recipe 5.5 in [Building projects with the API](/en/desenvolvedores/api/projetos-com-a-api) |
| `files` | array | Attached documents and bases. `[{ "type": "file", "id": "<file id>" }]` or `[{ "type": "collection", "id": "<base id>" }]` |
| `features` | object | `{ "web_search": true, "image_generation": true, "code_interpreter": true }`. Only works if your account has the matching permission |
| `variables` | object | Prompt substitutions, like `{ "{{USER_LANGUAGE}}": "en-US" }` |

**Optional fields: platform history**

| Field | Type | Description |
| - | - | - |
| `chat_id` | string | ID of a conversation created with `POST /api/v1/chats/new`. See below |
| `id` | string | UUID that identifies the response message to be saved |

**Example**

```bash theme={null}
curl -X POST https://symphony.fcamara.com/api/chat/completions \
  -H "Authorization: Bearer sk-..." \
  -H "X-Enterprise-Id: YOUR_COMPANY_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "azure.gpt-5-chat",
    "messages": [
      { "role": "system", "content": "Answer in English, concisely." },
      { "role": "user", "content": "Summarize the risks in this contract." }
    ],
    "files": [{ "type": "file", "id": "3f1c..." }],
    "temperature": 0.3
  }'
```

**Response (`200`)**

```json theme={null}
{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1764696021,
  "model": "azure.gpt-5-chat",
  "choices": [
    {
      "index": 0,
      "finish_reason": "stop",
      "message": { "role": "assistant", "content": "..." }
    }
  ],
  "usage": { "prompt_tokens": 24, "completion_tokens": 61, "total_tokens": 85 }
}
```

**Streaming.** With `"stream": true`, the response arrives as `data: {...}` lines, each with a chunk in `choices[0].delta.content`, ending with `data: [DONE]`. An error can arrive **inside the stream**, after the `200 OK`. See section 6 of [Building projects with the API](/en/desenvolvedores/api/projetos-com-a-api).

**Automatic history.** If you send a `chat_id` and **no** message with `role: "assistant"`, Symphony retrieves that conversation's saved history and puts it before your message. This way you keep a long conversation going by sending only the new question. If your array has any `assistant` message, Symphony assumes you manage the history and injects nothing.

**Errors specific to this endpoint**

| Status | Code | When |
| - | - | - |
| `400` | `INVALID_PARAMETER` | A parameter is outside what the model accepts |
| `400` | — | Image model called without `features.image_generation: true` |
| `402` | `CONSUMPTION_LIMIT_REACHED` / `CONSUMPTION_BLOCKED` | Your usage limit ran out or your access was blocked |
| `404` | `MODEL_UNAVAILABLE` | `model` outside the company catalog or no access |
| `409` | `AGENT_BASE_MODEL_UNAVAILABLE` | The agent exists, but its base model was removed |
| `429` | `detail.error = "quota_exceeded"` | Your company's token quota ran out. The body includes `reset_at`, with the renewal date |
| `429` | `RATE_LIMITED` | Too many requests in a short time, or the AI provider temporarily rate-limited you |

### `POST /api/responses`

Version compatible with OpenAI's **Responses API**, for tools that only speak that format. Accepts `input` (text or list) instead of `messages` and streams in the Responses API format.

<Note>
  **For new integrations, use `POST /api/chat/completions`.** This endpoint exists only for compatibility.
</Note>

## 5. Files

### `POST /api/v1/files/`

Uploads a file. The body is `multipart/form-data`, with the file in the `file` field.

```bash theme={null}
curl -X POST https://symphony.fcamara.com/api/v1/files/ \
  -H "Authorization: Bearer sk-..." \
  -H "X-Enterprise-Id: YOUR_COMPANY_ID" \
  -F "file=@contract.pdf"
```

```json theme={null}
{
  "id": "3f1c...",
  "user_id": "b7c1...",
  "filename": "contract.pdf",
  "data": { "status": "processing" },
  "meta": { "name": "contract.pdf", "content_type": "application/pdf", "size": 284113 },
  "created_at": 1760533200,
  "updated_at": 1760533200
}
```

| Query | Default | Description |
| - | - | - |
| `process` | `true` | Extracts the file's text for use in chat and bases. Use `false` only to store the file without processing |

<Warning>
  **The response arrives before the file is ready.** Reading (text extraction, OCR) continues in the background. Before using the file, poll `GET /api/v1/files/{id}` until `data.status` becomes `ready`. Attaching a file still in `processing` makes the model respond as if the document were empty.
</Warning>

### `GET /api/v1/files/{id}`

Returns the file data, including processing status.

| `data.status` | Meaning |
| - | - |
| `processing` | Still being read. Check again in a few seconds |
| `ready` | Ready to use in chat or in a base |
| `error` | Failed. The reason is in `data.error` |

Large or scanned PDFs can take a few minutes. Poll at intervals (for example, every 3 seconds) with a maximum wait time.

### `GET /api/v1/files/`

Lists your files.

| Query | Default | Description |
| - | - | - |
| `content` | `true` | Use `false` to leave out the extracted text and keep the response lighter |

### `GET /api/v1/files/search`

Searches files by name.

| Query | Required | Description |
| - | - | - |
| `filename` | Yes | Name or wildcard pattern, like `*.pdf` or `contract*` |
| `content` | No | `false` to leave out the extracted text |

### `GET /api/v1/files/{id}/content`

Downloads the original file.

| Query | Default | Description |
| - | - | - |
| `attachment` | `false` | `true` forces download (`Content-Disposition: attachment`) |

### `DELETE /api/v1/files/{id}`

Deletes the file. Returns `{ "message": "File deleted successfully" }`. Only the owner, or someone with write permission, can delete it.

## 6. Knowledge bases

A knowledge base groups several files so the model looks up only the relevant parts for each question. To use a base in chat, send `"files": [{ "type": "collection", "id": "<base id>" }]`, or use an agent that already has the base configured.

**Full flow through the API:**

<Steps>
  <Step title="Create the base">
    `POST /api/v1/knowledge/create`
  </Step>

  <Step title="Upload each file">
    `POST /api/v1/files/` and wait for the `ready` status.
  </Step>

  <Step title="Add the files to the base">
    `POST /api/v1/knowledge/{id}/file/add`
  </Step>

  <Step title="Use it in chat">
    `files: [{ "type": "collection", "id": "..." }]`
  </Step>
</Steps>

### `GET /api/v1/knowledge/list/compact`

Lists the bases you can see, with cursor pagination.

| Query | Default | Description |
| - | - | - |
| `limit` | `50` | Items per page (1 to 200) |
| `cursor` | — | `next_cursor` from the previous page |
| `search` | — | Filters by name or description (partial, case-insensitive) |

```json theme={null}
{
  "items": [
    {
      "id": "kb-7a2f...",
      "name": "HR Policies",
      "description": "Internal manuals and policies",
      "files_count": 12,
      "can_write": true,
      "created_at": 1760533200,
      "updated_at": 1760619600
    }
  ],
  "next_cursor": "eyJ1cGRhdGVkX2F0Ijo..."
}
```

`can_write` indicates whether you can change the base.

### `GET /api/v1/knowledge/count`

Returns the total number of bases you can see: `{ "total": 8 }`.

### `GET /api/v1/knowledge/{id}`

Returns the full base, with the list of files (`files`).

### `POST /api/v1/knowledge/create`

Creates a base. **Requires the `workspace.knowledge` permission.** Without it, returns `401`.

```json theme={null}
{
  "name": "Contracts 2026",
  "description": "Contracts signed in 2026",
  "access_control": {}
}
```

| Field | Required | Description |
| - | - | - |
| `name` | Yes | Base name |
| `description` | Yes | Description (can be `""`) |
| `access_control` | No | Who else can see or edit. `{}` keeps the base **private** (only you). To share: `{ "read": { "group_ids": ["..."], "user_ids": ["..."] }, "write": { "group_ids": [], "user_ids": [] } }` |

Returns the created base, with its `id`.

### `POST /api/v1/knowledge/{id}/update`

Changes name, description, or access. Same body as `create`. Requires write permission on the base.

### `POST /api/v1/knowledge/{id}/file/add`

Adds an already uploaded file (with `ready` status) to the base.

```json theme={null}
{ "file_id": "3f1c..." }
```

Returns the updated base, with the list of files.

### `POST /api/v1/knowledge/{id}/files/batch/add`

Adds several files at once.

```json theme={null}
[{ "file_id": "3f1c..." }, { "file_id": "8d4e..." }]
```

### `POST /api/v1/knowledge/{id}/file/remove`

Removes a file from the base.

```json theme={null}
{ "file_id": "3f1c..." }
```

### `DELETE /api/v1/knowledge/{id}/delete`

Deletes the base. The files still exist in `/api/v1/files/`. Returns `true`.

## 7. Conversations

By default, chat calls **aren't saved**. Use these endpoints when you want your project's conversations to stay in the platform's history, where they can be audited or continued in the interface.

### `POST /api/v1/chats/new`

Creates an empty conversation.

```json theme={null}
{
  "chat": {
    "title": "Ticket #4821",
    "models": ["azure.gpt-5-chat"],
    "messages": []
  }
}
```

Returns the created conversation. Keep the `id` and send it as `chat_id` in `POST /api/chat/completions`.

```json theme={null}
{
  "id": "ca49f9ae-...",
  "user_id": "b7c1...",
  "title": "Ticket #4821",
  "chat": { ... },
  "archived": false,
  "pinned": false,
  "created_at": 1760533200,
  "updated_at": 1760533200
}
```

### `GET /api/v1/chats/list/cursor`

Lists your conversations, from newest to oldest.

| Query | Default | Description |
| - | - | - |
| `limit` | `50` | Items per page (1 to 200) |
| `cursor` | — | `next_cursor` from the previous page |

```json theme={null}
{
  "items": [
    {
      "id": "ca49f9ae-...",
      "title": "Ticket #4821",
      "created_at": 1760533200,
      "updated_at": 1760619600,
      "pinned": false,
      "folder_id": null,
      "tags": []
    }
  ],
  "next_cursor": null
}
```

### `GET /api/v1/chats/search`

Searches conversations by text.

| Query | Required | Description |
| - | - | - |
| `text` | Yes | Search term |
| `page` | No | Page, starting at `1`. Each page has up to 60 items |

Returns `[{ "id", "title", "created_at", "updated_at" }]`.

### `GET /api/v1/chats/{id}`

Returns the full conversation, with all messages in `chat.history.messages`. Only works for your own conversations.

### `DELETE /api/v1/chats/{id}`

Deletes the conversation. Returns `true`.

## 8. Flows (Workflows)

[Flows](/en/guia/fluxos) are sequences of steps built in the Symphony interface (for example: read a document → summarize with an agent → classify). Through the API you **list, run, and track** the flows you have permission to use.

**How a run works:** the run call responds right away with a `run_id`. The flow runs in the background, and you poll the result until it finishes.

| `status` | Meaning |
| - | - |
| `queued` | Queued |
| `running` | Running |
| `completed` | Finished successfully. The result is in `output` |
| `failed` | Failed. The reason is in `error`, and the failed step in `failed_node_id` |
| `cancelled` | Was cancelled |

### `GET /api/v1/workflows/list`

Lists the flows you can use, with cursor pagination.

| Query | Default | Description |
| - | - | - |
| `limit` | `50` | Items per page (1 to 200) |
| `cursor` | — | `next_cursor` from the previous page |

```json theme={null}
{
  "items": [
    {
      "id": "wf-91b3...",
      "name": "Contract summary",
      "description": "Reads the contract and produces a risk summary",
      "is_active": true,
      "created_at": 1760533200,
      "updated_at": 1760619600
    }
  ],
  "next_cursor": null
}
```

### `GET /api/v1/workflows/workflow?id={id}`

Returns the full flow, including its steps (`graph`).

### `POST /api/v1/workflows/workflow/run?id={id}`

Runs the flow. The body is optional and sets the input for the first step:

| Input | Format |
| - | - |
| Text | `{ "input": { "content": "Text to process..." } }` |
| File | `{ "input": { "file_id": "3f1c..." } }`: a file uploaded with `POST /api/v1/files/`, already with `ready` status |

```bash theme={null}
curl -X POST "https://symphony.fcamara.com/api/v1/workflows/workflow/run?id=wf-91b3..." \
  -H "Authorization: Bearer sk-..." \
  -H "X-Enterprise-Id: YOUR_COMPANY_ID" \
  -H "Content-Type: application/json" \
  -d '{ "input": { "file_id": "3f1c..." } }'
```

```json theme={null}
{ "run_id": "run-55c0...", "workflow_id": "wf-91b3...", "status": "queued" }
```

Returns `429` if your company has already started the maximum number of runs allowed in the last minute (currently 30). Wait a few seconds and try again.

### `GET /api/v1/workflows/runs/detail?run_id={run_id}`

Returns the run, with the result of each step. **This is the endpoint you poll until the run finishes.**

```json theme={null}
{
  "id": "run-55c0...",
  "workflow_id": "wf-91b3...",
  "status": "completed",
  "input": { "file_id": "3f1c..." },
  "output": { "content": "Summary: the contract has three risks..." },
  "error": null,
  "failed_node_id": null,
  "started_at": 1760533200,
  "ended_at": 1760533242,
  "steps": [
    {
      "node_id": "node-1",
      "node_type": "agent",
      "status": "completed",
      "output": { "content": "..." },
      "error": null
    }
  ]
}
```

### `GET /api/v1/workflows/workflow/runs?id={id}`

Lists a flow's runs, without step details.

### `POST /api/v1/workflows/runs/cancel?run_id={run_id}`

Requests cancellation of a run in progress. Returns `true`. Only the person who started the run can cancel it.

## 9. Audio

### `POST /api/v1/audio/transcriptions`

Transcribes audio to text. The body is `multipart/form-data`, with the audio in the `file` field.

* **Accepted formats:** MP3 (`audio/mpeg`), WAV (`audio/wav`), OGG (`audio/ogg`), and M4A (`audio/x-m4a`).
* **Size:** audio over 25 MB is compressed automatically. If it's still over the limit, it returns `FILE_TOO_LARGE`.

```bash theme={null}
curl -X POST https://symphony.fcamara.com/api/v1/audio/transcriptions \
  -H "Authorization: Bearer sk-..." \
  -H "X-Enterprise-Id: YOUR_COMPANY_ID" \
  -F "file=@meeting.mp3"
```

```json theme={null}
{ "text": "Good morning everyone, let's get started...", "filename": "9a1e....mp3" }
```

### `POST /api/v1/audio/speech`

Converts text to speech. Returns the audio as MP3.

```bash theme={null}
curl -X POST https://symphony.fcamara.com/api/v1/audio/speech \
  -H "Authorization: Bearer sk-..." \
  -H "X-Enterprise-Id: YOUR_COMPANY_ID" \
  -H "Content-Type: application/json" \
  -d '{ "input": "Hello, this is a test.", "voice": "alloy" }' \
  --output speech.mp3
```

| Field | Description |
| - | - |
| `input` | Text to speak |
| `voice` | One of the voices from `GET /api/v1/audio/voices` |

The voice model is set by your company's configuration. Identical requests are served from cache and don't count toward the limit.

### `GET /api/v1/audio/voices`

Lists the available voices: `{ "voices": [{ "id": "alloy", "name": "alloy" }] }`.

### `GET /api/v1/audio/models`

Lists the available voice models: `{ "models": [...] }`.

<Note>
  **Limit:** transcription and speech each accept up to 30 calls per minute per company. Above that, they return `429`.
</Note>

## 10. Service status

These endpoints **don't require authentication**.

| Endpoint | Response | Use |
| - | - | - |
| `GET /health` | `{ "status": true }` | Check whether the service is up |
| `GET /api/version` | `{ "version": "2.8.0" }` | Find out which Symphony version is running |

## 11. What's not part of the public API

The endpoints below exist, but **aren't supported for integration**. They may change or be removed without notice, or they require a profile that integration accounts don't have:

* **Platform administration** (`/api/v1/admin/...`, management of users, companies, groups, models, and other people's usage): requires an administrator profile and is done through the interface.
* **Password login and SSO** (`/api/v1/auths/signin`, `/signup`, `/api/v1/auth/sso/...`): use the API key.
* **Internal interface routes**: screen settings, suggestions, banners, ratings, automatic title and tag generation, and `GET /api/config`, which doesn't accept an API key.
* **Direct access to AI providers** (`/openai/...`, `/ollama/...`): use `POST /api/chat/completions`.
* **Direct image generation** (`/api/v1/images/...`): generate images through chat, with `features.image_generation: true`.
* **Direct vector ingestion and search** (`/api/v1/retrieval/...`): use knowledge bases and the chat `files` field.
* **Task management** (`/api/tasks/...`): to stop a streaming response, close the connection.

If your use case needs something that isn't on this page, contact the Symphony team. See [Environments and support](/en/desenvolvedores/api/ambientes-e-suporte).

## Related documents

* [Connect via API](/en/desenvolvedores/api/conectar-api)
* [Building projects with the API](/en/desenvolvedores/api/projetos-com-a-api)
* [Errors and limits](/en/desenvolvedores/api/erros-e-limites)
* [Environments and support](/en/desenvolvedores/api/ambientes-e-suporte)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.