The record
Every job has one append-only record. Its status, its stage, its money and its ledger are replayed from it, and nothing else, so the record is the job.
The record answers one question: what happened on this job, in order, and who did it?
Every change to a job is an event appended to its record: the order, each step proposed and committed or refused, each review, each ask, each submission and its receipt, each AI decision, each signal, each charge. Nothing is edited or removed. The job's status, stage, what it waits on, its policy, its signals and its ledger are all replayed from the record and the step graph, never stored beside them.
check, the CLI and the apps print a record as one line, a step at a time:
→ POST /proofreaders/jobs/job_7Hq2/approve {"output":{"match":0.96}} record translate · ai · refused · guard_refused · match: below the match the client set (0.7 < 0.9) | translate · ai · redo | proof · proofreader · refused · guard_refused · match: below the match the client set (0.8 < 0.9) | proof · proofreader | review · ai · pass| Event | Audience | Holds |
|---|---|---|
job.ordered | buyer, owner | A buyer, or another of your Services, ordered the job at its pinned price, with their metadata. |
step.proposed | owner | A doer proposed a step's output: its hash, before the gate. |
step.committed | buyer, owner | The gate committed a step: the doer, the output hash, its files with sha256, its cite, and where its next sent the job. The buyer sees its stage. |
step.refused | owner | The gate refused a proposal, with the code and why. The doer's work stays open: the AI redoes it, and a person's step stays theirs. |
step.skipped | buyer, owner | A step's when said no, so it never ran. |
review.done | owner | A review finished a round: its kind, lenses, round, verdict, and review/<step>.json with the findings and signals. |
decision.made | owner | One AI call: the model it was pinned to, the hashes of what it read, and the brief and its version. |
job.paused | buyer, member, owner | The work paused on a person: an approval, a signature or their step; or on a party's ask, its clock paused. |
job.delivered | buyer, owner | The output is ready for the buyer. |
job.sent_back | buyer, owner | The buyer, the person at the line, or a member with the defects, sent the work back: to the step a member names, or the one before. |
job.accepted | buyer, owner | The buyer accepted, or 7 days passed after delivery. Final. |
job.canceled | buyer, owner | The job stopped: the buyer canceled, the AI cap ran out, or a step failed. The buyer pays $0. |
job.ended | buyer, owner | The job reached an end: lapsed, or one the Service declared, with what it owes there. An end is forever. |
job.at_risk | buyer, owner | Three-quarters of the job's within has gone while the work was the brand's. A wait on a party, an outside system or the client's direction never counts. |
job.late | buyer, owner | The job's within has gone while the work was the brand's: it is late. |
policy.set | buyer, owner | The buyer, or the brand's console, changed policy values within their bounds. |
signal.raised | buyer, owner | A named fact was raised: a predicate turned true, a silence ran its span, or an inbound call. Its goto moved the job. |
outcome.reported | buyer, owner | Your code reported what the job won, for a share. |
charge.held | buyer, owner | The buyer key holds the price, or the buyer's max for a share. |
charge.collected | buyer, owner | The buyer was charged: at delivery, or at outcome for a share. |
charge.earned | buyer, owner | The charges are final. |
charge.released | buyer, owner | A share's unused hold went back to the buyer key. |
charge.voided | buyer, owner | A stopped job dropped its hold. |
charge.refunded | buyer, owner | A stopped job gave back what it had charged, or an end gave back what it no longer owes. |
submission.sent | buyer, owner | A submit step sent one submission past the gate: its rcp_ receipt, transmitted, filed at the first submission's time for a repair inside perfect. |
receipt.accepted | buyer, owner | The outside system accepted a submission, with or without alerts. Once every one of the step's is accepted, a <step>.accepted charge releases. |
receipt.rejected | buyer, owner | The outside system rejected a submission, with its codes. A transition, never an error: the job goes to the repair the codes name, or after two rejections to the fallback. |
receipt.timed_out | buyer, owner | The outside system stayed silent past the step's wait: the job went to its fallback. |
ask.opened | buyer, owner | An ask step asked a party to act: the ask, its party, its expiry, its request list, and for a sign the output hash it binds. |
item.done | buyer, owner | One item of an ask's request list came in: answered, waived with a reason, or substituted. |
ask.reminded | buyer, owner | The party was reminded, before the ask's link expires. |
ask.done | buyer, owner | The party acted, or declined: through their link, or as a delegated agent for an answer or an upload. A decide records its choice. |
ask.expired | buyer, owner | The ask's link expired. It opens once more; a second expiry lapses the job. |
ask.voided | buyer, owner | The ask was voided: another party acted, the job ended, or what was signed changed past its tolerance (signature_void), and a new ask opened. |
ask.relinked | buyer, owner | The ask's link was reissued; the old one stopped working. |
grant.given | buyer, owner | The party gave a grant through their own link: the acts it permits, and until when it is live. A step that needs it can run. |
grant.expired | buyer, owner | A grant ran out at its until. A step that needs it is refused needs_grant, and the party is asked to grant it again. |
grant.revoked | buyer, owner | The party revoked their grant through their own link: it stopped being live at once. A step that needs it is refused needs_grant from then on. |
member.applied | owner | An application to a Pool is complete: the member, the Pool and every answer, for the Pool's verifier, which writes back only what it checks. It goes to the Pool's verify URL, signed and retried; on localhost it lands in the owner's feed and the fixture verifier answers. |
task.posted | member, owner | A role step posted a Task at its fee, fixed now and never lowered, to its dispatch: or to the one member a client's direct named. Its reach says who it can be offered to. |
task.unreached | owner | A Task posted that no member reaches: eligible, but every one is outside what they declared, or no one is eligible. The owner console alarms; the ladder climbs on. |
task.offered | member, owner | A Task was offered to a member, by its dispatch (feed or cascade), first refusal or the owner: its teaser, with its minutes, rate and due date, and never a party name. |
task.claimed | member, owner | A member claimed a Task: it is held for them, gone from every other feed, until they clear it or the hold runs out. |
task.hold_expiring | member, owner | Three-quarters of a member's hold on a Task has run: it reopens at held_until unless they finish, or extend it once. |
task.extended | member, owner | The member extended their hold, once: by as long again as it first held, never past the due date. |
task.due_moved | member, owner | A quorum of the members who read a Task's sheet passed on its timing: its due date moved a day. |
task.raised | member, owner | The fill ladder raised a Task no one claimed: a share of the posted fee, up to its cap, and who funds it. A fee is never lowered. |
task.widened | member, owner | The fill ladder opened a Task no one claimed to the next tier down that is still eligible, or to staff who hold its credential. |
task.declined | member, owner | The member declined, with a memo only the client reads: paid, never scored. The job waits on the client's direction. |
task.recused | member, owner | The member stepped aside for a conflict: nothing accrues and nothing is scored, the Task reopens at once, and they are screened from every Task on the subject. The client reads that a professional stepped aside. |
task.contested | member, owner | The member contested a send-back their attested work received, with a reason, for the owner or a staff role to rule on. |
task.ruled | member, owner | The owner, or a staff role, ruled on a contest: the send-back upheld or overturned. |
thread.posted | buyer, owner | A post in the job's thread: the client's message, a member's question, note or flag, the party's reply, or a member's memo on advice they declined. |
message.sent | buyer, owner | An answer went out in the thread: the AI's, at once, or held advice once a member adopted it, under their name, credential and region. |
message.held | owner | The AI's answer fell in an advice class a rules row reserves: held as a proposal and posted as a Task to the adopt role. The client reads that a professional is reviewing it. |
message.adopted | member, owner | A member adopted held advice, as written or edited: their name, credential, region, the hash and the rules version, frozen on the record. |
tier.changed | member, owner | The member's tier changed, with the rule that moved them. |
pay.accrued | member, owner | A member's pay for a paid act accrued: an attestation, a send-back or a decline at the Task's fee as it stood, with the raise the brand funds; or a kill fee when a Task they cleared is withdrawn. A buyer's send-back or a withdrawal never claws it back. |
pay.payable | member, owner | An accrued pay became payable, on its own clock after the act, and joins the member's next payout. |
consent.given | buyer, owner | The client consented to what a Pool's sheet shows the members who read it, and to whom, before the first Task posted: through their own link. |
succession.started | member, owner | The member of record began to withdraw, naming a successor: the seat stays theirs until the successor clears conflicts and accepts it. |
succession.accepted | member, owner | The successor cleared conflicts against the subject's parties and accepted the seat: they are of record from now on. |
clock.opened | buyer, owner | A clock opened: its name, the Service, where it lives, its date resolved on the calendar (due, due_on, zone) and a hash of its spec. Every later change to it is an event, so the record alone rebuilds it. |
clock.unopened | owner | The Service's own code couldn't give a clock's date: its due function threw, or returned something that isn't a date. Recorded once, with why; the owner console alarms until it opens. |
clock.noticed | buyer, owner | A clock's notice rung: its owner is told the date is coming. |
clock.escalated | buyer, owner | A clock's escalate rung: the date is close, and the owner console hears of it beside the owner. |
clock.ack_due | buyer, owner | Inside an ack daily rung's window, the day's acknowledgement is due from the clock's owner. |
clock.ack_missed | buyer, owner | The day passed with no acknowledgement from the owner: recorded, and the next day's is due. |
clock.ran | buyer, owner | A clock's run rung sent the job to its routed step, which proposes through the gate like any other. One that can't send, or that the gate refuses, is held (held names why): it escalates at once, stays armed, and proposes again. With no live work, the rung is recorded and nothing runs. |
clock.moved | buyer, owner | A step the clock's moves names committed: its date moved, from and to. Every other clock stays where it was. |
clock.due | buyer, owner | The date came with the clock unsatisfied: it waits on its owner's choice of the lapse options. Nothing lapses silently. |
clock.satisfied | buyer, owner | The clock closed on evidence on the record: the step it is named for committed, or its owner sent the evidence, a file or a receipt the job holds. |
clock.rolled | buyer, owner | The calendar rolled a clock's date past a weekend or a closed day: from, to, and why. |
clock.recurred | buyer, owner | A recurring clock was satisfied, and its every brought its next occurrence: its date, counted from the first so it never drifts, with its rungs. |
clock.vacant | owner | No one answers for a running clock, such as one owned by a vacant seat of record: its owner is null, and the owner console alarms. |
clock.acked | buyer, owner | The clock's owner acknowledged it: inside an ack daily window, the day's acknowledgement, so the day is never missed; else the rung that last fired. |
clock.chosen | buyer, owner | At the date, the owner chose one of the clock's lapse options, and the clock closed. A step's name sends the job there, through the gate. |
clock.assigned | buyer, owner | Someone answers for the clock now: the owner console assigned a member, or the client signed that they own the date. |
clock.outlived | buyer, owner | The job ended with the clock still running on its subject. Unless the subject's steward Service keeps it, the client is asked to sign that they own the date. |
subscription.created | buyer, owner | An order of a Service whose price has every is a subscription: its first cycle charged, when the cycle ends, and its subject. |
subscription.renewed | buyer, owner | A cycle ended and the next began: charged again, and every allowance reset. |
subscription.minted | buyer, owner | A schedule date came or an event arrived: the job it minted, from the subscription with its subject and policy; the extra job offered at its price; or the refusal, such as period_taken, recorded on the subscription. |
allowance.used | buyer, owner | A job inside an allowance: $0 on the job, counted, with how many of the cycle's are used. |
allowance.exceeded | buyer, owner | An order past an allowance: the extra job is offered at its price, 402 OFFER, with the exact next call. |
subscription.canceled | buyer, owner | The subscription was canceled: it runs to the end of the cycle paid for, never renews, and nothing mints after. |
board.updated | public, owner | A Pool's demand board changed: its aggregates, never a job. |
The owner reads the whole record, in the owner console and through GET /owner/jobs/:id. A buyer never does. A buyer's job carries its status, stage, payment and steps, and a buyer's events carry only the facts listed for the buyer above: never a proposal, a refusal, a review's findings or an AI decision.
curl http://localhost:8787/jobs/job_7Hq3 # input, price and next left out; a buyer never reads the record{
"id": "job_7Hq3",
"object": "job",
"created": "2026-10-25T14:02:11.000Z",
"livemode": false,
"service": "certified-translation",
"status": "waiting",
"on": "signature",
"waiting": {
"on": "signature",
"since_at": "2026-10-25T14:02:11.000Z"
},
"stage": "review",
"payment": {
"status": "held",
"amount_usd": 189
},
"metadata": {
"docket": "ACME-17"
},
Each committed step carries the hash of its output, so the buyer sees what committed, and a signature's subject, without reading the record.
Each committed step records the hash of its output and the sha256 of every file it produced. A signature or a stamp binds a hash, so a later change is caught:
→ POST /owner/jobs/job_7Hq2/approve signed sha256:bf0eee586b6d, then sha256:a1ae472c5c3b
filed under sha256:a1ae472c5c3b: the second signature, over the document as it leftReplaying a record reproduces the job bit for bit, with every AI decision at its pinned model. See evidence and replay. Clocks replay the same way: every change to a clock is an event on the record, each one a rung or a date owes naming when it was owed, so the events alone rebuild every clock (A year, and the next rebuilds twelve). Every status a replay can reach is on the job lifecycle.
A person's act lands on the same record as the AI's: who acted, under which credential, in which region, and what they earned. In the legal example a patent practitioner attests a provisional application, in their own session:
→ POST /reviews/tsk_7Hq2/attest {"checklist":["the claims read on the disclosure","every inventor is named","a reasonable inquiry was made"]} # as mbr_eligible← 200 tsk_7Hq2 · done · practitioner · sign · * · $150.00 · attested · 60 min · $150.00 an hour · due 2026-10-30 14:02
14:02 · step.committed · sign · person · patent attorney · * · mbr_eligible
14:02 · pay.accrued · mbr_eligible · attest · $150.00The owner reads every act in order, the Task's own events among them (the legal brand calls a Task a review):
→ GET /owner/matters/job_7Hq2 # the owner console record consent · applicant · consent | questions · applicant · answer | draft · ai | examine · ai · adversarial · 4 lenses · flagged | draft · ai · redo | examine · ai · adversarial · 4 lenses · pass | sign · person · patent attorney · * · mbr_eligible | file · USPTO · accepted · rcp_7Hq2
events matter.ordered · charge.held · ask.opened · matter.paused · consent.given · ask.done · step.proposed · step.committed · ask.opened · matter.paused · ask.done · step.proposed · step.committed · decision.made · step.proposed · step.committed · decision.made · decision.made · decision.made · decision.made · review.done · step.proposed · step.committed · decision.made · step.proposed · step.committed · decision.made · decision.made · decision.made · decision.made · review.done · step.proposed · step.committed · matter.paused · review.posted · review.offered · review.claimed · matter.paused · step.proposed · step.committed · pay.accrued · submission.sent · receipt.accepted · step.proposed · step.committed · charge.collected · matter.deliveredMessages in the job's thread are on the record by the hash of their words: see Talk. Data classes, which decide who reads which fact, are the data key's. Each job's trace, its ledger and the AI it spent are read from this record: Observe.
| Op | API | CLI | MCP | SDK | Site | Docs | App |
|---|---|---|---|---|---|---|---|
job.ledger | GET /owner/jobs/:id | jobs ledger <job> | never: a person acts | never: a person acts | 1 error page | owner console | |
event.list | GET /events, GET /owner/events | events list | list_events | events.list() | 1 error page | customer portal, owner console | |
event.stream | GET /events/stream | listen [--forward-to <url>] | never: a stream, not a call: an agent reads list_events after a seq, or job:// for one job | events.stream() | 2 error pages | customer portal |
Operations has every column of every row.
| Code | Category | HTTP | Why |
|---|---|---|---|
not_found | invalid_request | 404 | Nothing has that id. |
needs_a_person | blocked | 403 | A person approves and signs, in the app. A key or a tool never can. |