ITS INCOM AI ITS INCOM AI docs

API reference

Authentication

API keys for the /v1 API, user tokens for the app API: how to get them, how to use them, what the errors mean.

Last updated: 2026-10-03

There are two APIs, and each has its own credential. Both go in the same header, Authorization: Bearer …, but they are not interchangeable.

API Base URL Credential For
Developer API, OpenAI-compatible https://api.ai.itsincom.org/v1 API key, sk-… your servers, scripts, the OpenAI SDKs
App API https://my.ai.itsincom.org/api/v1 user token, from sign-in document search (RAG), chat sessions

An API key sent to the app API gets 401, and so does a user token sent to /v1.

API keys

Create one

In the dashboard: API keys → give it a name, choose its default tier → Create. The key is shown once: copy it straight away. We keep only a hash of it, and its first characters so you can recognise it in the list.

bash
export API_KEY="sk-…"

Use it

bash
curl https://api.ai.itsincom.org/v1/models \
  -H "Authorization: Bearer $API_KEY"

With the OpenAI SDKs, pass the key as the API key and https://api.ai.itsincom.org/v1 as the base URL: see the Quickstart.

Tier and zones of a key

A key has a default tier, chosen when you create it. The dashboard cannot change it later: create a new key, or override the tier of a single request with the X-Siati-Tier header.

bash
curl https://api.ai.itsincom.org/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "X-Siati-Tier: fast" \
  -H "Content-Type: application/json" \
  -d '{"model": "gemma-4-26b", "messages": [{"role": "user", "content": "Hello"}]}'

Every key may use any of the four tiers. An unknown value returns 400. What a tier changes is in Tiers.

A key may also be limited to some zones; by default it can use all the zones ITS INCOM AI offers. A request never leaves the zones of its key. The dashboard has no setting for this: write to segreteria@itsincom.it. See Zones.

Revoke or rotate

Dashboard → API keys → Revoke. It applies from the next request: there is no grace period. To rotate a key, create the new one, move your code to it, then revoke the old one.

A key can also carry an expiry date, set by an administrator. After that date it is refused.

App API: user tokens

The app API acts as a signed-in user, not as a key. It is the one you need for document search, which does not exist under /v1: a call to https://api.ai.itsincom.org/v1/rag/… answers 404.

Sign in

bash
curl https://my.ai.itsincom.org/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "…"}'

The answer carries two tokens:

Field What it is
access_token goes in Authorization: Bearer on every app API request
refresh_token gets you a new pair when the access token expires
access_expires_in_seconds, refresh_expires_in_seconds how long each one lasts
user the account: id, email, whether the email is verified

token and expires_in_seconds repeat the access token and its lifetime, for older clients.

bash
export USER_TOKEN="eyJ…"

curl https://my.ai.itsincom.org/api/v1/auth/me \
  -H "Authorization: Bearer $USER_TOKEN"

Sign-in answers 429 after 10 attempts in a minute from the same address. Until the email address is confirmed, most app API endpoints answer 403 with code: email_unverified.

Refresh

bash
curl https://my.ai.itsincom.org/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJ…"}'

You get a new pair, with the same fields as sign-in. The refresh token you sent stops working: keep the new one. If an already used refresh token is sent again, we treat it as stolen and revoke every refresh token of the account, so the next refresh fails and the user has to sign in again.

Sign out

bash
curl https://my.ai.itsincom.org/api/v1/auth/logout \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "eyJ…"}'

This revokes the refresh token. The access token cannot be revoked: it stays valid until it expires, so delete it on your side.

Errors

API key

Always 401, with type: invalid_request_error and code: invalid_api_key. The message says why:

message Cause
missing Authorization header no Authorization: Bearer … header
invalid api key format the value is not shaped like a key (a user token, for example)
invalid api key the key does not exist or has been revoked
api key expired the key is past its expiry date
account disabled the account the key belongs to has been disabled
json
{
  "error": {
    "message": "invalid api key",
    "type": "invalid_request_error",
    "code": "invalid_api_key"
  }
}

An unknown X-Siati-Tier gets 400 with the message unknown tier: ….

User token

The body is {"error": {"code": …, "message": …}}. Read code: some messages are in Italian.

HTTP code Cause
401 unauthorized token missing, invalid or expired (refresh it), or account disabled
403 email_unverified the email address is not confirmed yet
401 invalid_credentials sign-in: wrong email or password
403 account_disabled sign-in: the account is disabled
401 invalid_refresh_token refresh: token unknown, already used, revoked or expired
422 missing_refresh_token refresh: no token in the body

Everything else is in Errors.