> ## 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.

# Connect via API

> Integrate external systems and scripts with Symphony models via the chat completions endpoint.

## What it is

Allows external systems and scripts to communicate with **Symphony** models programmatically, via the **chat completions** endpoint. Use this integration for automations, backends, tests (Postman), or integrations with other tools.

## Prerequisites

* Active account in **AI Symphony**.
* An **API key** and/or **JWT token**.
* The **company ID** (`X-Enterprise-Id`).

## How to get your API key

<Steps>
  <Step title="Open AI Symphony">
    Go to [symphony.fcamara.com.br](https://symphony.fcamara.com.br/).
  </Step>

  <Step title="Click your username">
    In the bottom left corner.
  </Step>

  <Step title="Go to Settings" />

  <Step title="Access the Account (or Connections) tab">
    Under **API Keys**, depending on the version.
  </Step>

  <Step title="Create and copy the key">
    Click **API Key** and **copy** the generated key.
  </Step>
</Steps>

<Tip>Paste the **complete** key, without extra spaces or unnecessary quotes.</Tip>

## API endpoint

* **Endpoint:** `POST https://symphony.fcamara.com/api/chat/completions`
* **Authentication:** `Authorization: Bearer <token>` (token obtained from Symphony).

### Required headers

```http theme={null}
POST /api/chat/completions HTTP/1.1
Host: symphony.fcamara.com
Content-Type: application/json
Authorization: Bearer {JWT_TOKEN}
X-CSRF-Token: {CSRF_TOKEN}
X-Enterprise-Id: fcamara-0000-0000-0000-000000000001
```

| Header            | Description                                                     |
| ----------------- | --------------------------------------------------------------- |
| `Authorization`   | User's JWT token (`Bearer eyJhbGciOi...`).                      |
| `X-CSRF-Token`    | CSRF token for protection (required for POST/PUT/PATCH/DELETE). |
| `X-Enterprise-Id` | Company/tenant ID.                                              |
| `Content-Type`    | `application/json`.                                             |

## Request body structure (JSON)

### Required fields

| Field        | Type          | Description                                                                                   |
| ------------ | ------------- | --------------------------------------------------------------------------------------------- |
| `id`         | string (UUID) | Unique **message** ID (UUID v4).                                                              |
| `chat_id`    | string (UUID) | **Conversation** ID; all messages in the same conversation use the same value.                |
| `session_id` | string        | User **session** ID.                                                                          |
| `model`      | string        | LLM model ID, in the format `provider.model-name` (e.g., `azure.gpt-5-chat`).                 |
| `stream`     | boolean       | `true` = streaming response; `false` = complete response at once.                             |
| `messages`   | array         | Conversation messages; each item has `role` (`user`, `assistant`, or `system`) and `content`. |

### Recommended fields

| Field            | Type   | Description                                                                          |
| ---------------- | ------ | ------------------------------------------------------------------------------------ |
| `params`         | object | Model parameters: `temperature` (0.0–2.0), `max_tokens`, `top_p` (0.0–1.0).          |
| `tool_servers`   | array  | Tool servers; empty if not using tools.                                              |
| `features`       | object | Enabled features: `image_generation`, `code_interpreter`, `web_search` (true/false). |
| `variables`      | object | Context variables (e.g., `{{USER_NAME}}`, `{{CURRENT_DATE}}`, `{{USER_LANGUAGE}}`).  |
| `model_item`     | object | Model details (`id`, `name`, `owned_by`, `info`).                                    |
| `stream_options` | object | Streaming options, e.g.: `include_usage` (include usage statistics).                 |

### Complete example

```json theme={null}
{
  "id": "2e0aab0c-1202-48d4-8461-2a61f3f09a89",
  "chat_id": "ca49f9ae-c8fc-4a2c-807e-4ee1e73d4c01",
  "session_id": "mRiO2bEEkTnLsb8oAAPS",
  "model": "azure.gpt-5-chat",
  "stream": false,
  "messages": [
    { "role": "user", "content": "Hello chat." },
    { "role": "assistant", "content": "Hello! How can I help you?" },
    { "role": "user", "content": "Explain API" }
  ],
  "params": { "temperature": 0.7, "max_tokens": 2000 },
  "tool_servers": [],
  "features": {
    "image_generation": false,
    "code_interpreter": false,
    "web_search": false
  },
  "variables": {
    "{{USER_NAME}}": "Leonardo Pereira",
    "{{USER_LOCATION}}": "São Paulo, Brazil",
    "{{CURRENT_DATE}}": "2026-06-17",
    "{{USER_LANGUAGE}}": "en-US"
  },
  "model_item": {
    "id": "azure.gpt-5-chat",
    "name": "Azure gpt-5-chat",
    "owned_by": "openai"
  },
  "stream_options": { "include_usage": true }
}
```

### Success response (200 OK)

```json theme={null}
{
  "id": "chatcmpl-DXttDwwlWkL6YkzARekAPP2cuFUX2",
  "object": "chat.completion",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "API stands for Application Programming Interface..." },
      "finish_reason": "stop"
    }
  ],
  "model": "gpt-5-chat-2025-08-07",
  "usage": { "completion_tokens": 293, "prompt_tokens": 42, "total_tokens": 335 }
}
```

## Python example

```python theme={null}
import requests
import uuid
from datetime import datetime
import pytz

BASE_URL = "https://symphony.fcamara.com"
JWT_TOKEN = "your_jwt_token_here"
CSRF_TOKEN = "your_csrf_token_here"
ENTERPRISE_ID = "fcamara-0000-0000-0000-000000000001"

now = datetime.now(pytz.timezone('America/Sao_Paulo'))

payload = {
    "id": str(uuid.uuid4()),
    "chat_id": str(uuid.uuid4()),
    "session_id": str(uuid.uuid4()),
    "model": "azure.gpt-5-chat",
    "stream": False,
    "messages": [{"role": "user", "content": "Explain API"}],
    "params": {},
    "features": {"image_generation": False, "code_interpreter": False, "web_search": False},
    "variables": {"{{USER_LANGUAGE}}": "en-US"},
    "stream_options": {"include_usage": True}
}

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {JWT_TOKEN}",
    "X-CSRF-Token": CSRF_TOKEN,
    "X-Enterprise-Id": ENTERPRISE_ID
}

response = requests.post(f"{BASE_URL}/api/chat/completions", json=payload, headers=headers)
if response.status_code == 200:
    data = response.json()
    print(data['choices'][0]['message']['content'])
    print(f"Tokens used: {data['usage']['total_tokens']}")
else:
    print(f"Error {response.status_code}:", response.json())
```

## Authentication — getting tokens

### JWT token

1. Log in to the Symphony platform.
2. The token is stored in `localStorage` with the key `token`.
3. Use it in all authenticated requests (`Authorization: Bearer <token>`).

### CSRF token

Required for POST/PUT/PATCH/DELETE. There are two ways:

<Tabs>
  <Tab title="Via endpoint (recommended)">
    ```bash theme={null}
    curl -X GET https://symphony.fcamara.com/api/v1/configs/csrf-token \
      -H "Authorization: Bearer your_token_here" \
      --cookie "token=your_token_here"
    ```

    Response:

    ```json theme={null}
    { "csrf_token": "7cQ46iNeuCBKE71bs2yhWWPShYjJUlQ7ZTMn7q4Pk7o...." }
    ```
  </Tab>

  <Tab title="Via browser DevTools">
    Open DevTools (F12) → **Application → Cookies** tab → copy the `csrf_token` cookie value.
  </Tab>
</Tabs>

<Note>
  If making requests via cURL/API, include the `Authorization` and `X-CSRF-Token` headers and use `--cookie`/`withCredentials: true` to send cookies.
</Note>

## Other useful endpoints

All require the `Authorization: Bearer <key>` header.

| Action                  | Method and endpoint                                                 |
| ----------------------- | ------------------------------------------------------------------- |
| List available models   | `GET /api/models`                                                   |
| Server configuration    | `GET /api/config`                                                   |
| List user conversations | `GET /api/v1/chats` (query `page`, default 1)                       |
| Create new conversation | `POST /api/v1/chats/new`                                            |
| Current user data       | `GET /api/v1/users/me`                                              |
| User permissions        | `GET /api/v1/users/permissions`                                     |
| List knowledge bases    | `GET /api/v1/knowledge`                                             |
| Document upload         | `POST /api/v1/knowledge/upload` (multipart/form-data, field `file`) |
| List tools              | `GET /api/v1/tools`                                                 |
| List prompts            | `GET /api/v1/prompts`                                               |

## Common errors

| Code | Meaning                       | Solution                                                              |
| ---: | ----------------------------- | --------------------------------------------------------------------- |
|  400 | Missing required fields       | Include `id`, `chat_id`, `session_id`, `model`, `stream`, `messages`. |
|  401 | Token missing/invalid/expired | Check the `Authorization` header.                                     |
|  403 | No permission for the model   | Check user permissions for that model.                                |
|  404 | Model not found               | Confirm the `model` with `GET /api/models`.                           |
|  429 | Request limit exceeded        | Wait; implement exponential backoff; reduce frequency.                |
|  500 | Server error                  | Try again and check logs.                                             |

Error structure:

```json theme={null}
{ "detail": "Descriptive error message" }
```

## Streaming (Server-Sent Events)

For real-time responses, send `"stream": true` and read the body in chunks. Lines start with `data: ` and the transmission ends in `data: [DONE]`; incremental content is in `choices[0].delta.content`.

## Security best practices

<Columns cols={2}>
  <Card title="Do" icon="circle-check">
    * Store the key in **environment variables**.
    * Use **HTTPS** in all requests.
    * Implement **retry with exponential backoff** and **timeouts** (\~30s).
    * **Validate** responses before processing.
  </Card>

  <Card title="Don't" icon="circle-xmark">
    * Don't expose the key in **source code**, **URLs**, or query parameters.
    * Don't store the key in **cookies** or `localStorage`.
    * Don't **share** the key or reuse the same one in multiple environments.
  </Card>
</Columns>

## Limits and quotas

* **Rate limit:** varies by plan (consult the administrator).
* **Timeout:** \~30 seconds per request.
* **Maximum request size:** 10 MB.
* **Maximum response size:** no fixed limit (depends on the model).

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Which model should I use in the model field?">
    One of the `id` values returned by `GET /api/models` (e.g., `azure.gpt-5-chat`).
  </Accordion>

  <Accordion title="I get 401 even with the correct key.">
    Confirm the `Bearer` prefix and, for POST methods, the `X-CSRF-Token` header.
  </Accordion>

  <Accordion title="Do I need X-Enterprise-Id?">
    Yes — it identifies the company/tenant of the request.
  </Accordion>
</AccordionGroup>

## Known limitations

* Access to each model depends on the account/company **permissions**.
* **JWT/CSRF** tokens expire; renew them when necessary.
* The model list changes according to administrator configuration — always check `GET /api/models`.
