API
API — connect your software to AICLOUD
If you already have an application with us, this is how your other programs talk to it — the warehouse system, the accounting package, your website. Plus access to the AI models, paid from your credits. Written so you can hand this page to whoever maintains the other program.
Last revised: 2 September 2026
What it does
Two entrances, both using the same key. You choose at issue time which of them a key may use — or both.
- AI models. Your program sends a question and gets an answer from a language model. The cost comes out of your credits with us — no contract with the model vendor and no vendor key.
- A bridge to your application. Another system calls the application you built with us through our address. You get rate limiting, a log, and a signature that proves a call really came from us.
Getting started
Two minutes. Keys are issued by the owner or an administrator of the account — members and viewers cannot, because a key spends the whole account’s credits and works without signing in.
- Sign in to the portal and open API from the menu.
- Press “Issue a key”: give it a name, pick the project, choose what it may do.
- The key is shown once. Save it immediately — we do not keep it and it cannot be shown again. A forgotten key is revoked and replaced.
- Try it with the first command below.
The address and the key
Everything goes through one address. The key travels in the
Authorization header, exactly as in most APIs you already know.
curl https://aicloud.bg/api/v1/me \
-H "Authorization: Bearer YOUR_KEY"
{
"key": {
"name": "Warehouse system",
"masked": "ak_live_…f3c9",
"scopes": ["ai"],
"project": "43baa9f08a20"
},
"balanceCredits": 4820,
"limits": { "perMinute": 60, "perDay": 5000 }
}
Which models are offered
Your program asks for the list rather than hard-coding it. The prices in the answer are yours — what will actually be charged, not the vendor’s price.
- Prices are in micro-credits per 1000 tokens. 1000 micro-credits = 1 credit.
- A token is roughly three to four characters. A medium question with its answer is a few hundred tokens.
- Anthropic models are offered, because this entrance speaks their format. If you need another vendor, write to us.
curl https://aicloud.bg/api/v1/models \
-H "Authorization: Bearer YOUR_KEY"
{
"models": [
{
"model": "claude-haiku-4-5",
"contextWindow": 200000,
"inputPricePer1kMicro": 180,
"outputPricePer1kMicro": 900
}
]
}
One AI call
The body is the one Anthropic accepts — if your program already works with their API, you change the address and the key and nothing else. The answer comes back exactly as it arrived, with nothing removed.
max_tokenscaps the answer. We do not allow more than 4096, which keeps the most expensive possible call predictable.- Streaming (
"stream": true) is not supported, and the request is refused in words rather than silently changed. - A call has 25 seconds. If the model has not answered by then you get an error, not an open-ended wait.
curl https://aicloud.bg/api/v1/ai/messages \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5",
"max_tokens": 300,
"messages": [
{ "role": "user", "content": "Summarise this complaint in one sentence: ..." }
]
}'
X-AICLOUD-Cost-Micro: 9
X-AICLOUD-Charged: 1
What it costs
You pay what the call cost, plus a 20% margin. The bill is made after the
answer, from the real token counts in it — nothing is deducted in advance. Before
we send the request, though, we check that your balance covers its most expensive
possible outcome (your text plus the full max_tokens). If it does
not, we refuse straight away rather than leave you with an unpaid bill.
- What was taken is visible immediately in the response headers and on the “API” screen in the portal. Header names are case-insensitive — most clients hand them back lowercased.
- If your credits do not cover the most expensive outcome of a request, it is refused before it is made — nothing is spent and no debt builds up. The answer says how many credits are needed and how many you have.
- If you use prompt caching, cached tokens are billed too — writing to the cache at 1.25× the input price, reading from it at 0.1×. The discount is real, but it is not zero.
- Each key can carry a monthly cap in credits. When it is reached only that key stops; the others keep working.
- The bridge to your application costs no credits. You already pay for the project’s hosting.
input tokens 16 × 150 micro-credits / 1000 = 2.40
output tokens 6 × 750 micro-credits / 1000 = 4.50
────
cost 6.90 → 7 micro-credits
with the 20% margin 9 micro-credits
(= 0.009 credits)
The bridge to your application
Another system calls your application through our address. The point is that we stand between the two: a key you revoke with one button, rate limiting, and a log of who called when.
- The address is declared in the portal, on the API screen, per project.
- Only
https://and only a domain name — not a numeric address. - Everything after the project id is appended to your address as it is, query string included.
curl https://aicloud.bg/api/v1/p/43baa9f08a20/orders \
-H "Authorization: Bearer A_BRIDGE_KEY"
↓ reaches your address
https://your-application.com/orders
Why we ask you to prove the address is yours
A declared address does not work straight away. First you show the domain is yours — otherwise anyone could enter someone else’s site and hammer it in our name and from our address. Done once, in a minute.
- The portal shows you a string of the form
aicloud-verify-…. - Make
https://your-address/.well-known/aicloud-gateway.txtreturn that string as plain text. - Press “Prove ownership”. Done.
- Changing the address clears the proof and it is done again — ownership proved once for one domain does not open the door to the next.
Make /.well-known/aicloud-gateway.txt return this text
as plain text: aicloud-verify-xxxxxxxx
How your application knows it is us
Every bridge call carries a signature. Your application computes the same signature with the shared secret from the portal and compares — so a stranger who guesses your address cannot pass for us.
- The time, the method, the path and the hash of the body are signed — not just the body. One signature therefore cannot be reused for a different path.
- The path is exactly the one your server receives — query string included, encoded as it travelled. In Node that is
req.urluntouched: do not decode it and do not strip the query before computing the signature. - If your address has a prefix (
https://your-site.com/api), that prefix is part of the signed path too — just as it is part of the request you receive. - The secret is visible in the portal at any time and is replaced with a button. The old one stops working immediately.
X-AICLOUD-Signature: t=1788332240,v1=5c4afbda789bcceb…
X-AICLOUD-Timestamp: 1788332240
X-AICLOUD-Project: 43baa9f08a20
X-AICLOUD-Caller-Ip: 78.47.88.53
User-Agent: AICLOUD-Gateway/1
import { createHmac, createHash, timingSafeEqual } from 'node:crypto';
function verify(req, body, secret) {
const [t, v1] = req.headers['x-aicloud-signature']
.split(',').map(part => part.split('=')[1]);
// An old signature is not accepted: that is what the signed time is for.
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const hash = createHash('sha256').update(body).digest('hex');
const payload = `${t}.${req.method}\n${req.url}\n${hash}`;
const ours = createHmac('sha256', secret).update(payload).digest('hex');
return ours.length === v1.length
&& timingSafeEqual(Buffer.from(ours), Buffer.from(v1));
}
What does NOT reach your application
The request is handed on stripped. Not out of caution for us, but for you: an application that receives other people’s cookies and keys writes them into its own log.
- The key. The
Authorizationheader stays with us. Your application never sees the key it was called with. - Cookies. In neither direction — including
Set-Cookiefrom your application back to the caller. - The headers of our own entrance (
Host,X-Forwarded-*). They describe us, not the request, and would mislead you about where the call came from. - Only these are passed on:
Content-Type,Accept,Accept-Language,Idempotency-Key,X-Request-Id.
Limits
The numbers apply to everyone, ourselves included. If they get in the way of real work, write to us — they are raised, not worked around.
| What | How much | Why |
|---|---|---|
| Requests per key | 60 a minute, 5000 a day | A leaked key is only expensive when nobody is counting. |
| Requests per account | 120 a minute | So the line above cannot be sidestepped with ten keys. |
| Request size | 256 KB | Large files do not go through here, and we say so rather than fail quietly. |
| Response size | 1 MB | The same, in the other direction. |
| Time per call | 25 s for AI, 20 s for the bridge | After that you get an error, not an endless wait. |
| Live keys per account | 20 | Twenty keys are more than one account can keep track of. |
When something does not work
Every error carries a short code for the program and a sentence for the
person. The code is in the code field — read that, not the text,
which may be reworded.
- You will never get a 403 or a 404 from us. The network in front of the site turns both into a page instead of an answer, so refusals come out as 401 or 400 — with the precise reason in
code.
| Status | Code | What it means |
|---|---|---|
| 401 | bad_key |
The key is wrong, revoked, expired or not allowed to do this. Issue a new one in the portal. |
| 401 | wrong_project |
The key belongs to a different project. Each key belongs to one. |
| 401 | ip_not_allowed |
The key is locked to other addresses. Change the list in the portal. |
| 401 | account_blocked |
Access to the account is suspended. Get in touch. |
| 400 | bad_json |
The body is not valid JSON. |
| 400 | unknown_model |
No such model. The names are at /v1/models. |
| 400 | model_not_allowed |
That model is not offered. The list is at /v1/models. |
| 400 | stream_unsupported |
You sent "stream": true. Drop it — there is no streaming. |
| 400 | not_found |
No such address. Check the path. |
| 400 | target_unverified |
The application address has not been proved in the portal yet. |
| 402 | no_wallet |
The account has no credit wallet. |
| 402 | insufficient_credits |
Not enough credits for this request. Top up in the portal — nothing was spent. |
| 402 | unpaid_calls |
Earlier calls are still unpaid. Top up and they settle by themselves. |
| 402 | balance_unavailable |
The balance cannot be checked right now. Try again shortly. |
| 402 | key_limit_reached |
This key has reached its monthly cap. |
| 409 | — | Your application answered 403 or 404. The real number is in X-AICLOUD-Upstream-Status. |
| 413 | too_large |
The request is over 256 KB. |
| 429 | rate_limited |
Too many requests. Wait the seconds in Retry-After. |
| 502 | model_error |
The model refused the request. Its own reason is in detail. Not billed. |
| 502 | target_unreachable |
The bridge did not reach your application — usually a wrong or unreachable address. |
| 502 | response_too_large |
Your application returned more than 1 MB. |
| 503 | gateway_off |
The entrance is temporarily switched off by us. Try again shortly. |
| 500 | internal |
Our fault. If it keeps happening, tell us. |
Security — what we do and what we ask of you
A key is a string that sits inside someone else’s program, probably for years. So we have put everything we can around it — and two things are up to you.
- On our side: the key is stored only as an irreversible hash. A leaked database gives nobody a working key.
- On our side: the log keeps what was asked, how it ended and what it cost — never the content of your request and never the key.
- On our side: a bridge request never travels to an internal network, even if the domain is repointed there after it was proved. It is checked on every call, not once.
- On your side: treat the key like a password — in an environment variable, not in the code and not in the repository.
- On your side: if you have a fixed address, put it in the key’s allowed-addresses list. Then a stolen key does not work from anywhere else.
- More on the measures: Data security.
Frequently asked questions
Do we need a programmer?
For the AI entrance, not necessarily: whoever maintains your other program can usually make it send a request. The bridge needs someone to place the proof file and check the signature. If your application was built with us, that is one sentence to the studio agent.
Can I see my key again?
No, and that is deliberate. We hold only its irreversible hash — nobody, ourselves included, can recover it. A forgotten key is revoked with one button and replaced.
What if the key leaks?
You revoke it in the portal and it stops on the very next call. This is why you should issue a separate key per program — then revoking stops one, not all of them.
Do I pay for failed calls?
No. Only what the model actually processed is charged. A refused request, exhausted credits, an exceeded limit — none of it costs credits.
Can the API read and change the data in my project?
Only through your own application, and only what it allows. We do not open a door to your database — the bridge hands the request to your code and your code decides.
Issue your first key
From the portal, on the “API” screen. Two minutes, and it costs nothing until you make the first call.