Documentation ▸

Accounts for your customers

Your agents act for your customers: an account for each, its owner confirming its playbook, your agents' keys there.

If your agents act for your customers - an AI support agent for online shops, say - open an account on Himmel for each customer you serve. It is your customer's account: its playbook, and the record of every action your agents take there, are theirs whatever becomes of you. The person who runs it, its owner, confirms its rules, names who approves and approves where its rules name them. You act in it as its builder, and no further.

Himmel answers; your agent's tools enforce. In your customer's account Himmel checks your agent against your customer's own rules, and keeps the proof for them.

What you do there, and what you never do

YouYou never
open the account, with its owner's address and your agentsconfirm a rule, or switch a playbook on
register your agents there, and make and revoke their keyschange a setting, or name who approves
send its owner's invitation again, until they joininvite anybody but its owner
post its playbook from Himmel's template, or fill a draft of it againdecide a question, or approve an action
read where it standssee its customers' names, or hold a key that confirms

The account has no keys of its own: every key you hold there is one of your agents', which asks, reports and reads its rules, and none of them confirms a rule in its owner's name.

Before you start

Your company's own account, opened by signing up: see Opening your account. Opening an account for a customer, and everything you do in one, is a person's work - an admin or an engineer of your account, signed in to the console, under Developers, Your customers' accounts; or through the API with their session. No key opens an account or makes a key: the scope it needs, accounts, belongs to people alone. The sandbox opens none.

Open an account

POST /v1/accounts opens one:

{
  "account": {
    "name": "Example Coffee GmbH",
    "slug": "example_coffee",
    "country": "DE",
    "currency": "EUR",
    "retention_years": 10
  },
  "owner": { "email": "owner@coffee.example" },
  "agents": [{ "id": "agt_support", "role": "The support assistant" }],
  "playbook": {
    "template": "online_shop_support",
    "values": {
      "refund_without_approval": { "amount": 5000, "currency": "EUR" },
      "refund_with_team_lead": { "amount": 25000, "currency": "EUR" },
      "refund_by_assistant": { "amount": 3000, "currency": "EUR" },
      "refund_days": 30,
      "discount_without_approval": 15,
      "discount_with_team_lead": 30,
      "credit_at_most": { "amount": 2000, "currency": "EUR" },
      "credits_in_window": 2,
      "credit_window_days": 90,
      "credits_a_year": { "amount": 6000, "currency": "EUR" },
      "refund_above_assistant": "hand_to_a_person"
    }
  }
}
  • The account is your customer's company, as you open your own: its name; a short name of 2 to 40 lower-case letters, digits and _, which names its rule sets (policy.example_coffee.customer_support); where it is established; the currency its books are kept in, never taken from the country; and how many years its country's law has it keep its records, from 1 to 30.
  • Its owner is the address of the person who runs it. Never somebody in your own account: one person is in one account, and they could not join it.
  • Your agents that act for it, up to ten, each by its id in your systems and what it is, in words.
  • Its playbook, where you have the customer's figures: Himmel's template for an online shop's support - refunds, retention discounts and goodwill credits - with every figure filled in, money in the account's currency, and its one choice made - what becomes of a refund above what the AI assistant gives on its own: handed to the team lead, whom Himmel tells (hand_to_a_person), or the team lead's approval first (team_lead_approval). Himmel proposes none. GET /v1/templates lists each blank, what it is, the clauses that say it and the least and most it takes, and each choice with its options; a figure out of the order its words put them in is refused, naming the clauses. Leave playbook out to post it later.

The answer is the account, where it stands, and each of your agents' keys there, a live one and a test one, shown once: store each where that agent reads its secrets. A retry with the same Idempotency-Key gets the same answer with every key empty, never a second account.

Refused, with nothing opened: a field not as described (422, naming it), a short name another account has (409, taken), an owner's address of your own people (422, in_your_account), the sandbox (409), and the accounts opened in a day - 20 by your account, 5 from one network address, 50 for all of Himmel (429 rate-limited, with Retry-After saying in how many seconds the next can be opened).

Its owner joins

Himmel emails the owner - not you: who opened the account for whom, what waits for them, and the link that signs them up at the address you gave. You never see that link: whoever holds it joins as the account's owner. Signed up, they accept Himmel's terms for their account and go straight to their playbook: each rule beside the clause it comes from, in their figures; a figure that is not theirs changed there, the playbook filled again from the template; who approves, and the day their year starts; and one button that confirms the rules and switches the playbook on. Nothing in the account answers until they do. They own your agents there from then, and switch any of them off in one step.

Where each stands

GET /v1/accounts lists the accounts you opened, the newest first, fifty to a page - limit up to 200, and before set to the last page's next_before for the next. Each says:

FieldWhat it says
ownertheir invitation: waiting, accepted once they joined, or expired - send it again; when it runs out, and when Himmel's email went (emailed_at; still null a few minutes on, their mail server may have refused the address - send it again, to one it takes)
termsHimmel's terms, as the owner accepted them for the account
playbookseach playbook's version its owner switched on, and the draft waiting for them
agentsyour agents there: whether each is switched off, and when each last acted, in live
cut_off_atwhen its owner cut you off: every other field is then empty

GET /v1/accounts/{account_id} reads one, with the owner's address while their invitation waits - the address you send it again from - and the keys you made there, never the keys themselves. Never the account's own agents or people, its customers, or what its people decided.

Your agents and their keys there

RequestWhat it does
POST /v1/accounts/{account_id}/agentsregisters another of your agents there, by id and role
POST /v1/accounts/{account_id}/keysmakes one of them a key, live or test, shown once
POST /v1/accounts/{account_id}/keys/{key_id}/revokerevokes one you made, for good

A key acts in its customer's account alone. Your agent holds one key for each customer it serves, and asks with the key of the customer it is acting for, naming that customer's playbook by its short name: The SDK and Connect an agent by MCP show how. Every check it sends there is recorded in that customer's account, as your agent's, and its owner sees it in their check log.

The invitation again, and the playbook

RequestWhat it does
POST /v1/accounts/{account_id}/invitationsends the owner's invitation again - to the same address, or a corrected one - until they have joined: the earlier link stops working. After that its people are theirs to invite (409, owner_joined)
POST /v1/accounts/{account_id}/policiesposts its playbook from the template with your figures, as a draft its owner confirms rule by rule - the next version, where one is switched on. A draft of it already there is 409: fill that again
PUT /v1/accounts/{account_id}/policies/{policy_id}fills its draft again with every figure: the rules a changed figure reaches wait for its owner again

Never a playbook's files, and never switched on: its owner does that.

When its owner cuts you off

The owner, or another admin of their account, can cut you off - from then, and for good. Every request you make in that account is 403 cut-off, and where it stands reads as what it is and when, and nothing more. Your agents there act on until its owner switches them off or revokes their keys: an owner who wants your agent to stop switches it off.

When a request is refused

StatusProblem typeWhy
403insufficient-scopeA key, or a role that does not hold accounts - opening and acting in your customers' accounts is an admin's or an engineer's, signed in
403cut-offThe account's owner cut you off
403live-onlyA change made from test: your customers' accounts are changed from your own account's live side
404not-foundAn account your account did not open, or a key you did not make there
409conflictA short name taken, an agent registered there already, the owner joined, a draft of the playbook there already, or the sandbox
422invalid-requestA field not as described, naming it, or an owner's address of your own people
503sign-in-unavailableClerk, which signs people in, could not be asked: nothing was opened or sent
503sign-up-closedAccounts are opened once Himmel's terms are published: nothing was opened

Endpoints

GET/v1/accountsScope accounts

The accounts you opened for your customers

The accounts your account opened for the customers its agents serve, the newest first, fifty to a page, each with where it stands: its owner invited or joined - their address is one account's read - the terms they accepted for it, each playbook's version switched on and its draft waiting, and your agents there - switched off or not, and when each last acted, in live. Never the account's own agents or people, its customers, or what its people decided. Of one its owner cut you off from, what it is and when, and nothing more. Continue with before set to the last page's next_before.

Needs a person signed in whose role carries accounts: no key can hold it.

Parameters

  • limitquery · integer

    How many accounts to a page.

  • beforequery · string or null

    The last page's next_before, an account's id, to continue from.

Responses

200 Successful response
  • accountslist of OpenedAccountrequired

    The accounts your account opened for its customers, the newest first, a page.

    13 fields
    • idstringrequired
    • slugstringrequired
    • namestringrequired
    • countrystringrequired
    • currencystringrequired
    • retention_yearsintegerrequired
    • opened_atstringrequired
    • cut_off_atstring or null

      When its owner cut you off from it, for good: you act in it no more, and read nothing more of it. Your agents there act on until its owner switches them off. Null while you may act.

    • ownerOpenedOwner or null

      Its owner. Null once you were cut off.

      6 fields
      • status"waiting" | "accepted" | "withdrawn" | "expired"required

        waiting for them to take it up; accepted, they joined - the account is theirs to run; expired, not taken up in time - send it again.

      • invited_atstringrequired
      • expires_atstringrequired
      • emailstring or null

        The address you sent it to, while it waits, to send it again from - or to another: in one account's read (GET /v1/accounts/{account_id}), and null in the list. Null once they have joined: their address is theirs.

      • emailed_atstring or null

        When Himmel's email with the invitation's link went to them: who opened the account for whom, what waits for them, and the link, which you never see. Null until it has gone, and where their mail server refused the address - send it again, to one it takes - and where the deployment sends no email of its own, when Clerk sent its own.

      • joined_atstring or null

        When they joined. Null until they have.

    • termsOpenedTerms or null

      Himmel's terms, as its owner accepted them for it joining. Null until they have.

      2 fields
      • versionstringrequired
      • accepted_atstringrequired
    • playbookslist of OpenedPlaybook or null

      Its playbooks, by rule set. Null once you were cut off.

      4 fields
      • rule_setstringrequired
      • titlestringrequired
      • switched_onSwitchedOnVersion or null

        The latest version its owner confirmed and switched on. Null while none is.

        2 fields
        • versionstringrequired
        • effective_fromstringrequired

          The day its owner switched it on from.

      • draftDraftVersion or null

        The draft waiting for its owner to confirm it, rule by rule. Null where none waits.

        2 fields
        • policy_idstringrequired

          The draft's id: what PUT /v1/accounts/{account_id}/policies/{policy_id} fills again.

        • versionstringrequired
    • agentslist of OpenedAgent or null

      Your agents there, in the order registered - never its own. Null once cut off.

      5 fields
      • idstringrequired
      • registered_atstringrequired
      • rolestring or null
      • switched_off_atstring or null

        When the account's owner - or a person they let - switched it off: every request its keys send there is refused since. Null while it is on.

      • last_acted_atstring or null

        When an action recorded as its was last asked about or taken there, in live.

    • keyslist of OpenedKey or null

      The keys you made there, the newest first, revoked ones too: in one account's answer, null in the list of them and once you were cut off.

      8 fields
      • idstringrequired
      • prefixstringrequired
      • namestringrequired
      • env"live" | "test"required
      • agentstringrequired
      • created_atstringrequired
      • last_used_atstring or null
      • revoked_atstring or null

        When it was revoked, for good - by you, or by the account's own people. Null while it works.

  • next_beforestring or null

    before for the next page, an account's id; null on the last.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
POST/v1/accountsScope accounts

Open an account for a customer

For a builder - a company whose agents act for its customers: an admin or an engineer of its account opens one for a customer it serves. The account is the customer's: its account as POST /v1/me/account takes one; owner.email, the address of the person who runs it - who confirms its rules, names who approves and approves where its rules name them - invited at once; agents, yours that act for it, each by id and role, registered there and owned by the owner once they join; and playbook, where you have its figures, a template filled with them (GET /v1/templates), posted as a draft its owner confirms. It opens with live and test and no keys of its own: nothing you hold confirms a rule in its owner's name. Each of your agents gets a live and a test key, an agent's four scopes, each shown here once. From then you read where it stands, register your agents there and make and revoke their keys, send its owner's invitation again and post its playbook from a template - nothing more: never a confirmation, a playbook switched on, a setting, a person, a decision or an approval. Its owner joins accepting Himmel's terms for it, and may cut you off. Refused, nothing opened: a field not as described (422, naming it - account.<field>, owner.email, agents[i].id, playbook.values.<blank>), a company name holding an email address or an IBAN (422 pii-in-facts), an owner's address of a person in your own account (422, in_your_account: they cannot join another), a slug taken (409, taken), the sandbox (409, test_only_account), the accounts opened in a day - 20 by one builder, 5 from one network address, 50 for the whole deployment (429 rate-limited, with Retry-After saying when to try again) - Clerk not answering (503 sign-in-unavailable), and a deployment whose terms are not yet written (503 sign-up-closed). A retry with the same Idempotency-Key gets the same answer, the keys' key and the owner's email null.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • Idempotency-Keyheader · string or null

    Makes a retry safe: the same key with the same request within 24 hours gets the first answer again, and nothing is done twice. The same key with a different request is 409 idempotency-conflict. Keys are per environment and per path.

Request body · application/json

  • accountAccountFieldsrequired
    5 fields
    • namestringrequired

      The company's name, as every page of the console shows it: one line, up to 200 characters, never an email address or an IBAN (pii-in-facts).

    • slugstringrequired

      The account's short name, which names its own rule sets - policy.<slug>.<name> - so it is 2 to 40 lower-case letters, digits and _, beginning with a letter, and one account's alone (409, taken).

    • countrystring, one of 249required

      Where the company is established, as an ISO 3166-1 code: US, AE, DE - the United Kingdom is GB. Never read off the currency.

    • currencystring, one of 165required

      The currency the company's books are kept in, as an ISO 4217 code amounts are written in: USD, AED, EUR. Never taken from the country: a company may keep its books in another.

    • retention_yearsintegerrequired

      How many years the company must keep its records - its country's law, which it says, from 1 to 30 - and so how long Himmel keeps every check of the account. Never assumed.

  • ownerOwnerBodyrequired
    1 field
    • emailstringrequired

      The address the owner signs in with. They are emailed an invitation to the account, and join it signed up at that address. Never a person of your own account, who cannot join another (in_your_account).

  • agentslist of OpenedAgentBody

    Your agents that act for it, each by its id and role - up to ten; more are registered later. Each gets a live and a test key, made for you.

    2 fields
    • idstringrequired

      The agent's own id in your systems - what every check it sends records, and what a rule reading actor.id names: letters, digits and _ . : -, up to 64, never a name or an address, and never beginning usr_. Fixed once registered.

    • rolestringrequired

      What the agent is, in words, as every page names it: The support assistant. One line; never a person's name or address (pii-in-facts).

  • playbookPlaybookBody or null

    Its playbook, where you have its figures: posted as a draft its owner confirms. Left out, it is posted later (POST /v1/accounts/{account_id}/policies).

    2 fields
    • templatestringrequired

      One of our templates, by its name (GET /v1/templates).

    • valuesobjectrequired

      Every blank of the template and your figure for it, by the blank's name: money as an integer amount in minor units with the account's currency, days, percent and counts as whole numbers - and every choice and the value of the option you pick, by the choice's name. Each is required: the template proposes no figure and no choice, and its owner confirms each rule with its figure, or changes it.

Responses

200 Successful response
  • accountOpenedAccountrequired
    13 fields
    • idstringrequired
    • slugstringrequired
    • namestringrequired
    • countrystringrequired
    • currencystringrequired
    • retention_yearsintegerrequired
    • opened_atstringrequired
    • cut_off_atstring or null

      When its owner cut you off from it, for good: you act in it no more, and read nothing more of it. Your agents there act on until its owner switches them off. Null while you may act.

    • ownerOpenedOwner or null

      Its owner. Null once you were cut off.

      6 fields
      • status"waiting" | "accepted" | "withdrawn" | "expired"required

        waiting for them to take it up; accepted, they joined - the account is theirs to run; expired, not taken up in time - send it again.

      • invited_atstringrequired
      • expires_atstringrequired
      • emailstring or null

        The address you sent it to, while it waits, to send it again from - or to another: in one account's read (GET /v1/accounts/{account_id}), and null in the list. Null once they have joined: their address is theirs.

      • emailed_atstring or null

        When Himmel's email with the invitation's link went to them: who opened the account for whom, what waits for them, and the link, which you never see. Null until it has gone, and where their mail server refused the address - send it again, to one it takes - and where the deployment sends no email of its own, when Clerk sent its own.

      • joined_atstring or null

        When they joined. Null until they have.

    • termsOpenedTerms or null

      Himmel's terms, as its owner accepted them for it joining. Null until they have.

      2 fields
      • versionstringrequired
      • accepted_atstringrequired
    • playbookslist of OpenedPlaybook or null

      Its playbooks, by rule set. Null once you were cut off.

      4 fields
      • rule_setstringrequired
      • titlestringrequired
      • switched_onSwitchedOnVersion or null

        The latest version its owner confirmed and switched on. Null while none is.

        2 fields
        • versionstringrequired
        • effective_fromstringrequired

          The day its owner switched it on from.

      • draftDraftVersion or null

        The draft waiting for its owner to confirm it, rule by rule. Null where none waits.

        2 fields
        • policy_idstringrequired

          The draft's id: what PUT /v1/accounts/{account_id}/policies/{policy_id} fills again.

        • versionstringrequired
    • agentslist of OpenedAgent or null

      Your agents there, in the order registered - never its own. Null once cut off.

      5 fields
      • idstringrequired
      • registered_atstringrequired
      • rolestring or null
      • switched_off_atstring or null

        When the account's owner - or a person they let - switched it off: every request its keys send there is refused since. Null while it is on.

      • last_acted_atstring or null

        When an action recorded as its was last asked about or taken there, in live.

    • keyslist of OpenedKey or null

      The keys you made there, the newest first, revoked ones too: in one account's answer, null in the list of them and once you were cut off.

      8 fields
      • idstringrequired
      • prefixstringrequired
      • namestringrequired
      • env"live" | "test"required
      • agentstringrequired
      • created_atstringrequired
      • last_used_atstring or null
      • revoked_atstring or null

        When it was revoked, for good - by you, or by the account's own people. Null while it works.

  • keyslist of OpenedKeyMaderequired

    For each of your agents, in the order sent, its live key and then its test key - each an agent's four scopes. key is each one itself, shown here once: store them now. A retry with the same Idempotency-Key gets their records with key null, and the owner's address null.

    9 fields
    • idstringrequired
    • prefixstringrequired
    • namestringrequired
    • env"live" | "test"required
    • agentstringrequired
    • created_atstringrequired
    • keystring or nullrequired

      The key itself, hk_live_… or hk_test_…: shown here once and never again. Null on a retry with the same Idempotency-Key.

    • last_used_atstring or null
    • revoked_atstring or null

      When it was revoked, for good - by you, or by the account's own people. Null while it works.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 409The request conflicts with what is stored: see detail.
  • 413The request's body is larger than the operation takes, refused before any of it is read (body-too-large): a policy's files at most 5 MB, any other body 1 MB - and an uploaded file at most 20 MB (file-too-large).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
  • 503An optional part of the service is not configured in this deployment, or a service it relies on did not answer: type says which.
GET/v1/accounts/{account_id}Scope accounts

An account you opened, where it stands

One account your account opened, as GET /v1/accounts lists it, with its owner's address while their invitation waits - the one you send it again from - and the keys you made there: their records, never the keys. 404 not-found for one it did not open.

Needs a person signed in whose role carries accounts: no key can hold it.

Parameters

  • account_idpath · stringrequired

Responses

200 Successful response
  • idstringrequired
  • slugstringrequired
  • namestringrequired
  • countrystringrequired
  • currencystringrequired
  • retention_yearsintegerrequired
  • opened_atstringrequired
  • cut_off_atstring or null

    When its owner cut you off from it, for good: you act in it no more, and read nothing more of it. Your agents there act on until its owner switches them off. Null while you may act.

  • ownerOpenedOwner or null

    Its owner. Null once you were cut off.

    6 fields
    • status"waiting" | "accepted" | "withdrawn" | "expired"required

      waiting for them to take it up; accepted, they joined - the account is theirs to run; expired, not taken up in time - send it again.

    • invited_atstringrequired
    • expires_atstringrequired
    • emailstring or null

      The address you sent it to, while it waits, to send it again from - or to another: in one account's read (GET /v1/accounts/{account_id}), and null in the list. Null once they have joined: their address is theirs.

    • emailed_atstring or null

      When Himmel's email with the invitation's link went to them: who opened the account for whom, what waits for them, and the link, which you never see. Null until it has gone, and where their mail server refused the address - send it again, to one it takes - and where the deployment sends no email of its own, when Clerk sent its own.

    • joined_atstring or null

      When they joined. Null until they have.

  • termsOpenedTerms or null

    Himmel's terms, as its owner accepted them for it joining. Null until they have.

    2 fields
    • versionstringrequired
    • accepted_atstringrequired
  • playbookslist of OpenedPlaybook or null

    Its playbooks, by rule set. Null once you were cut off.

    4 fields
    • rule_setstringrequired
    • titlestringrequired
    • switched_onSwitchedOnVersion or null

      The latest version its owner confirmed and switched on. Null while none is.

      2 fields
      • versionstringrequired
      • effective_fromstringrequired

        The day its owner switched it on from.

    • draftDraftVersion or null

      The draft waiting for its owner to confirm it, rule by rule. Null where none waits.

      2 fields
      • policy_idstringrequired

        The draft's id: what PUT /v1/accounts/{account_id}/policies/{policy_id} fills again.

      • versionstringrequired
  • agentslist of OpenedAgent or null

    Your agents there, in the order registered - never its own. Null once cut off.

    5 fields
    • idstringrequired
    • registered_atstringrequired
    • rolestring or null
    • switched_off_atstring or null

      When the account's owner - or a person they let - switched it off: every request its keys send there is refused since. Null while it is on.

    • last_acted_atstring or null

      When an action recorded as its was last asked about or taken there, in live.

  • keyslist of OpenedKey or null

    The keys you made there, the newest first, revoked ones too: in one account's answer, null in the list of them and once you were cut off.

    8 fields
    • idstringrequired
    • prefixstringrequired
    • namestringrequired
    • env"live" | "test"required
    • agentstringrequired
    • created_atstringrequired
    • last_used_atstring or null
    • revoked_atstring or null

      When it was revoked, for good - by you, or by the account's own people. Null while it works.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
POST/v1/accounts/{account_id}/agentsScope accounts

Register one of your agents in an account you opened

Your agent, known there before it acts: id and role as POST /v1/agents takes them - an id the account has registered already is 409, already_registered. Its owner is the account's owner where they have joined, and nobody until they do. Make its keys with POST /v1/accounts/{account_id}/keys. 404 not-found for an account yours did not open, 403 cut-off for one whose owner cut you off.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • account_idpath · stringrequired
  • Idempotency-Keyheader · string or null

    Makes a retry safe: the same key with the same request within 24 hours gets the first answer again, and nothing is done twice. The same key with a different request is 409 idempotency-conflict. Keys are per environment and per path.

Request body · application/json

  • idstringrequired

    The agent's own id in your systems - what every check it sends records, and what a rule reading actor.id names: letters, digits and _ . : -, up to 64, never a name or an address, and never beginning usr_. Fixed once registered.

  • rolestringrequired

    What the agent is, in words, as every page names it: The support assistant. One line; never a person's name or address (pii-in-facts).

Responses

200 Successful response
  • idstringrequired
  • registered_atstringrequired
  • rolestring or null
  • switched_off_atstring or null

    When the account's owner - or a person they let - switched it off: every request its keys send there is refused since. Null while it is on.

  • last_acted_atstring or null

    When an action recorded as its was last asked about or taken there, in live.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 409The request conflicts with what is stored: see detail.
  • 413The request's body is larger than the operation takes, refused before any of it is read (body-too-large): a policy's files at most 5 MB, any other body 1 MB - and an uploaded file at most 20 MB (file-too-large).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
POST/v1/accounts/{account_id}/keysScope accounts

Make a key for one of your agents in an account you opened

A key for one of your agents there, live or test, holding an agent's four scopes - check, checks:read, checks:write, rules:read - and never more: every check it sends records the agent. The key itself is in this answer and never again. An agent you did not register in that account is 422, unknown_agent. A retry with the same Idempotency-Key gets the same key's record, key null. 404 not-found for an account yours did not open, 403 cut-off for one whose owner cut you off.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • account_idpath · stringrequired
  • Idempotency-Keyheader · string or null

    Makes a retry safe: the same key with the same request within 24 hours gets the first answer again, and nothing is done twice. The same key with a different request is 409 idempotency-conflict. Keys are per environment and per path.

Request body · application/json

  • agentstringrequired

    The agent, by the id you registered it under there: unknown_agent for one you did not register in that account.

  • env"live" | "test"required

    Where it acts.

  • namestring or null

    What it is for, as the account's check log shows it beside its prefix. Left out, the agent's id and the environment. Never a person's name or address (pii-in-facts).

Responses

200 Successful response
  • idstringrequired
  • prefixstringrequired
  • namestringrequired
  • env"live" | "test"required
  • agentstringrequired
  • created_atstringrequired
  • keystring or nullrequired

    The key itself, hk_live_… or hk_test_…: shown here once and never again. Null on a retry with the same Idempotency-Key.

  • last_used_atstring or null
  • revoked_atstring or null

    When it was revoked, for good - by you, or by the account's own people. Null while it works.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 413The request's body is larger than the operation takes, refused before any of it is read (body-too-large): a policy's files at most 5 MB, any other body 1 MB - and an uploaded file at most 20 MB (file-too-large).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
POST/v1/accounts/{account_id}/keys/{key_id}/revokeScope accounts

Revoke a key you made in an account you opened

Revoked from now, for good: the next request with it is 401. A key you did not make there is 404 not-found; one revoked already - by you, or by the account's own people - is answered as it stands. 403 cut-off for an account whose owner cut you off.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • account_idpath · stringrequired
  • key_idpath · stringrequired
  • Idempotency-Keyheader · string or null

    Makes a retry safe: the same key with the same request within 24 hours gets the first answer again, and nothing is done twice. The same key with a different request is 409 idempotency-conflict. Keys are per environment and per path.

Responses

200 Successful response
  • idstringrequired
  • prefixstringrequired
  • namestringrequired
  • env"live" | "test"required
  • agentstringrequired
  • created_atstringrequired
  • last_used_atstring or null
  • revoked_atstring or null

    When it was revoked, for good - by you, or by the account's own people. Null while it works.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
POST/v1/accounts/{account_id}/invitationScope accounts

Send the owner's invitation again

Until the owner of an account you opened has joined it: the invitation waiting is withdrawn and another sent - to the same address, or a corrected one. Once they have joined it is 409, owner_joined: its people are theirs to invite, and you invite nobody. Refused as opening refuses an owner's address (422, format, in_your_account), and 503 sign-in-unavailable where Clerk could not be asked: nothing sent. A retry with the same Idempotency-Key gets the same answer, email null.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • account_idpath · stringrequired
  • Idempotency-Keyheader · string or null

    Makes a retry safe: the same key with the same request within 24 hours gets the first answer again, and nothing is done twice. The same key with a different request is 409 idempotency-conflict. Keys are per environment and per path.

Request body · application/json

  • emailstringrequired

    The address the owner signs in with. They are emailed an invitation to the account, and join it signed up at that address. Never a person of your own account, who cannot join another (in_your_account).

Responses

200 Successful response
  • status"waiting" | "accepted" | "withdrawn" | "expired"required

    waiting for them to take it up; accepted, they joined - the account is theirs to run; expired, not taken up in time - send it again.

  • invited_atstringrequired
  • expires_atstringrequired
  • emailstring or null

    The address you sent it to, while it waits, to send it again from - or to another: in one account's read (GET /v1/accounts/{account_id}), and null in the list. Null once they have joined: their address is theirs.

  • emailed_atstring or null

    When Himmel's email with the invitation's link went to them: who opened the account for whom, what waits for them, and the link, which you never see. Null until it has gone, and where their mail server refused the address - send it again, to one it takes - and where the deployment sends no email of its own, when Clerk sent its own.

  • joined_atstring or null

    When they joined. Null until they have.

  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 409The request conflicts with what is stored: see detail.
  • 413The request's body is larger than the operation takes, refused before any of it is read (body-too-large): a policy's files at most 5 MB, any other body 1 MB - and an uploaded file at most 20 MB (file-too-large).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
  • 503An optional part of the service is not configured in this deployment, or a service it relies on did not answer: type says which.
POST/v1/accounts/{account_id}/policiesScope accounts

Post a playbook from a template in an account you opened

A template filled with your figures for the customer, as POST /v1/policies fills one: its document, rules and worked examples saying them, in the account's currency, posted as a draft its owner confirms rule by rule - a new playbook's 1.0.0, or the next version of the one it has; a draft of it already there is 409, naming it, and is filled again with PUT. Never its files, and never switched on: its owner does that. 404 not-found for an account yours did not open, 403 cut-off for one whose owner cut you off.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • account_idpath · stringrequired
  • Idempotency-Keyheader · string or null

    Makes a retry safe: the same key with the same request within 24 hours gets the first answer again, and nothing is done twice. The same key with a different request is 409 idempotency-conflict. Keys are per environment and per path.

Request body · application/json

  • templatestringrequired

    One of our templates, by its name (GET /v1/templates).

  • valuesobjectrequired

    Every blank of the template and your figure for it, by the blank's name: money as an integer amount in minor units with the account's currency, days, percent and counts as whole numbers - and every choice and the value of the option you pick, by the choice's name. Each is required: the template proposes no figure and no choice, and its owner confirms each rule with its figure, or changes it.

Responses

200 Successful response
  • policy_idstringrequired
  • rule_setstringrequired
  • versionstringrequired
  • statusstringrequired
  • effective_fromstringrequired
  • rulesintegerrequired
  • pending_confirmationlist of stringrequired
  • flaggedlist of stringrequired
  • filled_fromFilledFrom or nullrequired

    The template that filled this version and the figures it was filled with; null for one posted as files or drafted from a document.

    3 fields
    • templatestringrequired

      The template's name, as GET /v1/templates lists it.

    • versionstringrequired

      The template's own version when it filled this one.

    • valuesobjectrequired

      Each blank's figure, by its name: money as {amount, currency}, the rest whole numbers.

  • titlestringrequired
  • domainstringrequired
  • jurisdictionslist of stringrequired
  • sits_onlist of stringrequired

    The law versions it is layered over, rule_set@version. Empty for a policy that stands alone: one for a domain and country we hold no law for, which states outcomes only.

  • filesmap of stringrequired
  • checksPublishChecksrequired

    Everything publishing would run, run now.

    6 fields
    • publishablebooleanrequired
    • blockinglist of PublishFindingrequired
      11 fields
      • checkstringrequired

        lint, consequence, coverage, cases or floor.

      • codestring or null
      • rulestring or null
      • casestring or null
      • messagestring or null
      • failureslist of string or null
      • lawstring or null
      • law_rulestring or null
      • policy_rulestring or null
      • owedany
      • paidany
    • warningslist of PublishFindingrequired
      11 fields
      • checkstringrequired

        lint, consequence, coverage, cases or floor.

      • codestring or null
      • rulestring or null
      • casestring or null
      • messagestring or null
      • failureslist of string or null
      • lawstring or null
      • law_rulestring or null
      • policy_rulestring or null
      • owedany
      • paidany
    • casesCaseCountsrequired
      2 fields
      • passedintegerrequired
      • failedintegerrequired
    • coveragemap of integerrequired

      How many cases reach each rule.

    • floorFloorSummaryrequired
      2 fields
      • lawsintegerrequired
      • payments_comparedintegerrequired
  • drafted_fromDraftedFrom or nullrequired

    The document this version was last drafted from; null for one posted as files.

    5 fields
    • document_idstringrequired
    • filenamestringrequired
    • titlestringrequired
    • created_atstringrequired

      When the document was uploaded.

    • drafted_atstringrequired

      When the drafting that wrote this version began.

  • review_itemslist of ReviewItemrequired

    What its latest drafting raised - examples the two drafts decide differently, holes the third pass found, cases that fail, examples a rule could not answer once altered - and each flag of a rule that stands flagged.

    5 fields
    • review_itemstringrequired
    • kindstringrequired
    • statusstringrequired
    • payloadobjectrequired
    • created_atstring or null
  • superseded_bystring or null
  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 409The request conflicts with what is stored: see detail.
  • 413The request's body is larger than the operation takes, refused before any of it is read (body-too-large): a policy's files at most 5 MB, any other body 1 MB - and an uploaded file at most 20 MB (file-too-large).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.
PUT/v1/accounts/{account_id}/policies/{policy_id}Scope accounts

Fill a draft playbook again in an account you opened

A draft of the playbook filled from a template, filled again with your figures: the rules a changed figure reaches wait for its owner again, and the rest keep their confirmations. Only a draft filled from that template - one the account's own people posted as files is 409, not_from_a_template, and a version switched on never changes. 404 not-found for an account yours did not open or a version it does not have, 403 cut-off for one whose owner cut you off.

Needs a person signed in whose role carries accounts: no key can hold it. It changes what your account has decided, which live and test share, so it is done from live: in an account with a live side, a test key gets 403 live-only.

Parameters

  • account_idpath · stringrequired
  • policy_idpath · stringrequired

Request body · application/json

  • templatestringrequired

    One of our templates, by its name (GET /v1/templates).

  • valuesobjectrequired

    Every blank of the template and your figure for it, by the blank's name: money as an integer amount in minor units with the account's currency, days, percent and counts as whole numbers - and every choice and the value of the option you pick, by the choice's name. Each is required: the template proposes no figure and no choice, and its owner confirms each rule with its figure, or changes it.

Responses

200 Successful response
  • policy_idstringrequired
  • rule_setstringrequired
  • versionstringrequired
  • statusstringrequired
  • effective_fromstringrequired
  • rulesintegerrequired
  • pending_confirmationlist of stringrequired
  • flaggedlist of stringrequired
  • filled_fromFilledFrom or nullrequired

    The template that filled this version and the figures it was filled with; null for one posted as files or drafted from a document.

    3 fields
    • templatestringrequired

      The template's name, as GET /v1/templates lists it.

    • versionstringrequired

      The template's own version when it filled this one.

    • valuesobjectrequired

      Each blank's figure, by its name: money as {amount, currency}, the rest whole numbers.

  • titlestringrequired
  • domainstringrequired
  • jurisdictionslist of stringrequired
  • sits_onlist of stringrequired

    The law versions it is layered over, rule_set@version. Empty for a policy that stands alone: one for a domain and country we hold no law for, which states outcomes only.

  • filesmap of stringrequired
  • checksPublishChecksrequired

    Everything publishing would run, run now.

    6 fields
    • publishablebooleanrequired
    • blockinglist of PublishFindingrequired
      11 fields
      • checkstringrequired

        lint, consequence, coverage, cases or floor.

      • codestring or null
      • rulestring or null
      • casestring or null
      • messagestring or null
      • failureslist of string or null
      • lawstring or null
      • law_rulestring or null
      • policy_rulestring or null
      • owedany
      • paidany
    • warningslist of PublishFindingrequired
      11 fields
      • checkstringrequired

        lint, consequence, coverage, cases or floor.

      • codestring or null
      • rulestring or null
      • casestring or null
      • messagestring or null
      • failureslist of string or null
      • lawstring or null
      • law_rulestring or null
      • policy_rulestring or null
      • owedany
      • paidany
    • casesCaseCountsrequired
      2 fields
      • passedintegerrequired
      • failedintegerrequired
    • coveragemap of integerrequired

      How many cases reach each rule.

    • floorFloorSummaryrequired
      2 fields
      • lawsintegerrequired
      • payments_comparedintegerrequired
  • drafted_fromDraftedFrom or nullrequired

    The document this version was last drafted from; null for one posted as files.

    5 fields
    • document_idstringrequired
    • filenamestringrequired
    • titlestringrequired
    • created_atstringrequired

      When the document was uploaded.

    • drafted_atstringrequired

      When the drafting that wrote this version began.

  • review_itemslist of ReviewItemrequired

    What its latest drafting raised - examples the two drafts decide differently, holes the third pass found, cases that fail, examples a rule could not answer once altered - and each flag of a rule that stands flagged.

    5 fields
    • review_itemstringrequired
    • kindstringrequired
    • statusstringrequired
    • payloadobjectrequired
    • created_atstring or null
  • superseded_bystring or null
  • 401No API key was sent, or it is not in use (unauthorized).
  • 403The caller may not do this, and type says why: the key or role lacks the scope, the rule set is not enabled for this account, the person signed in belongs to no account, names were asked for by a caller that is not shown them, or a request acting in test tried to change the account's settings (live-only).
  • 404Nothing with that id or name exists for this account.
  • 409The request conflicts with what is stored: see detail.
  • 413The request's body is larger than the operation takes, refused before any of it is read (body-too-large): a policy's files at most 5 MB, any other body 1 MB - and an uploaded file at most 20 MB (file-too-large).
  • 422The request, or a fact in it, is not in the documented shape - a query parameter the operation does not take included, which is named (unknown_parameter) rather than ignored - or its Himmel-Env does not fit the caller. Missing facts are not errors.
  • 429More requests in a minute than the key's or the person's limit (rate-limited) - or, opening an account, more accounts in a day than the deployment opens, with Retry-After saying when to try again.
  • 500Something failed on our side. X-Request-Id identifies it in our logs.