Skip to main content

Before you start

You need three things, and the first request fails in a documented way if any of them is missing:
1

A verified account

Sign up and verify your email address at app.uniblock.dev.
2

A workspace with credit

Credit is prepaid, so a workspace with a zero balance refuses requests before they reach a provider. The workspace owner buys credit on the Billing screen. See buying credit.
3

An API key

Mint one on the Keys screen. The key appears once and we keep only a hash, so we cannot show it to you again or recover it for you. Copy it before you leave the screen. See authentication.

Set the base URL

Point your existing OpenAI client at https://ai.uniblock.dev and give it a Uniblock API key. Nothing else about your code changes.
Base URL
Two forms of the same address, and which one you use depends on your client: The SDKs append the endpoint path themselves, which is why their setting carries the /v1 and nothing after it.

Send the request

Every request to the API carries your key in an Authorization header using the Bearer scheme. A missing header, a scheme other than Bearer, a key of the wrong shape, and a key we reject are all answered with 401.
Keep the key out of your source. Read it from the environment, as above.
The response body is the OpenAI chat completion shape. Your request body is forwarded as you sent it and is neither parsed nor rebuilt on the way through, so any parameter your client already sends keeps working.

Read the response headers

Every response carries the id for that request, on two headers with the same value:
Every response carries the same id on two headers: x-uniblock-request-id, which is ours, and x-request-id, which is the one the official OpenAI SDKs surface on their error objects. Every error envelope repeats it as request_id. Quote it when you ask us about a request. Without it we are guessing at which of your requests you mean.
Token counts do not ride back on a header on a non-streamed reply today. They are read on our side and turn into your usage record, and they reach you on the wire only on a streamed reply, as the comment line described below. Your token counts for a non-streamed request are in Activity rather than in a response header.

Stream the response

Set stream: true and read the SSE stream exactly as you would from OpenAI. Before the final data: [DONE] line, we splice in one SSE comment line carrying the token counts. The SSE specification requires a parser to ignore comment lines, so an OpenAI SDK skips it without being taught about it.
The raw stream ends like this. The comment line is the one starting with a colon:
Annotated SSE tail
Streaming covers the usage line’s fields and what happens if a stream outlives the credit paying for it.

The two first-run failures

Both arrive in the OpenAI error envelope, so your existing error handling parses them. Branch on type and code rather than on the message text: the fields are the contract and the sentences are prose. Every error on the API, at every status, is one JSON object with a single top-level error key. An OpenAI client parses it with the error handling it already has.
Error envelope
Branch on type and code. Both are stable. message is prose and may change. The type values are invalid_request_error, authentication_error, permission_error, not_found_error, rate_limit_error, api_error, insufficient_quota, and server_error.

No key, or a key we do not recognise: 401

Sending no Authorization header at all:
401
Sending a string that is not shaped like a Uniblock key, which is the answer you get if you paste a key from another provider:
401
Sending a correctly shaped key that we do not accept returns "Incorrect API key provided." in the same envelope. An unknown key and a revoked key get that one identical sentence on purpose, because confirming that a stolen key was once real helps whoever stole it and helps nobody else.

Not enough credit: 402

A request is priced and held against your balance before it reaches a provider, so a workspace that cannot cover the hold is refused rather than served and billed. The type is insufficient_quota, which is the value an OpenAI client already has a branch for, and the code is insufficient_credit:
402
The way out is buying credit. Nothing is charged for a request we refuse.

Catch errors in your client

The OpenAI SDKs raise their normal status errors, so the catch you already have works. Read type and code off the body:

Next

OpenAI compatibility

Which endpoints exist today, and what a call to one that does not returns.

Errors

Every shipped code, its status, and what to do about it.