FOR DEVELOPERS

One API.
A whole back office.

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.

API LIVE · SDKS COMING

The REST API is live at beta.zuger.ai/v1: make a key in the Console under Developers, read every route in the OpenAPI reference, and have Zuger call your own address with signed webhooks. The shell sample on this page runs today. The Python and TypeScript samples are the SDK interface we are building: the packages are not published yet, and when they are, those samples will run verbatim.

Quickstart

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 zuger COMING
npm i @zuger/sdk COMING

Neither package is published yet. Until they are, call the API directly: the shell tab is a call you can make now.

from 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);
}
# live today: brief an agent, then read the Run it made
curl https://beta.zuger.ai/v1/briefs \
  -H "Authorization: Bearer $ZUGER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "LEDGER",
    "text": "Where does cash stand this week?"
  }'

curl https://beta.zuger.ai/v1/runs \
  -H "Authorization: Bearer $ZUGER_KEY"

CORE OBJECTS

Five nouns,
and that is the whole model.

ObjectWhat it is
CompanyYour tenant. Holds entities, connected tools, memory and the audit log.
AgentA hired role with a standing mandate, a tool list and an approval threshold.
RunOne execution of a task. Emits events, produces artefacts, ends in done, blocked, awaiting_signature or stopped_by_bernina.
ApprovalA stop. Carries the proposed action, the reasoning and the evidence. Only a human resolves it.
RoutineA run on a schedule, created from runs you have already approved.

THE RUN OBJECT

What comes back
when you fetch a run.

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

The ones you will
actually call.

MethodPathDoes
POST/v1/briefsBrief an agent in plain words; the words become one Run
GET/v1/runsList Runs, newest first
GET/v1/runs/:idFetch a Run: its steps, its answer and any document
GET/v1/agentsList agents and whether each is on shift
GET/v1/approvalsEverything waiting on a human. Read only: no key can decide
POST/v1/routinesSchedule a brief to run every day, week or month
GET/v1/memoryRead company memory
GET/v1/audit/exportThe hash-chained audit log, oldest first. Founder Max and Ultra
POST/v1/webhooksAdd an address of your own for Zuger to call

Every route, and the ones no key can call, are in the OpenAPI reference.

WEBHOOKS

Subscribe to the moments
that matter.

EventFires when
run.finishedAn agent finished a Run, or stopped to wait for a decision
run.failedA Run could not finish
approval.createdSomething consequential is waiting on a human
approval.decidedA human approved or rejected it
approval.doneA human marked what they approved as carried out

Calls carry ids and states only, and are signed: X-Zuger-Signature: t=…,v1=…, where v1 is HMAC-SHA256 of t + "." + body with the secret shown once when you add the address. A failed call is retried five times; an address that keeps failing is switched off.

MCP

The same store,
as a tool server.

Zuger speaks the Model Context Protocol at beta.zuger.ai/mcp: Streamable HTTP, one JSON-RPC message per request, no session. With a key it is a bearer; without one, OAuth 2.1 with dynamic client registration and PKCE, which is how Claude and ChatGPT connect a person. The metadata is at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource/mcp.

ToolDoesScope
brief_agentHand an agent work in plain words; the words become one Runruns:write
list_runs · get_runRuns, and one Run in full: steps, answer, documents, Bernina’s verdicts, approvalsruns:read
whats_waiting · list_approvals · get_approvalWhat is waiting on a person. Read only, with the Console link to decideapprovals:read
list_routines · create_routine · pause_routineStanding instructions on a scheduleroutines:*
list_memory · rememberCompany memory, read and added tomemory:*
list_agents · list_findings · export_auditWho is on shift; what Säntis found; the hash-chained logagents:read · findings:read · audit:read

There is no tool that approves, signs, files, pays, hires, connects a tool or changes billing, and the server’s instructions say so to the model before it does anything. A person connecting from Claude sees the same list, in plain words, on the Zuger in Claude page; the full technical page is Zuger MCP.

claude mcp add --transport http zuger https://beta.zuger.ai/mcp \
  --header "Authorization: Bearer $ZUGER_KEY"

THE RULES

What the API
will not let you do.

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.

You cannot raise a threshold from inside a run

Mandates and limits are edited by people, out of band. An agent asking to change its own limit is itself an escalation.

There is no sandbox, on purpose

Every key is live, and the gate is what keeps it from anything binding: no key can approve, sign, file or pay. To try things, make a second company on the Free plan and load a month of example data from Settings → Connectors; the agents are told it is example data.

Rate limits are per company

1,000 requests a minute for a company. Every 429 tells you when to retry.

Errors say what to do

Every error carries a type, a human message and a run_id where one exists. No opaque 500s.

Retries are safe

Send an Idempotency-Key header with a brief. The same key from the same person within a day answers with the first Run (replayed: true) instead of starting another.

Free plan · No card

Build on the back office.

The API is open. Make a key in the Console, under Developers, and send your first brief.