# Responses (OpenAI format)

> Call router.africa with the OpenAI Responses API. Point the OpenAI SDK at the API and keep your code.

Source: https://router.africa/docs/responses

`POST /v1/responses` ([API reference](https://router.africa/docs/api-reference/create-response)) accepts requests in the OpenAI Responses format. It is the endpoint that the OpenAI Agents SDK and Codex use. If your code calls `client.responses.create`, you change the base URL and the key, and nothing else.

## Change one line

Point the OpenAI SDK at `https://api.router.africa/v1` and give it your router.africa key. The key is sent as `Authorization: Bearer`, as on every other endpoint.

**curl**

```bash
curl https://api.router.africa/v1/responses \
  -H "Authorization: Bearer $ROUTER_AFRICA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1-mini",
    "instructions": "Answer in one short sentence.",
    "input": "Habari! Say hello in Swahili.",
    "max_output_tokens": 100
  }'
```

**Python**

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.router.africa/v1",  # the one line that changes
    api_key=os.environ["ROUTER_AFRICA_API_KEY"],
)

response = client.responses.create(
    model="openai/gpt-4.1-mini",
    instructions="Answer in one short sentence.",
    input="Habari! Say hello in Swahili.",
    max_output_tokens=100,
)
print(response.output_text)
print(response.usage)
```

**TypeScript**

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.router.africa/v1", // the one line that changes
  apiKey: process.env.ROUTER_AFRICA_API_KEY,
});

const response = await client.responses.create({
  model: "openai/gpt-4.1-mini",
  instructions: "Answer in one short sentence.",
  input: "Habari! Say hello in Swahili.",
  max_output_tokens: 100,
});
console.log(response.output_text);
console.log(response.usage);
```

## Request

| Field | Notes |
|---|---|
| `model` | Required. A router.africa model id, as listed by `GET /v1/models`. The model must be switched on and allowed for your key. |
| `input` | Required. A string, or an array of input items. |
| `instructions` | A system instruction for the model. |
| `stream` | Set `true` for server-sent events. See below. |
| `temperature` | Passed to the model. |
| `max_output_tokens` | A value above the model's limit is lowered to the limit. It isn't an error. |
| `tools` | Function tools: `type: "function"`, a `name`, and optionally `description`, `parameters` and `strict`. |

Other fields are not part of the contract on this endpoint. See [Compatibility notes](https://router.africa/docs/compatibility-notes).

You can send an [`Idempotency-Key`](https://router.africa/docs/idempotency-and-retries) header on this endpoint, as on chat completions.

## Response

The response is the Responses object: `id`, `object`, `created_at`, `status`, `model`, `output` and `usage`. The text is in `output`, in items of type `message` with `output_text` content. The SDK's `output_text` joins it for you. `usage` has `input_tokens`, `output_tokens` and `total_tokens`. The header `x-request-id` identifies the request. You can look it up with [`GET /v1/generation`](https://router.africa/docs/generation).

## Stream the response

Set `stream: true`. Each event has an `event:` line with its type, such as `response.created`, `response.output_text.delta` and `response.completed`, and a `data:` line with one JSON object. The stream ends after `response.completed`, with no `[DONE]` line. The `response.completed` event carries the final `usage`. If you disconnect, you are charged for the tokens used up to that point. See [Streaming](https://router.africa/docs/streaming).

**curl**

```bash
curl -N https://api.router.africa/v1/responses \
  -H "Authorization: Bearer $ROUTER_AFRICA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1-mini",
    "input": "Habari! Say hello in Swahili.",
    "stream": true
  }'
```

**Python**

```python
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.router.africa/v1", api_key=os.environ["ROUTER_AFRICA_API_KEY"])

stream = client.responses.create(
    model="openai/gpt-4.1-mini",
    input="Habari! Say hello in Swahili.",
    stream=True,
)

for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)
    elif event.type == "response.completed":
        print("\ntokens:", event.response.usage.total_tokens)
```

**TypeScript**

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.router.africa/v1",
  apiKey: process.env.ROUTER_AFRICA_API_KEY,
});

const stream = await client.responses.create({
  model: "openai/gpt-4.1-mini",
  input: "Habari! Say hello in Swahili.",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") process.stdout.write(event.delta);
  if (event.type === "response.completed") console.log("\ntokens:", event.response.usage?.total_tokens);
}
```

## Errors

Errors use the same body and the same reasons as chat completions. An error after the stream has started arrives as a final `data: {"error": {…}}` event, and then the stream ends. See [Errors](https://router.africa/docs/errors).
