Quickstart
Make a first chat completion against the gateway and read what comes back.
The gateway speaks the OpenAI chat-completions dialect over HTTP. If you already have code that talks to an OpenAI-compatible endpoint, the base URL and the key are the only two things that change.
Every sample on this page was run against a live deployment before it was published, and the responses below are the ones that came back.
Before you start
You need two things.
A base URL. It is https://api.impossiblecarrot.cc/api/v1, written out in
full in every sample on this site, so there is nothing for you to set.
That is a different hostname from the site you are reading this on, and
deliberately so. impossiblecarrot.cc is where your browser holds its login
cookie; api.impossiblecarrot.cc is a bearer-token surface that holds no
cookies at all. Keeping the two apart is why https://impossiblecarrot.cc/api/v1
does not route and is not going to — an API credential and a browser session
never travel to the same origin.
An API key. Inference keys start with sk-or-v1-. Sign in and create one on
the Account page — the plaintext is shown once, when it is created,
and never again. See Authentication for what the two key
classes are allowed to do.
Keep the key in the environment rather than in the command, so it does not end up in your shell history:
export CP_API_KEY="sk-or-v1-..."
The key is the only thing the samples read from your environment; on every code sample on this site it is the line highlighted in red.
Find a model to call
Model ids are author/slug. The catalogue is public — no key is needed to read
it — so the shortest way to get a valid id is to ask for one:
curl -s "https://api.impossiblecarrot.cc/api/v1/models" | head -c 200
{"data":[{"id":"impCC/DeepSeek-V4-Flash-0731","canonical_slug":"impCC/DeepSeek-V4-Flash-0731","name":"ImpCC: DeepSeek V4 Flash 0731 (abliterated)","created":1786677579,"description":"An abliterated (d
Read the id rather than copying one out of a document — including this one. The id above replaced a different one while these pages were being written, which is the most direct argument for the advice. This deployment serves exactly one routable model today; see Models and providers for that in full.
Your first request
curl -s "https://api.impossiblecarrot.cc/api/v1/chat/completions" \
-H "Authorization: Bearer $CP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "impCC/DeepSeek-V4-Flash-0731",
"messages": [
{ "role": "user", "content": "Reply with exactly: hello from the gateway" }
],
"max_tokens": 24
}'
That request returned 200 and this body:
{
"id": "gen-1786757875-5np6jh6ix9nh6n0h",
"object": "chat.completion",
"created": 1786757875,
"model": "impCC/DeepSeek-V4-Flash-0731",
"provider": "Stealth",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"native_finish_reason": "stop",
"message": {
"role": "assistant",
"content": "hello from the gateway",
"refusal": null,
"annotations": null,
"function_call": null,
"reasoning": null
},
"logprobs": null
}
],
"system_fingerprint": "vllm-0.0.0-pp4-bd4126a7",
"usage": { "prompt_tokens": 12, "completion_tokens": 5, "total_tokens": 17, "is_byok": false },
"service_tier": null
}
Read the response
choices[0].message.content is the answer. The rest of the envelope is what
makes a generation accountable after the fact:
id— the generation id, prefixedgen-. Quote it in a bug report; it is also the key forGET /generation, which reports what the call cost.model— the id that was actually served, which is worth checking against the id you asked for.provider— the display name of the endpoint that answered. On this deployment it readsStealth: the field is constrained to a fixed set of upstream provider names, our own endpoint has to borrow one of them, and the routing identity that actually selected it isimpcc. It is a placeholder standing in for a name the field cannot yet express, not the name of a third party who served your request.usage— prompt, completion and total tokens.total_tokensis what the charge is computed from; see Credits and usage.finish_reason—stopmeans the model stopped on its own.native_finish_reasoncarries the provider's own word for the same event, unmapped.
Three response headers carry the same identifiers, so a client can correlate a request even when it never gets to parse a body:
request-id: req-3p
x-generation-id: gen-1786757875-5np6jh6ix9nh6n0h
x-provider-name: Stealth
x-generation-id is set before anything can fail, so a generation that produced
no tokens at all still has an id you can quote.
When it does not work
Two failures account for most first attempts, and both were run to produce the bodies below.
No credential at all:
{"error":{"code":401,"message":"Missing Authentication header","metadata":{"error_type":"authentication"}}}
A model id that the catalogue does not hold:
{"error":{"code":404,"message":"No endpoints found for nonexistent/model.","metadata":{"requested":"nonexistent/model","resolved":"nonexistent/model","reason":"model_not_in_catalogue","error_type":"not_found"}}}
error.code always repeats the HTTP status. Errors lists every
status this API returns and what each one means.
Where to go next
- Authentication — key classes, and what each may call.
- Models and providers — id shapes and what the catalogue holds.
- Credits and usage — how a call is paid for and reported.