# Integrations

> Use Numes from any OpenAI-compatible client by changing the base URL, the key and the model ID.

Source: https://0.0.0.0:3000/docs/integrations/overview
Documentation index: https://0.0.0.0:3000/docs/llms.txt

Any client that speaks the OpenAI Chat Completions API, or OpenRouter's version of it, can use Numes. Change three settings and keep the rest of your code.

## Configure any client

| Setting | Value |
| --- | --- |
| **Base URL** | `https://api.numes.ai/api/v1` |
| **API key** | An inference key, sent as `Authorization: Bearer <key>`. Keep it in `NUMES_API_KEY` |
| **Model** | An `author/model` ID such as `openai/gpt-6-luna`, from the [catalogue](/models) or [`GET /models`](/docs/api-reference/models/list-models) |
| **API style** | OpenAI **Chat Completions**, not the Responses API |

Some clients show their own provider prefix, such as `myrouter/openai/gpt-6-luna`. That prefix stays in the client and is never sent to the API.

| Endpoint | OpenAI SDK method |
| --- | --- |
| `POST /chat/completions` | `chat.completions.create` |
| `POST /embeddings` | `embeddings.create` |
| `POST /audio/speech` | `audio.speech.create` |
| `POST /audio/transcriptions` | `audio.transcriptions.create` |
| `POST /images` | None; see [Image generation](/docs/integrations/openai-sdk#image-generation) |
| `GET /models` | `models.list` |
| `GET /generation`, `GET /key`, `/keys`, `GET /credits` | None; call over HTTP |

## Tested clients

These clients run in the platform's automated compatibility tests at the versions shown, covering streaming, tool calls, reasoning and usage. Newer versions usually work.

| Client | Tested version | Guide |
| --- | --- | --- |
| OpenAI Python and TypeScript SDKs | Not pinned | [OpenAI SDK](/docs/integrations/openai-sdk) |
| OpenCode | 1.18.22 | [Coding agents](/docs/integrations/coding-agents#opencode) |
| Pi | 1.4.0 | [Coding agents](/docs/integrations/coding-agents#pi) |
| OMP | 18.0.11 | [Coding agents](/docs/integrations/coding-agents#omp) |
| OpenRouter provider for the Vercel AI SDK | `@openrouter/ai-sdk-provider` 2.9.0 with `ai` 6.0.168 | [Below](#vercel-ai-sdk) |
| curl, `requests`, `fetch`, Go `net/http` | — | [Raw HTTP](/docs/integrations/http) |

### Vercel AI SDK

Point the OpenRouter provider at Numes:

```typescript title="ai-sdk.ts"
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
import { streamText } from "ai";

const router = createOpenRouter({
  baseURL: "https://api.numes.ai/api/v1",
  apiKey: process.env.NUMES_API_KEY,
});

const result = streamText({
  model: router.chat("openai/gpt-6-luna"),
  prompt: "Explain exact-decimal billing in two sentences.",
});

for await (const text of result.textStream) process.stdout.write(text);
console.log("\n", await result.usage);
```

## If the first request fails

Most first-request failures come from a few rules. [Compatibility](/docs/api-reference/compatibility) lists every difference.

| Response | Usual cause |
| --- | --- |
| `400 invalid_request` | A nonnumeric sampling hint, such as `frequency_penalty: "high"`, an unsupported control such as `store: true`, or an invalid output limit |
| `401 invalid_credentials` | A key from another service, a management key, or a disabled key |
| `403 cors_forbidden` | A call from a browser on another website; call the API from your server |
| `503 provider_unavailable` | An unknown model ID, or no endpoint of the model supports a feature you sent, such as tools |

Two more things clients must handle: `usage.cost` is in the key's currency, so BTC keys report satoshis, and a stream ends with a usage-only chunk whose `choices` array is empty.

## Next steps

:::cards
- {code} [OpenAI SDK](/docs/integrations/openai-sdk) Python and TypeScript setup, streaming, tools and errors.
- {terminal} [Coding agents](/docs/integrations/coding-agents) Start OpenCode, Pi and OMP.
- {plug} [Raw HTTP](/docs/integrations/http) curl, Python, Node.js and Go without an SDK.
- {braces} [Compatibility](/docs/api-reference/compatibility) Every difference from OpenRouter.
:::
