Skip to content

Account

The /v1/account surface is your self-service management area — profile, usage history, API keys, connected integrations, and account settings.

Session authentication, not an API key

This is a credential-management surface, so it requires a logged-in session — the companions_session cookie set when you sign in (or the equivalent Authorization: Bearer <session token>). An API key is rejected with 401 here. This is deliberate: a key baked into a script must not be able to enumerate your other credentials or mint new ones. In practice these endpoints back the account dashboard.


Profile

GET /v1/account/me

Return the logged-in user's profile. A 401 means you are not logged in.

curl https://api.humx.ai/v1/account/me \
  -H "Authorization: Bearer $COMPANIONS_SESSION"
import os, requests

r = requests.get(
    "https://api.humx.ai/v1/account/me",
    headers={"Authorization": f"Bearer {os.environ['COMPANIONS_SESSION']}"},
)
r.raise_for_status()
print(r.json())
const res = await fetch("https://api.humx.ai/v1/account/me", {
  headers: { Authorization: `Bearer ${process.env.COMPANIONS_SESSION}` },
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
console.log(await res.json());
const res = await fetch("https://api.humx.ai/v1/account/me", {
  headers: { Authorization: `Bearer ${process.env.COMPANIONS_SESSION!}` },
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const me = await res.json();

Response 200

Field Type Description
id string User id.
email string Account email.
name string Display name.
email_verified boolean Whether the email is verified.
balance number Current balance.
created_at string ISO-8601 timestamp.

Usage

GET /v1/account/usage

Your engine runs, newest first, each with the net cost and token totals the billing ledger recorded for it. Cursor-paginated.

Parameter In Type Description
limit query integer Page size, 1–200 (default 50).
before query string Pass the oldest row's created_at to fetch the next page.

Response 200 — an array of runs.

Field Type Description
id string Run id.
kind string Run kind.
mode string Completion mode, if applicable.
status string Terminal status.
cost number | null Net ledger cost of the run, refunds netted out. null when the run recorded nothing.
tokens_prompt integer | null Prompt tokens, summed over the run's charges.
tokens_completion integer | null Completion tokens, summed over the run's charges.
created_at / finished_at string Timestamps.

cost is nullable — and null is not 0

This is a breaking change: a client that types cost as a plain number breaks on null. null means the run has no ledger rows at all — nothing was recorded, e.g. a run that died before its first billable call. 0.0 means a charge was recorded and netted to zero: a fully refunded failed run, or a free model, whose call now posts a real 0 charge with its token counts intact. Rendering an unrecorded run as $0.00 claims a fact the ledger never recorded. tokens_prompt and tokens_completion are null on the same footing — not recorded, rather than zero.

A page shorter than limit is the last one.


API keys

GET /v1/account/keys

List your active keys — fingerprints (key_prefix) only, never plaintext.

POST /v1/account/keys

Mint a new key. The plaintext key is returned exactly once — copy it now.

Field Type Required Description
label string An optional human label.
curl https://api.humx.ai/v1/account/keys \
  -H "Authorization: Bearer $COMPANIONS_SESSION" \
  -H "Content-Type: application/json" \
  -d '{ "label": "ci-pipeline" }'
import os, requests

r = requests.post(
    "https://api.humx.ai/v1/account/keys",
    headers={"Authorization": f"Bearer {os.environ['COMPANIONS_SESSION']}"},
    json={"label": "ci-pipeline"},
)
r.raise_for_status()
print(r.json()["key"])   # shown once — store it now
const res = await fetch("https://api.humx.ai/v1/account/keys", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.COMPANIONS_SESSION}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ label: "ci-pipeline" }),
});
const { key } = await res.json();   // shown once — store it now
const res = await fetch("https://api.humx.ai/v1/account/keys", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.COMPANIONS_SESSION!}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ label: "ci-pipeline" }),
});
const { key } = (await res.json()) as { key: string };

Response 200

Field Type Description
id string Key id (use it to revoke).
key string The plaintext key — shown once.
key_prefix string The fingerprint shown in listings.
label string Your label, if set.
created_at string ISO-8601 timestamp.

You may hold up to 5 active keys; a 6th returns 409.

DELETE /v1/account/keys/{key_id}

Revoke a key you own. Returns 204; an unknown or already-revoked key returns 404.


Integrations

Integrations are OAuth clients connected to your account — MCP clients like Claude Code or Codex that signed in through the OAuth flow.

GET /v1/account/integrations

List connected clients, one row per client.

Field Type Description
client_id string The client id.
client_name string The client's registered name.
scopes string[] Granted scopes.
granted_at string When consent was granted (disambiguates repeat installs).

DELETE /v1/account/integrations/{client_id}

Revoke a client's consent and all tokens minted under it. Returns 204.

Note

A just-revoked token can keep working for up to ~45 seconds while a cached authorization verdict expires.


Account settings

Account-wide defaults applied to every run unless a single completion overrides them via settings.

GET /v1/account/settings

Return your resolved settings — every key present, defaults filled in.

Field Type Default Description
zdr boolean false Zero Data Retention. Governs where your data is allowed to go — model providers and tool vendors. When true, every run uses only providers that do not retain prompt/completion data, so some models are unavailable and a run against one fails rather than falling back. Tools whose vendor is not vetted for it are not run: web search is dropped while ZDR is on, and naming such a tool explicitly is a 422. It does not change how long we keep your run's content — see collecting your result.
web_search boolean false Simple web search — the quick lookup. When true, personas may search the web and cite live sources (adds provider search cost).
budget_guard boolean true Pre-flight cost check. When true, a run is priced before it is enqueued and one whose expected cost is above your balance comes back 402 carrying the estimate, your balance and the shortfall — instead of starting, spending down to zero part-way through and billing you for the work already done. Set false to skip the check and run anyway.

What budget_guard will not do

Only the expected cost is compared, never the top of the estimate's range, so an ordinary run is not refused for a worst case it will not reach. A run the estimator cannot price — and any error inside the estimator itself — is always let through: a refusal we cannot justify is not a refusal. With the guard off you keep the per-call balance check that has always applied during a run, so a run can stop half-finished. A single completion can override the account default for one call with settings.budget_guard. To see the same price yourself before sending, use completion → estimating a run.

PUT /v1/account/settings

Patch your settings. Only fields present in the body are written; omit a field to leave it unchanged. Returns the full resolved object.

curl -X PUT https://api.humx.ai/v1/account/settings \
  -H "Authorization: Bearer $COMPANIONS_SESSION" \
  -H "Content-Type: application/json" \
  -d '{ "zdr": true, "web_search": true }'
import os, requests

r = requests.put(
    "https://api.humx.ai/v1/account/settings",
    headers={"Authorization": f"Bearer {os.environ['COMPANIONS_SESSION']}"},
    json={"zdr": True, "web_search": True},
)
r.raise_for_status()
print(r.json())
const res = await fetch("https://api.humx.ai/v1/account/settings", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.COMPANIONS_SESSION}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ zdr: true, web_search: true }),
});
console.log(await res.json());
const res = await fetch("https://api.humx.ai/v1/account/settings", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.COMPANIONS_SESSION!}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ zdr: true, web_search: true }),
});
const settings = (await res.json()) as {
  zdr: boolean;
  web_search: boolean;
  budget_guard: boolean;
};
Field Type Description
zdr boolean Set the account-wide ZDR default.
web_search boolean Set the account-wide simple web-search default.
budget_guard boolean Set the account-wide pre-flight cost check default. Send false to turn it off.