Documentation ▸

Errors

Problem details, and why a missing fact is never one.

An error is an RFC 9457 problem document, sent as application/problem+json:

{
  "type": "https://docs.gethimmel.com/errors/invalid-fact",
  "title": "Invalid fact",
  "status": 422,
  "detail": "booking_date must be a date",
  "instance": "/v1/check",
  "errors": [ { "fact": "booking_date", "code": "type" } ]
}

type names the problem, and is the thing to branch on: its address leads to the code's own row of the table below. errors names each field that was wrong, when there is one to name. Every response carries an X-Request-Id header; quote it when you ask us about a failed call.

The service's health check, GET /healthz, is the one answer that is no problem document: it says 200 and ok, or 503 and degraded with which part failed, in the same shape, for a monitor to read.

Not errors

A missing fact, an open question about who a recipient is, and a rule your rule owner has not confirmed are answers, never errors. They come back with HTTP 200 as undetermined_missing_facts or not_covered, because they are exactly what the check is about. So is a fact sent as null where a rule needs its value: it is named in missing, as a fact left out is. A 422 means the request was not in the documented shape: a fact of the wrong type, a body that does not parse, a query parameter the endpoint does not take. It never means "we do not know who received this gift".

Codes

TypeStatusWhen
invalid-fact422A fact is not of the type the rule set declares, or is not a fact it takes. An amount is refused in a currency ISO 4217 gives no decimals (currency), with a figure in its own currency or two in one (equivalents), and with a key money does not have (type); a setting's amount, in another currency than a rule set that reads it reads it in, with no figure in that one (currency). A number below zero the rule set does not declare signed (below_zero), and a code of more than 200 characters (format). A recipient that carries a key a customer does not have (unknown_key, the fact naming the key), a description beside an id (described_and_named), a resolution, a kind or a value of another kind (resolution, kind, type), or a value too long (too_long). A person, or the figure an approval was given for, sent with a value by a key made for an agent (not_the_keys): Himmel holds them for the agent
pii-in-facts422A fact other than a recipient, a provenance name or value, an actor value, transaction.ref, an execution report's ref or a decision's note_ref looks like an email address or an IBAN - or, on the MCP server, the Himmel-Run or Himmel-On-Behalf-Of header, named in errors[].field
invalid-request422The body or a parameter is not in the documented shape. A query parameter the endpoint does not take is refused rather than ignored, on every endpoint: errors[].field names it, with the code unknown_parameter. A reference longer than 200 characters - transaction.ref, a provenance name or value, actor.id or on_behalf_of, a report's ref, a note_ref, the MCP server's Himmel-Run and Himmel-On-Behalf-Of headers - is refused with string_too_long, naming the field. A tool of the MCP server given an argument it does not take refuses it with unknown_argument, rather than pass it on. A body that cannot be read at all is the same type with 400. A check that completes an action is refused where it says the action or a fact of it otherwise than the booking recorded (changed, naming the field, never its value), names another rule set's booking (other_rule_set), or is sent as a proposal (proposed). A check that corrects one is refused the same way where it says the action otherwise - its facts it may change - and where it changes nothing (unchanged) or completes too (both). An agent your account has not registered, named by one of your account's own keys in transaction.actor or given to a new key as its agent, is refused with unknown_agent: register it first
invalid-policy422A policy's files do not load, or are not named for your account
pii-in-policy422A policy's files hold an email address or an IBAN
invalid-document422An uploaded document is not a PDF, DOCX or Markdown file that can be read
unauthorized401No key, a malformed header, or a key that is not in use
insufficient-scope403The key lacks the scope the endpoint needs; required_scope names it. A key made for an agent gets it too, with the code agent_key, for what your whole account holds and for another agent's record: it reads its own agent's alone
not-a-member403Someone signed in to the console whom no account has added yet
names-withheld403A search of recipients by name (q) from a caller that is not shown names: every key, and people other than admins and ops
live-only403A request acting in test tried to change what your account has decided — its confirmed rules, settings or policies. Those are changed from live
rule-set-not-enabled403The rule set is not enabled for your account
unknown-rule-set404No rule set of that name
rule-version-not-found404The rule set has no such version
rule-version-not-in-force409A check named a version other than the one in force on its transaction's date, which answers it: in_force names that one, or is null where none is
not-found404Nothing with that id — or, for a mapping, that name — exists for your account; or the path is no path of the API
method-not-allowed405The path does not take that method: the Allow header names the ones it does. The MCP server takes POST alone
idempotency-conflict409The Idempotency-Key was used with a different body in the last 24 hours
not-a-proposal409The execution report is for a transaction that was never proposed, or is already closed. Or a check asks again about an action already taken: send the facts it lacked completing it as taken
answer-replaced409A decision was sent to an answer a later one replaced; standing names the answer to decide on. Or a check completes a booking another check already completed or asked about again: transaction_id names the booking to name instead, and standing its answer
action-not-taken409A decision was sent about an action that was never taken: it expired, or was reported not done. Or a check completes such an action, or asks about it again. Or a check completes one still being asked about as taken: it is asked about again, sent as proposed. Or such an action is taken back: one still being asked about is reported taken or not instead
action-taken-back409A decision was sent about an action taken back after it was taken, or a check completes one or asks about it again: it counts toward nothing, and nothing waits on it
nothing-to-decide409A sign-off on an answer that asks no question, or an override of one that decided nothing - it waits on facts, or on your rules. Or an approval or a refusal of a request that no longer waits: request_status says where it stands
cannot-decide403The person may not make this decision: only the one a question names signs it off, only an admin overrules, and only the person a request asks approves or refuses it (not_the_approver). Or the key is one made for an agent (agent_key), which records no decision: a decision is a person's - and an approval Himmel asked for is never a key's (a_key)
not-the-agents-action403A key made for an agent read, reported on, took back, completed or corrected an action its agent did not take, or read a request about one: it reads and acts on its own agent's actions only, and your account's own keys and your people on any
agent-switched-off403The agent was switched off: every request its keys send is refused, and so is a check asking first in its name, until it is switched on again. An action it took is reported as taken, as any is
cut-off403The owner of an account you opened for a customer cut you off from it, for good: you act in it no more. Your agents there act on until its owner switches them off
conflict409The request conflicts with what is stored - an action taken back is reported taken back at another moment or under another reference; detail says how
named-in-settings409A person your settings name from today on — who approves, who signs off — cannot be removed until they name somebody else; settings lists them
owns-agents409A person who owns one of your agents, switched on or off, cannot be removed until each has another owner; agents lists them
last-admin409The change would leave your account without an admin: make somebody else its admin first
policy-blocked409A policy cannot be published; blocking lists why
body-too-large413The request's body is larger than the operation takes: a policy's files 5 MB, any other body 1 MB. Refused by its length before any of it is read - or, sent chunked, as it arrives - and nothing was done
file-too-large413The file is larger than 20 MB, the most any endpoint takes. Nothing of it was read or kept
rate-limited429Too many requests in the last minute - or, opening an account, more accounts in a day than the deployment opens: 50 in all, 5 from one network address, 20 by one builder. Retry-After says in how many seconds the next can be opened, and nothing was opened
drafting-not-configured503Drafting from a document is not available in this deployment
sign-in-unavailable503Clerk, which signs people in to Himmel, could not be asked just now, or is not set up in this deployment: nothing was sent or changed
sign-up-closed503Accounts are not opened here yet - by signing up, or for a customer: the terms in force are a placeholder. Nothing was opened
rule-set-broken500A rule set could not be run on an action you asked about. The fault is ours, not your facts'. An action you report as taken is kept instead, answered not_covered with the reason rule_set_broken
internal500Something failed on our side

A 500 is ours to fix, and says so without describing itself; the request id finds it in our logs.