Sign in to the console, fund a balance, then create an API key. The secret is shown once. We store only a hash of it, so if you lose it we have no way to show it to you again — create a new key and revoke the old one.
Keep it out of client-side code and out of git. Anything that can read the key can spend your balance.
African Open Router speaks OpenAI's chat-completions API. If your code already talks to OpenAI, the only change is the base URL and the key.
# Python from openai import OpenAI client = OpenAI( base_url="https://api.redactron.ai/v1", api_key="<AOR_API_KEY>", )
// Node import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.redactron.ai/v1", apiKey: process.env.AOR_API_KEY, });
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Say hello in three words."}],
)
print(response.choices[0].message.content)
Or with curl:
curl https://api.redactron.ai/v1/chat/completions \ -H "Authorization: Bearer $AOR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-5.6-sol","messages":[{"role":"user","content":"Hello"}]}'
Pass stream=True and read chunks as they arrive. A stream that fails
midway is reported as a failed request, not as a short successful one, so you never have
to guess whether the text you got is complete.
stream = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Count to five."}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)
Use the provider's own model name — gpt-5.6-sol — not an African Open
Router alias. The console catalog is the reference list of what you can call and what it
costs; the pricing page shows current rates.
| Status | Code | What to do |
|---|---|---|
| 401 | invalid_token | The key is wrong, revoked, or not published yet. Check that you sent
Authorization: Bearer <key>. |
| 400 | invalid_request | The body failed schema validation — usually a missing
model, an empty messages list, or a model name with stray
whitespace in it. |
| 402 | wallet_denied | Your balance does not cover the request's worst-case cost. Top it up. |
| 404 | model_unavailable | The model is not in your workspace's catalog. |
| 429 | — | Rate limited at the edge, before the gateway ever sees the request. This
one is not JSON: the body is error code: 1015
as text/plain, and the wait is in the
Retry-After header, in seconds. Detect 429
from the status code, not from the body — every other row here uses the
JSON envelope above. |
| 503 | provider_unavailable | The upstream provider failed. Retrying is safe — you are not charged for a request that produced nothing. |
Before we call the provider we reserve the request's worst-case cost against your balance. When it finishes we settle the real amount and return the difference. A request refused before it reaches a provider costs nothing. Every settled request appears in the console with its token counts and its exact charge.
Create the new key first, deploy it, then revoke the old one — in that order, so nothing is ever running for even a moment without a valid credential.
[email protected]. Include the
request_id from the error body; it is the fastest way for us to find out
what happened to one specific request.