# OpenAI-compatible API overview

> Talk to Octo from the OpenAI SDK, LangChain, LiteLLM or n8n through /v1/responses and /v1/chat/completions — the endpoints, the base URL, the model allowlist and a first call in curl and Python.

The `/v1` API is an OpenAI-compatible facade over Octo. Any tool that speaks
the OpenAI API can talk to Octo by changing `base_url` and `api_key` — nothing
else in your integration needs to change.

- **Base URL:** `https://api.omniocto.com/v1`

Both endpoint families below are thin serializers over the same internal turn
pipeline that powers the dashboard and the channel bridge, so a `/v1` call
inherits Octo's full tool catalog, role filtering, confirmation machine, and
usage metering unchanged.

## Endpoints

| Endpoint | Purpose |
|---|---|
| `POST /v1/responses` | Native OpenAI **Responses API** (recommended). Server-side state, `background` mode, streaming. |
| `GET /v1/responses/:id` | Retrieve a stored response (for polling `background` requests). |
| `POST /v1/chat/completions` | **Chat Completions** compatibility shim — works with LangChain, LiteLLM, n8n, and anything expecting the classic shape. |
| `GET /v1/models`, `GET /v1/models/:id` | Model list / retrieve (`client.models.list()`). |
| `/v1/webhooks` (CRUD) | Register signed, retried **outbound webhooks** for workspace [events](/openai-api/events/). |
| `GET /v1/events` | Authenticated **Server-Sent Events** feed of the same events, with a resume cursor. Texting events (`message.received`, `message.sent`, `message.status_updated`) are described in [Track delivery and replies](/platform-api/events/). |
| `GET /v1/media/{id}` | A picture or video someone texted you: returns a signed download link valid for 1 hour. See [Inbound pictures (MMS)](/platform-api/events/#inbound-pictures-mms). |
| `GET /v1/recordings/{conversation_id}` | A presigned download URL for a call recording. |

For the full request/response schema of every operation, use the interactive
reference: [API reference (try it)](/openapi/v1/).

## The `model` field

`model` selects from a curated allowlist. Send any listed id to run that model;
an **unknown id returns `400 model_not_found`**; **omit `model`** to run the
default (`claude-sonnet-4-6`). The chosen model is echoed back in the response.
Call `GET /v1/models` (`client.models.list()`) for the live list.

| Model | Provider |
|---|---|
| `claude-sonnet-4-6` (default) | Anthropic |
| `claude-haiku-4-5` | Anthropic |
| `claude-opus-4-7` | Anthropic |
| `gpt-5.4` | OpenAI |
| `gpt-5.4-mini` | OpenAI |
| `deepseek-v4-flash` | DeepSeek (now served by DeepSeek V4.1 Flash) |
| `deepseek-v4-pro` | DeepSeek |
| `deepseek-flash` | DeepSeek V4.1 Flash |

`GET /v1/models` also lists the newer models Octo offers.

Every call runs through Octo's full tool catalog and confirmation logic
regardless of model; usage is metered at each model's own rate.

## Plan mode: `tool_choice: "none"`

Send `tool_choice: "none"` on `/v1/responses` to have Octo plan without acting.
Octo still sees every tool's name and schema, so it can say what it would set
up and what it still needs to know, but it calls no tool. A reply in plan mode
is never read as a confirmation: a `YES` does not run an action Octo proposed
earlier in the conversation. Send the next turn without `tool_choice` (or with
`"auto"`) when you want Octo to act.

In plan mode Octo reads its tools as a one-line list instead of their full
schemas, so a plan-mode turn is smaller and faster than a normal one.

## Reasoning effort: `reasoning.effort`

`reasoning: { "effort": "low" | "medium" | "high" }` replaces the model's default
effort for one turn. `"none"` turns thinking off where the model allows it, so
the first words arrive sooner; use it when something speaks Octo's reply aloud.
Any other value is ignored.

## First call: curl

```bash
curl https://api.omniocto.com/v1/responses \
  -H "Authorization: Bearer $OMNI_OCTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "input": "What can you help me with?"
  }'
```

## First call: Python (OpenAI SDK)

```python
from openai import OpenAI

client = OpenAI(
    api_key="sk-octo_...",
    base_url="https://api.omniocto.com/v1",
)

resp = client.responses.create(
    model="claude-sonnet-4-6",
    input="What can you help me with?",
)
print(resp.output_text)
```

## Next

- [Statefulness](/openai-api/statefulness/) — continuing a conversation across calls.
- [Confirmations](/openai-api/confirmations/) — how risky actions get confirmed over the API.
- [Streaming](/openai-api/streaming/) — Server-Sent Events for both endpoints.
- [Events & webhooks](/openai-api/events/) — subscribe to workspace state changes your agent didn't initiate.
- [Send SMS with the API](/platform-api/sms/) — single texts, campaigns, delivery status, reply webhooks and inbound media, with only an API key.
- [Rate limits](/openai-api/rate-limits/), [Errors](/openai-api/errors/), [Usage & billing](/openai-api/usage/).