# Olly API

Use the **Olly API** to make [Olly](https://coralogix.com/docs/user-guides/olly/index.md) a programmatic participant in your AI agents, automation pipelines, and scheduled jobs. Trigger investigations from outside the Coralogix UI, send prompts on behalf of a user, and retrieve the query results, charts, and tables Olly generates — all using the same models, skills, and permissions as the in-product chat.

Common use cases include:

- Pulling Olly findings into an external agent or partner integration that enriches its workflow with observability insights.
- Exposing Olly as a tool to your own automation or AI tooling.
- Running scheduled or deployment-triggered investigations with no human in the loop.

## What you need

Olly enabled for your team. The chat and message endpoints return `403 Forbidden` until your team admin turns on the **AI-Powered Capabilities** toggle in **Settings**, then **Account Preferences**. See [Enable Olly](https://coralogix.com/docs/user-guides/olly/enable/index.md).

## Authentication

Every request requires an [API key](https://coralogix.com/docs/user-guides/account-management/api-keys/api-keys/index.md), passed as a Bearer token in the `Authorization` header. The Olly API accepts two key types:

- **Personal API key**: tied to a single user. Token consumption is deducted from the user's quota.
- **Team API key**: tied to a team, intended for shared services, agents, and integrations. Token consumption is deducted from the team's quota only — no per-user limit and no free units. If the team has no paid quota, the request is blocked.

Pick the endpoint that matches your Coralogix [domain](https://coralogix.com/docs/user-guides/account-management/account-settings/coralogix-domain/index.md) using the domain selector at the top of the page.

**Example:**

```bash
curl -H "Authorization: Bearer <cx_api_key>" \
  https://api.[[DOMAIN_VALUE]]/api/v2/olly/v2/chats/
```

### Entity identity

Each chat and interaction is owned by a single **entity** — either a user or a team key. The owner is recorded in the response field `entity_id`:

| Caller           | `entity_id` value                                             |
| ---------------- | ------------------------------------------------------------- |
| Personal API key | The user's ID.                                                |
| Team API key     | `team_key:<key_id>`. `key_id` is stable across key rotations. |

### Access control

Access to a chat follows its `shared_type` and the caller's `entity_id`:

| `shared_type`         | Who can access                                      |
| --------------------- | --------------------------------------------------- |
| `private` (default)   | Only the owning `entity_id`.                        |
| `specific_entities`   | Only the entity IDs listed in `shared_entity_ids`.  |
| `entire_organization` | Any entity in the team — users and team keys alike. |

A `private` chat created by a user is not accessible by a team API key, and vice versa, because their `entity_id` values differ.

## Core concepts

| Concept         | Description                                                                                                                              |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Chat**        | A conversation session. Create one before sending messages.                                                                              |
| **Interaction** | A single user message and the AI response within a chat. Each message you send creates one interaction.                                  |
| **Artifact**    | A structured data object — logs, spans, or metrics — the agent produces during an interaction.                                           |
| **View**        | A visualization (chart or table) generated from artifact data.                                                                           |
| **User file**   | A file you upload through the API and reference in a chat message to give Olly extra context.                                            |
| **User rule**   | A personal instruction Olly applies to every chat in your session — for example, "always group log results by `service.name`."           |
| **Team rule**   | A team-wide instruction a team admin sets. Olly applies it to every team member's chats. Managing team rules requires admin permissions. |
| **Skill**       | A reusable Markdown instruction set Olly can apply mid-chat. Pre-load specific skills into a run with `load_skill_ids`.                  |

This document provides example requests and responses for creating chats, sending messages with the wait-for-response and polling flows, retrieving the artifacts Olly produces during an interaction, and managing your user rules and personal skills.

### Interaction modes

Every API interaction runs in **`skill`** mode — Pro mode in the in-product Olly chat. This is the default for `interaction_mode` and the mode the API is built around: Olly applies a curated set of specialized skills to each request, extensible with your own custom skills.

Deprecated modes

The API still accepts `focus` and `fast` for backward compatibility, but both will be deprecated. Migrate existing integrations to `skill`.

For background on Pro mode, see [Olly modes](https://coralogix.com/docs/user-guides/olly/modes/index.md).

### Models

Use the `model_choice` field to pick the model Olly runs the interaction with. The API default is `gpt-5.4`. To match what users see in the in-product Olly chat, pass one of:

`gpt-5.4`, `gpt-5.4-mini`, `gpt-5.2`, `claude-sonnet-4-5`, `claude-sonnet-4-6`, `claude-haiku-4-5`, `gemini-3.1-pro-preview`, `gemini-3-flash-preview`.

See [Model selection](https://coralogix.com/docs/user-guides/olly/model-selection/index.md) for the in-product display names and recommended defaults.

### Interaction status lifecycle

```
flowchart LR
    Created[Interaction created]
    InProgress[In progress]
    Completed[Completed]
    Error[Error]
    Stopped[Stopped]

    Created --> InProgress
    InProgress -->|Agent finished| Completed
    InProgress -->|Encountered an error| Error
    InProgress -->|User cancelled via /stop| Stopped

    class Created entry
    class Completed success
    class Error error
    class Stopped waiting
```

## Send a message and wait for the response

Send a message and wait for the response in a single request. Set `should_block: true` to make the call return only after the agent finishes.

### Step 1: Create a chat

**Example request:**

```text
POST /api/v2/olly/v2/chats/
```

**Example response** (`201 Created`):

```json
{
  "id": "a1b2c3d4-...",
  "title": "",
  "entity_id": "user_abc-123",
  "created_at": "2025-01-15T10:30:00Z",
  "type": "web",
  "shared_options": { "shared_type": "private", "shared_entity_ids": null },
  "metadata": null
}
```

### Step 2: Send a message (wait inline)

**Example request:**

```text
POST /api/v2/olly/v2/chats/{chat_id}/interactions/
```

```json
{
  "content": [{"type": "input_text", "text": "What alerts fired in the last hour?"}],
  "should_block": true,
  "timeout_seconds": 120
}
```

**Example response** (`200 OK`, after the agent finishes):

```json
{
  "id": "e5f6g7h8-...",
  "chat_id": "a1b2c3d4-...",
  "status": "completed",
  "interaction_mode": "skill",
  "model_choice": "gpt-5.4",
  "created_at": "2025-01-15T10:30:05Z",
  "feedback": null,
  "feedback_description": null,
  "data_sources": [],
  "responses": [
    {
      "id": "msg-user-1",
      "role": "user",
      "content": [{"type": "text", "text": "What alerts fired in the last hour?"}]
    },
    {
      "id": "msg-assistant-1",
      "role": "assistant",
      "content": [{"type": "text", "text": "I found 3 alerts that fired in the last hour..."}]
    }
  ]
}
```

## Poll for response

Send a message, then poll for the response. Use this flow when responses might take more than a few seconds, or when you want to show interim progress in your UI.

### Step 1: Create a chat

Create a chat the same way as described [here](https://coralogix.com/docs/developer-portal/apis/olly/#step-1-create-a-chat).

### Step 2: Send a message (non-blocking)

**Example request:**

```text
POST /api/v2/olly/v2/chats/{chat_id}/interactions/
```

```json
{
  "content": [{"type": "input_text", "text": "Show me error logs from the payments service"}]
}
```

**Example response** (`200 OK`, returns immediately):

```json
{
  "id": "e5f6g7h8-...",
  "chat_id": "a1b2c3d4-...",
  "status": "in_progress",
  "interaction_mode": "skill",
  "model_choice": "gpt-5.4",
  "created_at": "2025-01-15T10:30:05Z",
  "feedback": null,
  "feedback_description": null,
  "data_sources": [],
  "responses": null
}
```

### Step 3: Poll for completion

**Example request:**

```text
GET /api/v2/olly/v2/chats/{chat_id}/interactions/{interaction_id}
```

Poll every few seconds. When `status` changes to `completed`, the `responses` field contains the agent's reply.

**Example response** (`200 OK`, after `status` becomes `completed`):

```json
{
  "id": "e5f6g7h8-...",
  "chat_id": "a1b2c3d4-...",
  "status": "completed",
  "interaction_mode": "skill",
  "model_choice": "gpt-5.4",
  "created_at": "2025-01-15T10:30:05Z",
  "feedback": null,
  "feedback_description": null,
  "data_sources": [],
  "responses": [
    {
      "id": "msg-user-1",
      "role": "user",
      "content": [{"type": "text", "text": "Show me error logs from the payments service"}]
    },
    {
      "id": "msg-assistant-1",
      "role": "assistant",
      "content": [{"type": "text", "text": "Here are the recent error logs from the payments service..."}]
    }
  ]
}
```

## Attach files to a message

To include a file in a chat message, upload it first and then pass the returned file IDs in `user_file_ids` on the create-interaction request. The upload flow uses a presigned URL so file bytes go directly to cloud storage, not through the API.

### Step 1: Check upload options

**Example request:**

```text
GET /api/v2/olly/user-files/upload-options
```

**Example response** (`200 OK`):

```json
{
  "allowed_content_types": ["application/pdf", "image/png", "image/jpeg", "text/csv", "..."],
  "max_file_size_bytes": 5242880,
  "max_plaintext_total_size_bytes": 1048576,
  "max_files_per_message": 5,
  "plaintext_content_types": ["text/plain", "application/json", "text/csv", "..."]
}
```

Use this to check the current size and count limits, and the content types Olly accepts, before requesting an upload URL.

### Step 2: Request a presigned upload URL

**Example request:**

```text
POST /api/v2/olly/user-files/upload-url
```

```json
{
  "file_name": "alerts-2026-05-15.csv",
  "content_type": "text/csv"
}
```

**Example response** (`201 Created`):

```json
{
  "user_file_id": "f7e6d5c4-...",
  "presigned_post": {
    "url": "https://storage.example.com/uploads",
    "fields": {
      "key": "user-files/f7e6d5c4-...",
      "policy": "eyJleHBpcmF0aW9uIjogIjIw...",
      "x-amz-signature": "abc123...",
      "x-amz-credential": "..."
    }
  }
}
```

### Step 3: Upload the file to cloud storage

POST the file as a multipart form to `presigned_post.url`, including every key/value from `presigned_post.fields` and the file bytes in a `file` field:

```bash
curl -X POST <presigned_post.url> \
  -F key=<presigned_post.fields.key> \
  -F policy=<presigned_post.fields.policy> \
  -F x-amz-signature=<presigned_post.fields.x-amz-signature> \
  -F x-amz-credential=<presigned_post.fields.x-amz-credential> \
  -F file=@/path/to/alerts-2026-05-15.csv
```

A successful upload returns `204 No Content` from cloud storage.

### Step 4: Attach the file in your message

Pass the `user_file_id` returned in Step 2 on the create-interaction request:

**Example request:**

```text
POST /api/v2/olly/v2/chats/{chat_id}/interactions/
```

```json
{
  "content": [{"type": "input_text", "text": "Summarize the alerts in the attached CSV."}],
  "user_file_ids": ["f7e6d5c4-..."]
}
```

To retrieve a previously uploaded file later, use:

```text
GET /api/v2/olly/user-files/{user_file_id}/download_url
```

For the in-product file-attachment UX (file types, size limits, behavior in chat), see [File attachments for chat context](https://coralogix.com/docs/user-guides/olly/file-attachments/index.md).

## Manage artifacts

After an interaction completes, retrieve any artifacts the agent produced (query results, charts) through the artifacts endpoints.

### List artifacts for a chat

**Example request:**

```text
GET /api/v2/olly/artifacts/?chat_id={chat_id}
```

**Example response** (`200 OK`):

```json
[
  {
    "id": "art-1234-...",
    "created_at": "2025-01-15T10:30:10Z",
    "type": "coralogix_logs",
    "chat_id": "a1b2c3d4-...",
    "interaction_id": "e5f6g7h8-...",
    "is_user_managed": false,
    "data_source_id": null,
    "chat_title": "Alert Investigation",
    "chat_type": "web"
  }
]
```

### Get an artifact with download URL

**Example request:**

```text
GET /api/v2/olly/artifacts/{artifact_id}
```

**Example response** (`200 OK`):

```json
{
  "id": "art-1234-...",
  "type": "coralogix_logs",
  "params": {
    "query": "source logs | filter severity == 'error' | filter $d.service == 'payments'",
    "description": "Error logs from payments service"
  },
  "download_url": "https://storage.example.com/...",
  "created_at": "2025-01-15T10:30:10Z",
  "chat_id": "a1b2c3d4-...",
  "interaction_id": "e5f6g7h8-...",
  "is_user_managed": false,
  "data_source_id": null
}
```

The `download_url` is a pre-signed URL that gives temporary access to the full artifact data, stored as gzipped JSON.

### Get views (charts and tables) for an artifact

**Example request:**

```text
GET /api/v2/olly/views/artifacts/{artifact_id}
```

**Example response** (`200 OK`):

```json
[
  {
    "id": "view-5678-...",
    "type": "chart",
    "artifact_ids": ["art-1234-..."],
    "download_url": "https://storage.example.com/...",
    "created_at": "2025-01-15T10:30:15Z",
    "team_id": "team123"
  }
]
```

## Manage user rules

User rules are personal instructions Olly applies to every chat. See [Rules](https://coralogix.com/docs/user-guides/olly/rules/index.md) for the in-product UX, validation, and limits.

**Example request:** create a personal rule

```text
POST /api/v2/olly/user-rules/
```

```json
{
  "rule": "When summarizing logs, group entries by `service.name` and surface the top three error categories per service."
}
```

**Example response** (`201 Created`):

```json
{
  "id": "9f8e7d6c-...",
  "rule": "When summarizing logs, group entries by `service.name` and surface the top three error categories per service.",
  "enabled": true,
  "created_at": "2026-05-27T10:30:00Z"
}
```

See [User rules](#user-rules) in the Endpoint reference for `GET`, `PUT`, and `DELETE` operations.

## Manage team rules

Team rules are instructions a team admin defines and Olly applies for every team member. The endpoint shape mirrors user rules; the difference is scope and permissions — creating, updating, or deleting a team rule requires admin permissions. See [Rules](https://coralogix.com/docs/user-guides/olly/rules/#team-rules) for the in-product UX and the permission keys.

**Example request:** create a team rule

```text
POST /api/v2/olly/team-rules/
```

```json
{
  "rule": "When investigating incidents, prioritize production environments over staging."
}
```

**Example response** (`201 Created`):

```json
{
  "id": "4e3d2c1b-...",
  "rule": "When investigating incidents, prioritize production environments over staging.",
  "enabled": true,
  "created_at": "2026-05-27T10:30:00Z"
}
```

See [Team rules](#team-rules) in the Endpoint reference for `GET`, `PUT`, and `DELETE` operations.

## Manage personal skills

Personal skills are reusable Markdown instruction sets you can pre-load into a Skills Agent run with `load_skill_ids`. See [Skills](https://coralogix.com/docs/user-guides/olly/skills/index.md) for the in-product UX, naming rules, validation, and limits.

### Create a personal skill

**Example request:**

```text
POST /api/v2/olly/skills/personal/
```

```json
{
  "name": "log-summarizer",
  "description": "Summarize the last hour of logs by service.",
  "content": "When this skill is invoked, group log entries by `service.name` and surface the top three error categories per service."
}
```

**Example response** (`201 Created`):

```json
{
  "id": "5a4b3c2d-...",
  "name": "log-summarizer",
  "description": "Summarize the last hour of logs by service.",
  "content": "When this skill is invoked, group log entries by `service.name` and surface the top three error categories per service.",
  "enabled": true,
  "created_at": "2026-05-27T10:30:00Z",
  "entity_id": "user_abc-123"
}
```

Constraints: `name` ≤ 64 characters, `description` ≤ 1024 characters, `content` ≤ 20480 characters.

### List personal skills

**Example request:**

```text
GET /api/v2/olly/skills/personal/
```

**Example response** (`200 OK`):

```json
[
  {
    "id": "5a4b3c2d-...",
    "name": "log-summarizer",
    "description": "Summarize the last hour of logs by service.",
    "content": "When this skill is invoked, group log entries by `service.name` and surface the top three error categories per service.",
    "enabled": true,
    "created_at": "2026-05-27T10:30:00Z",
    "entity_id": "user_abc-123"
  }
]
```

See [Skills](#skills) in the Endpoint reference for `PUT` and `DELETE` operations.

## Endpoint reference

### Chats

| Method   | Path                                     | Description                               |
| -------- | ---------------------------------------- | ----------------------------------------- |
| `POST`   | `/api/v2/olly/v2/chats/`                 | Create a new chat                         |
| `GET`    | `/api/v2/olly/v2/chats/`                 | List all chats for the current user       |
| `GET`    | `/api/v2/olly/v2/chats/{chat_id}`        | Get a chat with full conversation history |
| `GET`    | `/api/v2/olly/v2/chats/search`           | Search chats by content                   |
| `GET`    | `/api/v2/olly/v2/chats/{chat_id}/title`  | Get a chat's title                        |
| `PATCH`  | `/api/v2/olly/v2/chats/{chat_id}/title`  | Rename a chat                             |
| `DELETE` | `/api/v2/olly/v2/chats/{chat_id}`        | Delete a chat and all associated data     |
| `PATCH`  | `/api/v2/olly/v2/chats/{chat_id}/shared` | Set chat privacy and sharing options      |
| `POST`   | `/api/v2/olly/v2/chats/{chat_id}/stop`   | Stop an ongoing response generation       |

### Interactions

| Method | Path                                                            | Description                            |
| ------ | --------------------------------------------------------------- | -------------------------------------- |
| `POST` | `/api/v2/olly/v2/chats/{chat_id}/interactions/`                 | Send a message (create an interaction) |
| `GET`  | `/api/v2/olly/v2/chats/{chat_id}/interactions/`                 | List interactions in a chat            |
| `GET`  | `/api/v2/olly/v2/chats/{chat_id}/interactions/{interaction_id}` | Get interaction status and responses   |

### User files

| Method | Path                                                  | Description                                       |
| ------ | ----------------------------------------------------- | ------------------------------------------------- |
| `GET`  | `/api/v2/olly/user-files/upload-options`              | Get current size, count, and content-type limits  |
| `POST` | `/api/v2/olly/user-files/upload-url`                  | Mint a presigned upload URL for a new file        |
| `GET`  | `/api/v2/olly/user-files/{user_file_id}/download_url` | Get a download URL for a previously uploaded file |

### User rules

User rules are personal instructions Olly applies to every chat. See [Rules](https://coralogix.com/docs/user-guides/olly/rules/index.md) for the in-product UX.

| Method   | Path                                | Description                   |
| -------- | ----------------------------------- | ----------------------------- |
| `GET`    | `/api/v2/olly/user-rules/`          | List the current user's rules |
| `POST`   | `/api/v2/olly/user-rules/`          | Create a new user rule        |
| `GET`    | `/api/v2/olly/user-rules/{rule_id}` | Get a specific rule           |
| `PUT`    | `/api/v2/olly/user-rules/{rule_id}` | Update a rule                 |
| `DELETE` | `/api/v2/olly/user-rules/{rule_id}` | Delete a rule                 |

### Team rules

Team rules are instructions a team admin defines and Olly applies for every team member. Managing team rules requires admin permissions. See [Rules](https://coralogix.com/docs/user-guides/olly/rules/#team-rules) for the in-product UX and permission details.

| Method   | Path                                | Description                    |
| -------- | ----------------------------------- | ------------------------------ |
| `GET`    | `/api/v2/olly/team-rules/`          | List team rules                |
| `POST`   | `/api/v2/olly/team-rules/`          | Create a new team rule (admin) |
| `GET`    | `/api/v2/olly/team-rules/{rule_id}` | Get a specific team rule       |
| `PUT`    | `/api/v2/olly/team-rules/{rule_id}` | Update a team rule (admin)     |
| `DELETE` | `/api/v2/olly/team-rules/{rule_id}` | Delete a team rule (admin)     |

### Skills

Skills are reusable instruction sets Olly can apply mid-chat. See [Skills](https://coralogix.com/docs/user-guides/olly/skills/index.md) for the in-product UX, naming rules, and limits.

| Method   | Path                                      | Description                             |
| -------- | ----------------------------------------- | --------------------------------------- |
| `GET`    | `/api/v2/olly/skills/personal/`           | List the current user's personal skills |
| `POST`   | `/api/v2/olly/skills/personal/`           | Create a personal skill                 |
| `PUT`    | `/api/v2/olly/skills/personal/{skill_id}` | Update a personal skill                 |
| `DELETE` | `/api/v2/olly/skills/personal/{skill_id}` | Delete a personal skill                 |

To pre-load specific skills (personal or team) into a Skills Agent run, pass their IDs in the `load_skill_ids` field on the create-interaction request (see [Request body: create interaction](#request-body-create-interaction)).

### Artifacts

| Method | Path                                   | Description                          |
| ------ | -------------------------------------- | ------------------------------------ |
| `GET`  | `/api/v2/olly/artifacts/`              | List artifacts with optional filters |
| `GET`  | `/api/v2/olly/artifacts/{artifact_id}` | Get an artifact with download URL    |

### Artifact views

| Method | Path                                         | Description                |
| ------ | -------------------------------------------- | -------------------------- |
| `GET`  | `/api/v2/olly/views/artifacts/{artifact_id}` | List views for an artifact |
| `GET`  | `/api/v2/olly/views/{artifact_view_id}`      | Get a specific view by ID  |

## Artifact types

| Type                       | Description                                      |
| -------------------------- | ------------------------------------------------ |
| `coralogix_logs`           | DataPrime log query results                      |
| `coralogix_spans`          | DataPrime span and trace query results           |
| `coralogix_metrics`        | PromQL metrics query results                     |
| `kubernetes_query_results` | Kubernetes resource query results                |
| `alert_watch_data`         | Alert trigger data with associated query results |
| `github_file_content`      | GitHub file content                              |

## Error handling

The API uses standard HTTP status codes. Error responses use this format:

```json
{
  "detail": "Human-readable error message"
}
```

| Status | Meaning                                                                                         |
| ------ | ----------------------------------------------------------------------------------------------- |
| `400`  | Bad request (for example, empty content, invalid parameters)                                    |
| `403`  | Forbidden (Olly not enabled for the team, quota exceeded, team API key with no paid team quota) |
| `404`  | Resource not found                                                                              |
| `422`  | Validation error (invalid request body)                                                         |
| `425`  | Too early (for example, stopping an interaction that has not started)                           |

## Request body: create interaction

The `POST /api/v2/olly/v2/chats/{chat_id}/interactions/` endpoint accepts:

| Field              | Type           | Default     | Description                                                                                                                                                                   |
| ------------------ | -------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `content`          | `list[object]` | required    | List of content blocks. Each block has `type` and content fields.                                                                                                             |
| `interaction_mode` | `string`       | `"skill"`   | The mode Olly uses for this interaction. Use `"skill"` for new integrations; `"focus"` and `"fast"` are accepted but deprecated. See [Interaction modes](#interaction-modes). |
| `model_choice`     | `string`       | `"gpt-5.4"` | AI model to use. See [Models](#models) for the available IDs.                                                                                                                 |
| `should_block`     | `boolean`      | `false`     | If `true`, wait for the agent to finish and return responses inline.                                                                                                          |
| `timeout_seconds`  | `integer`      | `900`       | Maximum seconds to wait. Only applies when `should_block=true`. Range: 1–3600.                                                                                                |
| `user_file_ids`    | `list[UUID]`   | `[]`        | File IDs returned from the [file upload flow](#attach-files-to-a-message).                                                                                                    |
| `load_skill_ids`   | `list[UUID]`   | `[]`        | Skill IDs (personal or team) to pre-load before the Skills Agent's first turn. Up to 10 IDs. Requires `interaction_mode == "skill"`.                                          |

### Content block format

```json
{"type": "input_text", "text": "Your message here"}
```

### Response format: get chat

By default, `GET /api/v2/olly/v2/chats/{chat_id}` returns structured messages (`response_format=content_blocks`). Pass `response_format=events` to receive streaming events instead.

## Learn more

- [Olly chat](https://coralogix.com/docs/user-guides/olly/olly-chat/index.md)
- [Model selection](https://coralogix.com/docs/user-guides/olly/model-selection/index.md)
- [Olly pricing](https://coralogix.com/docs/user-guides/olly/pricing/index.md)
- [Data processing, privacy, and compliance](https://coralogix.com/docs/user-guides/olly/data-privacy/index.md)
