Developer documentation
Build on our API
An OpenAI-compatible endpoint you can point an existing SDK at, and a write-only link for delivering environment variables into a project. If you already call OpenAI, moving across is one line.
Getting started
Our gateway speaks the same wire format as OpenAI, so you do not need a new SDK or a new mental model. Install the official client, point its baseURL at us, and use the key we issued you in place of an OpenAI key.
- 1Ask us for an API key. It starts with vii_live_ and is shown to you once.
- 2Set baseURL to https://visionitinfra.com/v1 in your OpenAI client.
- 3Call the models your key is enabled for. That is the whole integration.
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.VISIONIT_API_KEY, // vii_live_...
baseURL: 'https://visionitinfra.com/v1', // the only line that changes
});
const reply = await client.chat.completions.create({
model: 'gpt-4.1-mini',
messages: [{ role: 'user', content: 'Write one line about exams.' }],
});
console.log(reply.choices[0].message.content);Authentication
Every request carries your key as a bearer token. There is nothing else to sign and no timestamp to compute.
Authorization: Bearer vii_live_xxxxxxxxxxxxxxxx
Keep it server-side
A key spends real credit on your plan. Never ship one in a browser bundle, a mobile app, or a public repository — anyone who reads it can spend your balance. If one leaks, tell us and we will revoke it; revocation takes effect on the next request.
We store only a hash of your key, so we cannot email it back to you. A lost key is replaced, not recovered.
Chat completions
/v1/chat/completionsTakes and returns exactly what OpenAI's endpoint does. Anything the official SDK sends is passed through, and the response is returned untouched — including usage, so your own token accounting still works.
| Field | Type | Notes |
|---|---|---|
| model | string | Required. Must be enabled on your key — see Models. |
| messages | array | Required. The standard role/content shape. |
| stream | boolean | Optional. See Streaming. |
| max_tokens | number | Optional, but it makes our credit hold more accurate. |
| temperature, top_p, … | various | Passed through unchanged. |
Streaming
Set stream: true and the reply arrives as server-sent events, token by token, exactly as it would from OpenAI. Our proxy does not buffer, so the first token reaches you as soon as it exists.
const stream = await client.chat.completions.create({
model: 'gpt-4.1-mini',
messages: [{ role: 'user', content: 'Explain photosynthesis.' }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
}You do not need to ask for usage reporting — we add it to the upstream request ourselves so streamed calls are metered like any other. If you disconnect mid-stream, the work has already been done upstream and is still billed.
Models
/v1/modelsReturns the models your key is enabled for. Each key carries its own list, so this is the authoritative answer to “what can I call?” — a model outside it is refused with a 403.
curl https://visionitinfra.com/v1/models \ -H "Authorization: Bearer $VISIONIT_API_KEY"
Need one that is not on your list? Ask us — the cheaper models cost a fraction of the larger ones, so the right choice is usually a pricing conversation as much as a technical one.
Errors
Errors come back in OpenAI's own shape, so your SDK's existing error handling reads them without changes.
{
"error": {
"message": "This plan has no credit left. Top it up to keep going.",
"type": "insufficient_quota",
"param": null,
"code": null
}
}| Status | Meaning | What to do |
|---|---|---|
| 401 | The key is missing, unknown or revoked. | Check the Authorization header. Ask us for a new key if yours was revoked. |
| 402 | The plan is out of credit. | Nothing was sent upstream and nothing was charged. Top up and retry. |
| 403 | That model is not enabled on your key. | Call GET /v1/models to see what is. |
| 429 | Too many requests for this key. | Back off and retry. Your per-minute limit is set per key. |
| 502 | We could not reach the model provider. | Transient. Retry with backoff. |
A 402 costs you nothing
The credit check runs before anything is forwarded, so a refused request never reaches the provider and never appears on your bill.
Usage and credit
Your plan carries a token balance, visible any time under Billing in your portal, along with what has been used this period.
Balance is drawn down per request based on what the call actually consumed — prompt tokens and completion tokens, priced by the model you chose. A short prompt on a small model costs a fraction of a long one on a large model, so choosing the smallest model that does the job is the single biggest lever on how far a top-up goes.
When the balance runs out
Requests are refused with a 402 until the plan is topped up. Nothing is silently cut off mid-conversation and no overage is billed — you simply stop, and start again when the next top-up is paid.
Environment delivery
Every project in the portal can issue a delivery link — a single URL you can post a .env to. The variables land in the project encrypted, without anything needing a login, which means a build agent or an assistant can deliver credentials without being given an account.
/api/v1/env-ingest/{token}curl -X POST "https://visionitinfra.com/api/v1/env-ingest/vii_env_xxxx" \ -H "Content-Type: text/plain" \ --data-binary @.env.production
JSON works too, if that suits your tooling better:
{ "content": "DATABASE_URL=postgres://...\nNODE_ENV=production" }A link can only write
It cannot read back what is already stored, and it is pinned to one project and one named set when it is created. A link that ends up in a build log can add variables but can never leak the ones already there. Links are revocable and can be given an expiry.
Each delivery replaces the whole set rather than merging into it, so variables you removed do not linger. The response tells you which keys landed — never their values.