Skip to content

The agent contract

The agent contract is six signed documents an agent and a seller exchange for one purchase: before the call, during it and after.

One purchase, six documents

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.

DocumentServed atSigned byWhat it binds
Offer card/.well-known/agents.json, and inside every directory entrythe sellerThe price per unit, the terms digest, the refund rule, the seller's verified identity, the ways to pay and the latest attestation
QuotePOST /quote, at no chargethe sellerOne call's or one order's price, its input, the terms digest and an expiry; a purchase mandate may name it
Mandate presentationsent in Mandate; its status at the issuer's status URLeach issuer in the chainWho authorised which agent, for which sellers and Verbs, how much, in which currency and until when
Payment challengeinside a 402's offersthe sellerThe price, the terms digest, where to pay and the challenge id a proof answers; it is good for one call
Receipt/receipts/{id}, named by X-Receipt-Idthe sellerWhat was sold, delivered and paid, under which Definition, terms and mandate
Attestationits author's own address, and copied into the offer cardthe VerifierWhat it checked, how often, on how many calls, and the result per Verb

A seller lists its keys at /.well-known/receipt-keys on its own Host. A retired key stays listed with its dates, so an old receipt still verifies.

Offer card
18 lines
{
  "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.

402 Payment Required
14 lines
{
  "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.

FieldWhat it binds
sellerThe seller's Host and its verification level
verb, versionThe Verb sold, and the Version that served it
price, currency, paidWhat it cost, and how it was paid: balance, budget, in-call or tab
termsThe digest of the terms the call accepted
mandateThe mandate presentation the call carried, when an agent called
outputA digest of the reply body the buyer received
definitionThe Digest of the Definition the answer came from
kind, gradeThe Function kind that answered, and the assurance grade an outcome sold
upstreamThe receipts of every product this call bought from: the trace chain across composition
signatureThe 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.

Receipt
20 lines
{
  "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.

MarkWhat it bindsWhen it is used
IntentA scope and a budget: sellers, Verbs, amounts, currency and timeStanding and recurring spend inside the buyer's policy
PurchaseOne quote id and its priceOne purchase above the approval threshold, approved once by a person
PresentThe person is in the session and can step upA Verb whose risk asks for a fresh sign-in by the person
AbsentThe agent acts alone, inside its intentEvery other call
Mandate presentation
14 lines
{
  "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 lossWho repays itHow
A purchase inside the mandate the buyer regretsThe buyerIts budget; a refund only by the seller's published rule
A call served on a mandate already revoked or expiredThe sellerRefunded to the budget it came from, with no request
A purchase the buy side let through against the buyer's own policyAPIs.DevCredited to the budget, with the decision as evidence
An answer that misses its termsThe sellerThe 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.

PartWhat it does
MethodCalls every Interface with a Test key and sampled Live calls, and replays answers against their pinned Version
Cadence and samplesOn every publish, then on a schedule by plan; each attestation names its window and its number of calls
What it signsConformance, success rate, median time, first-time acceptance, freshness and coverage, per Verb
Where it livesAt the Verifier's own address under its own keys; the card's copy checks with no call to the seller
A contestThe 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: 'probation' buys inside lower limits, refuse skips it and allow treats it like any other.

MeasureWhat it countsCarried by
DisputesDisputes per thousand receipts, and how many were upheldSellers, suppliers and buyer agents
Refunds honouredRefunds the published rule owed, paid on timeSellers and suppliers
First-time acceptanceOutcomes accepted with no redoSellers and suppliers
On timeDeliveries inside their windowService sellers and suppliers
Payment recordChallenges paid, tabs settled and chargebacksBuyer agents
Volume and ageReceipts, and days since the firstEvery party

Disputes and discovery

Terms compile to checks a machine runs, so most disputes resolve on the receipt alone, with no person.

TermCompiles toDecided by
refund: 'wrong-answer'The reply fails its schema, differs from a replay against the pinned Version, or is older than freshThe replay, at once
An outcome's remedyThe acceptor's rejection inside acceptWithinThe Outcome contract
deliverWithinNo delivery inside the windowThe clock; the held funds return
Anything elseThe receipts, the call record and both parties' evidenceThe 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.