The agent contract
Open in
The agent contract is six signed documents an agent and a seller exchange for one purchase: before the call, during it and after.
Each document is signed by its author and checked by the other side alone. Filled: what the buyer holds. The point marks the money you are paid.
The six documents
Each document is JSON with a contract version, signed with an Ed25519 key its author lists, and served at one fixed address.
A field is added in place. A breaking change ships a new contract version beside the old one, and both answer until the old one retires.
| Document | Served at | Signed by | What it binds |
|---|---|---|---|
| Offer card | /, and inside every directory entry | the seller | The price per unit, the terms digest, the refund rule, the seller's verified identity, the ways to pay and the latest attestation |
| Quote | POST /, at no charge | the seller | One call's or one order's price, its input, the terms digest and an expiry; a purchase mandate may name it |
| Mandate presentation | sent in Mandate; its status at the issuer's status URL | each issuer in the chain | Who authorised which agent, for which sellers and Verbs, how much, in which currency and until when |
| Payment challenge | inside a 402's offers | the seller | The price, the terms digest, where to pay and the challenge id a proof answers; it is good for one call |
| Receipt | /, named by X-Receipt-Id | the seller | What was sold, delivered and paid, under which Definition, terms and mandate |
| Attestation | its author's own address, and copied into the offer card | the Verifier | What it checked, how often, on how many calls, and the result per Verb |
A seller lists its keys at /.well-known/ on its own Host. A retired key stays listed with its dates, so an old receipt still verifies.
{
"contract": "1",
"seller": { "host": "companyfacts.apis.dev", "verified": "business" },
"offer": {
"rates": [
{ "name": "Company.get", "price": 0.002, "currency": "USD",
"unit": "answer", "miss": 0 }
],
"quote": "POST /quote",
"terms": { "digest": "sha256: 2c0055d1", "refund": "wrong-answer",
"license": "internal-use" },
"pay": ["checkout", "budget", "in-call", "tab"],
"proof": { "by": "verifier", "window": "90d", "calls": 12000,
"success": 0.998, "signed": "2026-10-27T06: 00: 00Z" }
},
"keys": "/.well-known/ receipt-keys",
"signature": "ed25519: Lq0dN6w4Hc2vYp8tRk1mZf3xBa7sJe5u"
}An unpaid agent meets the challenge inside the 402's offers, beside Checkout for a person.
{
"type": "https: //companyfacts.apis.dev/ docs/ errors#payment_required",
"title": "Payment Required",
"status": 402,
"detail": "Company.get costs 0.002 USD, and the call carries no payment.",
"code": "payment_required",
"offers": [
{ "kind": "checkout", "pack": 10, "url": "https: //companyfacts.apis.dev/ checkout/ pack_10" },
{ "kind": "challenge", "id": "chl_4Fz9", "price": 0.002, "currency": "USD",
"terms": "sha256: 2c0055d1", "pay": ["in-call", "tab"],
"expires": "2026-10-27T09: 05: 00Z" }
],
"instance": "req_9b3f6e2a0d71c48e5a16"
}The receipt
A receipt binds one priced call to what it delivered, under which terms, mandate and Definition, so any party checks it alone.
| Field | What it binds |
|---|---|
seller | The seller's Host and its verification level |
verb, version | The Verb sold, and the Version that served it |
price, currency, paid | What it cost, and how it was paid: balance, budget, in-call or tab |
terms | The digest of the terms the call accepted |
mandate | The mandate presentation the call carried, when an agent called |
output | A digest of the reply body the buyer received |
definition | The Digest of the Definition the answer came from |
kind, grade | The Function kind that answered, and the assurance grade an outcome sold |
upstream | The receipts of every product this call bought from: the trace chain across composition |
signature | The seller's signature over every field above |
A buyer checks the signature against the seller's keys. It checks the output digest against the body it received, and the mandate against its own receipt stream.
{
"contract": "1",
"id": "rcpt_2",
"request": "req_7d1e04b9c35a8f2e6b10",
"seller": { "host": "summaries.apis.dev", "verified": "business" },
"customer": "cus_Acme",
"verb": "Company.research",
"version": "v3",
"price": 0.5,
"currency": "USD",
"paid": "budget",
"terms": "sha256: 8b41e7c2",
"mandate": "mp_7Hq2",
"output": "sha256: 5e0c9a17",
"definition": "d41f7a20c9e3",
"kind": "agentic",
"upstream": ["companyfacts.apis.dev/ receipts/ rcpt_1"],
"at": "2026-10-27T09: 00: 04Z",
"signature": "ed25519: Vn3pQ8aT1kLx6Rb0Zc4Wm9Ys2Fh7Dj5e"
}The mandate
A mandate starts at a person's own sign-in, and each hop to a sub-agent signs a narrower link below it.
| Mark | What it binds | When it is used |
|---|---|---|
| Intent | A scope and a budget: sellers, Verbs, amounts, currency and time | Standing and recurring spend inside the buyer's policy |
| Purchase | One quote id and its price | One purchase above the approval threshold, approved once by a person |
| Present | The person is in the session and can step up | A Verb whose risk asks for a fresh sign-in by the person |
| Absent | The agent acts alone, inside its intent | Every other call |
{
"contract": "1",
"id": "mp_7Hq2",
"chain": [
{ "by": "dana@acme.com", "for": "org_acme", "signed": "passkey" },
{ "by": "org_acme", "to": "researcher", "mark": "intent",
"sellers": ["summaries.apis.dev", "companyfacts.apis.dev"],
"month": 150, "task": 20, "currency": "USD", "until": "2027-01-25" }
],
"present": false,
"status": "https: //acme.com/ .well-known/ mandates/ mp_7Hq2",
"expires": "2026-10-27T09: 05: 00Z",
"signature": "ed25519: Hk2sP9wQ4mTz1Lc7Ra0Nv5Bx8Ye3Gj6u"
}A presentation lives five minutes, and the seller verifies its chain with no call to the buyer. The issuer's status URL answers active or revoked, so a revocation reaches every seller within that window.
| A loss | Who repays it | How |
|---|---|---|
| A purchase inside the mandate the buyer regrets | The buyer | Its budget; a refund only by the seller's published rule |
| A call served on a mandate already revoked or expired | The seller | Refunded to the budget it came from, with no request |
| A purchase the buy side let through against the buyer's own policy | APIs.Dev | Credited to the budget, with the decision as evidence |
| An answer that misses its terms | The seller | The remedy the terms name, through a dispute |
Proof, the Verifier and track record
The Verifier stands outside every product and its platform: it calls each product as a buyer would and signs what it finds.
| Part | What it does |
|---|---|
| Method | Calls every Interface with a Test key and sampled Live calls, and replays answers against their pinned Version |
| Cadence and samples | On every publish, then on a schedule by plan; each attestation names its window and its number of calls |
| What it signs | Conformance, success rate, median time, first-time acceptance, freshness and coverage, per Verb |
| Where it lives | At the Verifier's own address under its own keys; the card's copy checks with no call to the seller |
| A contest | The seller names call ids; the Verifier runs them again, then signs a new attestation or keeps the old with its reason |
A product with no history sells on probation. Its card shows a conformance pass, the seller's verified identity and a refund backed by funds held from its payouts.
A buyer's policy says how it treats such a product: unproven: buys inside lower limits, refuse skips it and allow treats it like any other.
| Measure | What it counts | Carried by |
|---|---|---|
| Disputes | Disputes per thousand receipts, and how many were upheld | Sellers, suppliers and buyer agents |
| Refunds honoured | Refunds the published rule owed, paid on time | Sellers and suppliers |
| First-time acceptance | Outcomes accepted with no redo | Sellers and suppliers |
| On time | Deliveries inside their window | Service sellers and suppliers |
| Payment record | Challenges paid, tabs settled and chargebacks | Buyer agents |
| Volume and age | Receipts, and days since the first | Every party |
Disputes and discovery
Terms compile to checks a machine runs, so most disputes resolve on the receipt alone, with no person.
| Term | Compiles to | Decided by |
|---|---|---|
refund: | The reply fails its schema, differs from a replay against the pinned Version, or is older than fresh | The replay, at once |
An outcome's remedy | The acceptor's rejection inside acceptWithin | The Outcome contract |
deliverWithin | No delivery inside the window | The clock; the held funds return |
| Anything else | The receipts, the call record and both parties' evidence | The arbiter |
The seller answers within 5 business days, or the dispute is upheld. The arbiter decides within 10 more, and a person hears an appeal.
A card dispute arrives from Stripe and runs on Stripe's rules, answered with the same receipts. A refund on an irreversible rail is a new payment from the seller's balance.
Discovery and quotes
search on the buy side takes a capability and answers offer cards from listed products, ranked by the buyer's own selection policy.
A quote binds until expires. For a Service API or a Marketplace, a request for quotes reaches several sellers at once, and each answers before its expiry.
Every document names its author and its version, so a buyer and a seller agree on a purchase without taking each other's word.