Sign in
Docs
0%

Get started

Authentication

API tokens to start with, API keys for production servers, the scopes both hold, and the pattern for an app that acts as a person.

Every call carries Authorization: Bearer <token>. There are two ways to get that token:

API tokenAPI key
What you keepthe token itselfa client id and a secret
Lives7, 30, 90 or 365 dayseach exchanged token lives 15 minutes
Madein one click here, or in the consolein the console
Fortrying the API, scripts, cron jobs, CIservers that keep a secret

Both hold only the scopes they were given, both are revoked in the console, and both count against the same account.

API tokens: start here

Have a token? Manage tokens in the console

Signed in, Create a test token above makes one for your account in this browser: every read scope, valid seven days. It is selected in the reference's playground at once, so every page's Send and every code sample carries it. Copy it from the bar for your terminal:

export INORBIT_TOKEN="eyJ…"
curl -H "Authorization: Bearer $INORBIT_TOKEN" https://api.inorbit.hr/v1/me

For a token with a name, chosen scopes or a longer life, use API tokens and keys in the console (https://console.inorbit.hr/keys/). There you can also write what the token is for in plain words ("read the radar from a weekly cron job") and the platform's own model proposes a name, the scopes with a reason for each, and a lifetime. You check the proposal and create the token yourself; the model never creates one.

  • A token is shown once, when it is made. The platform keeps its name, scopes, expiry and last use, never the token; lose it and make another.
  • The test tokens this site makes live in this browser's storage only, and Forget removes one from here without revoking it.
  • An account holds up to twenty active tokens.
  • Revoking a token in the console refuses it within seconds, on every route.

API keys: for production servers

An API key is a client id and a client secret. You do not send the key itself on a call; you exchange it for an access token and send the token. The exchange is the OAuth 2.0 client credentials grant at the identity provider:

curl -u "$KEY_ID:$KEY_SECRET" https://auth.inorbit.hr/oauth2/token \
  -d grant_type=client_credentials \
  -d audience=iohr-api \
  -d scope="identity:read account:read"
{
  "access_token": "eyJ…",
  "token_type": "bearer",
  "expires_in": 899,
  "scope": "identity:read account:read"
}

Then, on every call:

Authorization: Bearer eyJ…

The token is a signed JWT with audience iohr-api and the scopes it was given. The gateway verifies the signature and the audience on every request, admits the call only when the token holds the route's scope, and hands it on with the identity inside; the services behind it never see the secret and never verify a token themselves.

Where keys come from

Keys are made and revoked in the console at https://console.inorbit.hr/keys/, for your personal account or for a team you own or administer. The secret is shown once, with this exchange filled in.

Scopes

A token made in the console or here holds the scopes ticked when it was made. A key holds the scopes ticked when it was made, and a token from a key holds the ones asked for in the exchange: scope is a space-separated list, any subset of the key's. Asking for a scope the key does not hold is refused with invalid_scope; a call to a route whose scope the token lacks is 403 forbidden. Scopes are fixed for life: to change them, make a new token or key and revoke the old one.

ScopeLets a token call
identity:readGET /v1/me: the caller as the gateway verified it
account:readGET /v1/accounts/me: the account, its plan, the key's name and last use
usage:readGET /v1/accounts/orgs/{org_id}/units and /usage, GET /v1/accounts/units/categories: the account's units and the price list
radar:readGET /v1/radar/digests, /v1/radar/digests/{id}, /v1/radar/items: the radar's published digests
events:readGET /v1/events/types, the event catalogue, and the account's events over MQTT (events/#)
webhooks:readGET /v1/webhooks/endpoints and the routes under it: the account's webhook endpoints and their deliveries; GET /v1/webhooks/inboxes and what the test inbox received
webhooks:writemaking, changing, testing, rotating and deleting endpoints, resending a delivery, and making or deleting the test inbox
domains:readGET /v1/accounts/orgs/{org_id}/domains and /domains/{domain}: the account's domains, their records and status
domains:writeadding, checking, confirming and removing the account's domains
trail:readGET /v1/trails/recordings and /recordings/{recording_id}: the account's trail recordings (RFC 0055)
trail:writeuploading trail recordings and deleting them, in the account the token belongs to
connections:readGET /v1/connections/kinds, the account's connections, their grants and history of uses, and GET /v1/connections/tools: the actions granted to this token
connections:writeadding, changing, pausing, testing and deleting the account's connections, and revoking a grant; granting is done by a person in the console
connections:usecalling a connection action a grant gives this token: POST .../connections/{connection_id}/actions/{action} or POST /v1/connections/tools/{name}
mcp:readover MCP, listing and calling the tools that only read
mcp:writeover MCP, the tools that change something (a connection action also needs connections:use)
mcp:generateover MCP, the tools that run a model: a generation or an embedding, counted against the account's budget

Any token may fetch GET /v1/openapi.json: the document for its plan, narrowed to the scopes it holds, so it lists exactly the operations that token may call. info.x-iohr-cut names the plan, the account, the scopes and a hash of the operations and schemas; two documents with the same hash are the same API. A signed-in person in several accounts adds ?account=<id> for a team's document (its plan); an account they are not in answers 403. iohr sdk generate (Generate an SDK) turns that document into a client with exactly the operations the credential may call. Every operation in the Reference names its scope. Each product opens to keys with scopes of its own as it is published.

Lifetime, rotation, revocation

  • An API token lives the days chosen when it was made. A token from a key lives fifteen minutes; fetch a new one before it expires. A call with an expired token is 401 unauthenticated.
  • To rotate, make a second key, move your fleet to it, then revoke the first. An account holds up to ten keys at once.
  • Revoking a key refuses new tokens at once, and the gateway refuses the tokens already issued from it within seconds. Revoking an API token works the same way.
  • Keep the secret out of code and logs. The platform's own logs carry the key id, the route and the status of a call, never a body and never a secret. Every answer carries x-request-id; log it on your side to find a call with us (Paging, retries and errors).

The exchange in three languages

const basic = Buffer.from(`${process.env.KEY_ID}:${process.env.KEY_SECRET}`).toString("base64");
const res = await fetch("https://auth.inorbit.hr/oauth2/token", {
  method: "POST",
  headers: { authorization: `Basic ${basic}`, "content-type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "client_credentials",
    audience: "iohr-api",
    scope: "identity:read account:read",
  }),
});
const { access_token } = await res.json();

An app that acts as a person

A key represents an account. An app that acts for a signed-in person (a mobile or desktop client) uses the authorization code grant with PKCE against the same identity provider, in the system browser, with audience=iohr-api on the authorization request, and then sends the resulting bearer token exactly as above. Registering such a client is a request to the operator today.

What the token carries

GET /v1/me shows it: subject (the key id for a key or API token, the person's id for a person), kind (client for a key or API token, person for a person), scopes, and the account the call counts against under org: the account a key belongs to, or a person's own. GET /v1/accounts/me answers the account itself, with its plan and, for a key, the name of the key or token and when it was last used.