API
The Ingot server powers the portal, the IDE account and the model gateway. In the browser the portal proxies these paths, so the website calls them same-origin.
Basics
- Errors are
{ "error": "<code>", "message": "<localized text>" }. Language comes from ?lang=en|he|es, then Accept-Language, then English.
- Auth (any of): the browser session cookie,
Authorization: Bearer ingot_at_... (IDE session) or Authorization: Bearer ingot_pat_... (personal token).
Models (chat-completions compatible)
Call with Authorization: Bearer <IDE access token | personal token>; cookies are rejected.
| Method | Path | Notes |
|---|
| GET | /v1/models | models on your plan: { object: 'list', data: [{ id, name, context_window, pricing, available }] } |
| POST | /v1/chat/completions | standard body (model, messages, tools, tool_choice, temperature, top_p, max_tokens, stop, stream). Optional header x-ingot-feature (agent, chat, edit, autocomplete) for the usage breakdown. Body limit 10 MB. |
| POST | /v1/audio/transcriptions | multipart file (audio, max 25 MB) and model: ingot-transcribe → { text } |
curl https://<server>/v1/chat/completions \
-H "Authorization: Bearer $INGOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "model": "ingot-fast", "messages": [{ "role": "user", "content": "Hello" }] }'
Limit errors: 402 token_allowance_exhausted, 402 spend_cap_reached, 429 rate_limited. Model errors: 404 model_not_found, 403 model_not_in_plan, 503 model_unavailable, 502 upstream_rejected, 502 all_providers_failed.
Account
| Method | Path | Notes |
|---|
| GET | /api/health | { status, database } |
| GET | /api/auth/providers | which sign-in methods are configured |
| POST | /api/auth/otp/request | { email, purpose?, name?, locale? } sends a sign-in code |
| POST | /api/auth/otp/verify | { email, code, next? } sets the session cookie |
| POST | /api/auth/sign-out | |
| GET / PATCH | /api/me | profile; PATCH { name?, theme?, locale? } |
IDE sign-in
| Method | Path | Notes |
|---|
| POST | /api/ide/handoff | browser session only; { url: "ingot://auth?code=...", expiresIn: 60 }, single use |
| POST | /api/ide/token | grants: handoff code, authorization_code (PKCE), refresh_token → { access_token, refresh_token, expires_in: 3600, refresh_expires_in: 2592000 } |
| POST | /api/ide/revoke | { token } |
| GET | /api/ide/sessions | signed-in IDEs |
| DELETE | /api/ide/sessions/:id | sign an IDE out |
| GET | /api/ide/status | { user, balance, activity } for the IDE account menu |
| POST / GET | /api/ide/activity | IDE heartbeat / activity of your IDEs |
| POST | /api/device/code | device sign-in: { device_code, user_code, verification_uri, expires_in: 600, interval: 5 } |
| POST | /api/device/token | poll with { device_code } until approved |
Usage and balance
Window parameters: days=1|7|30|90 (default 30), period=month, or from / to (YYYY-MM-DD, max 366 days). Optional model=<id>.
| Method | Path | Notes |
|---|
| GET | /api/usage | { totals, byDay[], byModel[] } |
| GET | /api/usage/models | per-model totals |
| GET | /api/usage/export | CSV |
| GET | /api/balance | { plan, period, tokens: { allowance, used, remaining }, spend } |
Keys, tokens, team, billing, settings
| Method | Path | Notes |
|---|
| GET / POST | /api/keys | your provider keys (family: claude, gpt, gemini, deepseek, custom); secrets are never returned |
| DELETE | /api/keys/:id | |
| GET / POST | /api/tokens | personal access tokens; the ingot_pat_... value is shown only on create |
| DELETE | /api/tokens/:id | revoke |
| GET / POST | /api/team | your team / create one |
| POST | /api/team/invites | { email, role: admin|member } |
| POST | /api/team/accept | { token } |
| PATCH / DELETE | /api/team/members/:id | change role / remove |
| GET | /api/billing | { plan, status, renewsAt } |
| POST | /api/billing/checkout | { plan: pro|team } → checkout URL |
| GET / PUT | /api/settings | account settings { data, version }; PUT merges top-level keys, null deletes, 64 KB cap |