Integration guide
Everything an agent does — identity, network, storage, payments — goes through the gateway, where policy is enforced and every decision is recorded. This page walks the full integration:
- Authenticate — send
X-Imara-Tokenon every call. The token maps to a role, the role to capabilities. Admin routes takeX-Admin-Tokeninstead. - Register an identity —
POST /v1/agentsmints aPENDINGAgent DNA record with the agent’s Ed25519 public key, owner, zone, and capability grant. - Activate — an operator approves with
PUT /v1/agents/{id}/activate;approvedByandapprovalReasongo straight into the audit trail. - Apply policy — policy templates render org and zone ceiling documents. The effective chain for any agent is one
GETaway. - Allowlist merchants — payees are registered
PENDINGand must be approved by a different identity (maker-checker) before any agent can pay them. - Pay through the kernel — agents never hold keys.
POST /v1/x402/fetchor/v1/proxy/fetch— the kernel enforces policy, pays, and records the receipt.
Before you start you need the kernel base URL, a session token mapped to a role, and — for lifecycle operations — the deployment admin token.
Base URL and authentication
Section titled “Base URL and authentication”All routes below are served from your kernel gateway origin; the examples use $KERNEL as a stand-in. Two headers cover every surface:
X-Imara-Tokencarries a session or role token (aBearerAuthorization header works too). The kernel resolves the token to a role and the role to capabilities such asCAP_NETWORK,CAP_VFS_READ, andCAP_X402_OUT. The mapping lives inpolicy.toml([tokens]and[roles.*]tables) and can be changed at runtime viaPOST /admin/policy/roles.X-Admin-Tokenmust equal the deployment’sauth_tokenand gates lifecycle mutations: agent activation, payee registration and approval, and runtime policy changes.
export KERNEL=https://kernel.example.comexport TOKEN=my-session-token # maps to a role in policy.tomlexport ADMIN_TOKEN=my-admin-token # the deployment auth_token
# Sanity check: authenticated status callcurl -s "$KERNEL/status" -H "X-Imara-Token: $TOKEN"
# Define or update a role at runtime (admin)curl -s -X POST "$KERNEL/admin/policy/roles" \ -H "X-Admin-Token: $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "role": "finance_agent", "capabilities": ["CAP_VFS_READ", "CAP_NETWORK", "CAP_X402_OUT"], "max_actions_per_minute": 60 }'Registering an agent identity
Section titled “Registering an agent identity”Every agent gets an Agent DNA record: a UUID identity (the dna_id) bound to an Ed25519 public key, an owner, a zone, a jurisdiction, and an explicit capability grant. The kernel also mints a human-readable SRN alias of the form srn:<partition>:<region>:<account>:agent/<zone>/<name>, usable anywhere the UUID is.
Generate an Ed25519 keypair client-side and submit the raw 32-byte public key as hex (64 characters). The private key never leaves your infrastructure — the kernel only ever verifies signatures against the registered public key. Registration creates the record in PENDING; a separate, admin-authenticated activation call moves it to ACTIVE. Pass parentDnaId when a supervising agent spawns this one, so revocation cascades down the hierarchy. idemKey makes retries safe.
# 1. Register (returns 201 with the new dna_id, status PENDING)curl -s -X POST "$KERNEL/v1/agents" \ -H "Content-Type: application/json" \ -d '{ "agentName": "billing-bot", "publicKeyHex": "<64-char hex of the raw Ed25519 public key>", "ownerId": "9b2f6c1e-5f4a-4d2b-8c3e-7a1d9e0f2b45", "ownerName": "Finance Ops", "zone": "finance", "jurisdiction": "ZA", "capabilities": ["CAP_NETWORK", "CAP_VFS_READ", "CAP_X402_OUT"], "parentDnaId": null, "idemKey": "reg-billing-bot-001" }'
# 2. Activate (admin) — PENDING -> ACTIVE, recorded in the audit trailexport DNA_ID=<dna_id from step 1>curl -s -X PUT "$KERNEL/v1/agents/$DNA_ID/activate" \ -H "X-Admin-Token: $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "idemKey": "act-billing-bot-001", "approvedBy": "cto@example.com", "approvalReason": "Reviewed capability grant for production" }'
# 3. Verify authorisation (the hot-path check the kernel itself uses)curl -s "$KERNEL/v1/agents/$DNA_ID/verify"Governance: templates and the policy chain
Section titled “Governance: templates and the policy chain”Policy is layered like IAM: an org ceiling caps everything in the organisation, a zone ceiling caps the department, and each agent carries a compiled leaf derived from its own grant. A request must clear all three. Starter templates render the two ceiling documents from a handful of parameters — what you own afterwards is ordinary, editable policy documents, content-addressed by hash.
# Browse the template catalogcurl -s "$KERNEL/v1/policy-templates" -H "X-Imara-Token: $TOKEN"
# Preview what a template would render (dry_run saves nothing)curl -s -X POST "$KERNEL/v1/policy-templates/starter-retail/apply" \ -H "Content-Type: application/json" \ -d '{ "org_id": "<org uuid>", "dry_run": true }'
# Apply for real: renders, stores, and attaches org + zone ceilingscurl -s -X POST "$KERNEL/v1/policy-templates/starter-retail/apply" \ -H "Content-Type: application/json" \ -d '{ "org_id": "<org uuid>", "zone": "finance" }'
# Inspect the effective chain governing one agent# (org_ceiling -> zone_ceiling -> leaf, with document hashes)curl -s "$KERNEL/v1/agents/$DNA_ID/policy-chain"Re-applying a template with identical parameters is harmless — the documents are content-addressed, so the same hashes are re-attached. The chain endpoint returns the same resolution the enforcement gate performs, so “denied by policy” is always inspectable by hash.
Merchants: the payee registry
Section titled “Merchants: the payee registry”Agents can only pay merchants on the payee allowlist of their zone chain, and the registry is maker-checker enforced: the identity that registers a payee can never be the one that approves it. Registration creates the payee PENDING; approval by a different identity makes it APPROVED. Editing via /update resets the payee to PENDING with the editor as maker, so a second identity must re-approve before any agent can pay the edited merchant again.
# 1. Register a payee (admin) -> PENDINGcurl -s -X POST "$KERNEL/v1/payees" \ -H "X-Admin-Token: $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "zone": "finance", "displayName": "Cloud Vendor Ltd", "createdBy": "ops@example.com", "aliases": [ { "rail": "x402", "address": "0x1234abcd...ef56" } ] }'
# 2. Approve with a DIFFERENT identity (admin) -> APPROVEDexport PAYEE_ID=<payee_id from step 1>curl -s -X POST "$KERNEL/v1/payees/$PAYEE_ID/approve" \ -H "X-Admin-Token: $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "approvedBy": "cfo@example.com" }'
# Editing resets to PENDING and requires fresh approvalcurl -s -X POST "$KERNEL/v1/payees/$PAYEE_ID/update" \ -H "X-Admin-Token: $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "displayName": "Cloud Vendor (EU) Ltd", "updatedBy": "ops@example.com", "aliases": [{ "rail": "x402", "address": "0x1234abcd...ef56" }] }'Making governed payments
Section titled “Making governed payments”Agents never touch payment keys. Two data-plane routes move money, both requiring CAP_X402_OUT on the caller’s role and both fail-closed:
POST /v1/x402/fetchfetches an HTTP-402-protected URL. The kernel meets the paywall itself: it enforces the recipient allowlist and spend ceiling, signs the payment authorization with the kernel-held wallet key, retries with the payment signature, and records the settlement receipt in the ledger.POST /v1/proxy/fetchis the stricter, rail-neutral spend proxy. It requires a proven agent identity and a client-suppliedidempotency_key— retries replay the recorded outcome instead of paying twice. The merchant must be anAPPROVEDpayee. When a price crosses the escalation threshold the kernel answers202with anapproval_id; a human approves it in the console, and the agent collects by retrying with the same idempotency key plus that id.
# Governed fetch of a 402-protected resourcecurl -s -X POST "$KERNEL/v1/x402/fetch" \ -H "X-Imara-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://api.example.com/paid/report" }'
# Spend proxy: idempotency_key is requiredcurl -s -X POST "$KERNEL/v1/proxy/fetch" \ -H "X-Imara-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://api.example.com/paid/report", "method": "GET", "idempotency_key": "order-2026-08-11-001" }'
# If the kernel answered 202 { approval_id, ... }: after a human approves,# retry with the SAME idempotency_key plus the approval_idcurl -s -X POST "$KERNEL/v1/proxy/fetch" \ -H "X-Imara-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://api.example.com/paid/report", "method": "GET", "idempotency_key": "order-2026-08-11-001", "approval_id": "<approval_id from the 202>" }'Declines come back with stable reason codes you can branch on — MERCHANT_NOT_ALLOWLISTED, CEILING_EXCEEDED, POLICY_BLOCK, PRICE_CHANGED — while error strings stay free to change.
Where results land
Section titled “Where results land”Every payment attempt — allowed or denied — is observable in three console surfaces: the Feed shows the live event stream, the Ledger holds the tamper-evident entries (written before any reservation is released), and every payment gets a Trace covering the attempt end to end. Each trace carries the id of its ledger entry, so you can jump from “how the decision was reached” to “proof that it was”. Traces are also queryable over the API:
# Recent traces, filterable by agent, zone, status, or ledger entrycurl -s "$KERNEL/v1/traces?dna=$DNA_ID&limit=20" -H "X-Imara-Token: $TOKEN"
# One trace, end to endcurl -s "$KERNEL/v1/traces/<trace_id>" -H "X-Imara-Token: $TOKEN"
# Ledger entries and chain verificationcurl -s "$KERNEL/ledger" -H "X-Imara-Token: $TOKEN"curl -s "$KERNEL/ledger/verify" -H "X-Imara-Token: $TOKEN"See The audit ledger for how chain verification works and how to export the trail.