AICLOUD.BG

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.

Check that the key works
curl https://aicloud.bg/api/v1/me \
  -H "Authorization: Bearer YOUR_KEY"
Response
{
  "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.
The models and their prices
curl https://aicloud.bg/api/v1/models \
  -H "Authorization: Bearer YOUR_KEY"
Response
{
  "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_tokens caps 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.
Request
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: ..." }
    ]
  }'
Response headers — what it cost you
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.
A short call, worked out
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.
How it looks
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.txt return 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.
If your application is with us, tell the studio agent this
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.url untouched: 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.
What arrives at your end
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
Checking it (Node.js)
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 Authorization header stays with us. Your application never sees the key it was called with.
  • Cookies. In neither direction — including Set-Cookie from 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.