You cannot approve via the API as an agent
Approval endpoints require a human session token. A machine token can read the queue but never resolve it.
Hire an agent, hand it a mandate and a set of credentials, and subscribe to what it does. Approvals, audit trail and jurisdiction rules come with it — you do not rebuild them.
WAITLIST · NOT YET AVAILABLE
The API is specified, not shipped. The samples on this page are the interface we are building, not a live endpoint — when it ships they will run verbatim, and if a sample stops matching the API we change one of the two rather than leave the mismatch. Keys are issued by hand during the private beta.
Install, hire, run. The agent signs in to the tools you name using credentials you have already connected, and every consequential action lands in your approvals rather than in production.
pip install zugernpm i @zuger/sdkfrom zuger import Company
co = Company(api_key=os.environ["ZUGER_API_KEY"])
ledger = co.hire(
"ledger",
mandate="Close the month and prepare VAT.",
tools=["qonto", "stripe", "xero"],
approval="anything binding or over EUR 500",
)
run = ledger.run("August")
for event in run.stream():
print(event.actor, event.action, event.status)
# ledger reconcile done
# ledger file_vat awaiting_signature
import { Company } from "@zuger/sdk";
const co = new Company({ apiKey: process.env.ZUGER_API_KEY });
const ledger = await co.hire("ledger", {
mandate: "Close the month and prepare VAT.",
tools: ["qonto", "stripe", "xero"],
approval: "anything binding or over EUR 500",
});
for await (const e of ledger.run("August")) {
console.log(e.actor, e.action, e.status);
}
curl https://api.zuger.ai/v1/agents \
-H "Authorization: Bearer $ZUGER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": "ledger",
"mandate": "Close the month and prepare VAT.",
"tools": ["qonto","stripe","xero"],
"approval": "anything binding or over EUR 500"
}'
CORE OBJECTS
| Object | What it is |
|---|---|
Company | Your tenant. Holds entities, connected tools, memory and the audit log. |
Agent | A hired role with a standing mandate, a tool list and an approval threshold. |
Run | One execution of a task. Emits events, produces artefacts, ends in done, blocked, awaiting_signature or stopped_by_bernina. |
Approval | A stop. Carries the proposed action, the reasoning and the evidence. Only a human resolves it. |
Routine | A run on a schedule, created from runs you have already approved. |
THE RUN OBJECT
Bernina's three decisions ride on every run. They are read-only via the API; they cannot be overridden programmatically.
{
"id": "run_01j9x",
"agent": "ledger",
"status": "awaiting_signature", // done | blocked | awaiting_signature | stopped_by_bernina
"artefacts": ["art_vat_2026_08"],
"bernina": { "pre": "pass", "in_run": "pass", "post": "redact" }
}ENDPOINTS
| Method | Path | Does |
|---|---|---|
POST | /v1/agents | Hire an agent with a mandate, tools and threshold |
GET | /v1/agents | List agents and their current shift status |
POST | /v1/agents/:id/runs | Start a run |
GET | /v1/runs/:id | Fetch a run, its events and artefacts |
GET | /v1/runs/:id/stream | Server-sent events for a live run |
GET | /v1/approvals | Everything waiting on a human |
POST | /v1/approvals/:id | Approve or reject, with a reason |
POST | /v1/routines | Schedule a run that already works |
GET | /v1/memory | Read company memory |
GET | /v1/audit | Export the append-only log |
WEBHOOKS
| Event | Fires when |
|---|---|
run.started | An agent picks up a task |
run.blocked | An agent needs a credential, a document or a decision |
approval.created | Something consequential is waiting on a human |
approval.resolved | A human approved or rejected, with the reason |
run.completed | The task finished, with artefacts attached |
memory.updated | A correction was written and shared between agents |
agent.revoked | A credential was pulled and sessions were killed |
THE RULES
Approval endpoints require a human session token. A machine token can read the queue but never resolve it.
Mandates and limits are edited by people, out of band. An agent asking to change its own limit is itself an escalation.
test keys drive the same agents against fixture tools. Nothing reaches a bank, a registry or a customer.
60 requests a minute, 10 concurrent runs on Company; higher on Agency. Every 429 tells you when to retry.
Every error carries a type, a human message and a run_id where one exists. No opaque 500s.
Pass Idempotency-Key on any POST. Retries never start a second run or a second approval.
Tell us what you are building and we will put you at the front of the waitlist when the API opens.
Log in to pick up where the agents left off
Lost your passkey?Don’t have an account? Create account
By continuing you agree to our Terms & Privacy Policy
Free to start · No card
Already have an account? Log in
By continuing you agree to our Terms & Privacy Policy
If can be used, a link is on its way.
Open it on the device you want to sign in with — your phone, most likely. It works once, expires in a few hours, and can only create a passkey: it cannot read anything or approve anything.