This reference is generated from the same routes manifest the service ships — path, method, and request/response examples as JSON. The base path is this host; requests and responses are application/json.
API reference
Matters
The Matter is the unit of legal work — one Client, one legal objective, advanced through the six Stage Verbs (intake, prepare, examine, review, sign, file) to a terminal outcome. Stage is derived from the append-only journal; terminal is forever.
POST/matters
Mint a Matter and its Asset. A ratified matterType is required (400 otherwise) — jurisdiction derives from the Jurisdiction Rules table against the matter facts. The Asset carries lineage, docket, and a Deadline Ladder.
One turn of propose → gate → commit. If the next act is in the Reserved-Act Catalog, the service escalates instead: it posts a Gig to gigs.lawyer and the Matter waits on a Signer.
Request
{
// optional B2H2A override, merged over the agent's Proposal"merits": { "settlementUsd": 60000, "clientDirectionSeq": 1 }
}
POST/matters/:id/gig-resultsigned by a credential-holder
The gigs.lawyer callback. 'attested' commits the reserved act with the Signer's Attestation; 'send_back' returns the Matter to prepare with defects journaled; 'declined' journals the memo and the Matter needs the Client's direction — a Declination is final.
Journal the Client's instruction — the only event that reopens a Matter a Declination has stopped. Captured from the actual Client; a Tenant's agent cannot manufacture the Client's yes.
Request
{ "instruction": "proceed with a narrowed claim set", "authorizes": { "settlementUsd": 60000 } }
Journal the Client's Consent — the captured informed-consent artifact (limited scope, tenant data access). Required before a B2A2D Matter advances past intake. Executed by the actual Client: any other actor is refused with 422 — a Tenant's agent cannot consent on the Client's behalf.
The two-rail Settlement, only on a fulfilled Matter. Patent rail: platform as provider — flat Legal Fee to the Signer, Product Fee to the Customer. State rail: the Signer is merchant of record for the Legal Fee (recorded, never platform revenue). Both carry the per-act insurance line.
Clock-driven safety machinery on the Asset — deterministic (an explicit tick drives the clock, never wall time), closed only by evidence, daily human acknowledgment inside the final week, and an enumerated terminal rung.
GET/deadlines/:assetId
The ladder's state: days remaining, alarm (nominal | vacant), vacancy, the Monitoring Engagement holder, ack window, resolution — and on recurring obligations (franchise tax) the next occurrence and past-occurrence history.
Name who holds the Monitoring Engagement on this Asset — a Signer id, or 'platform' for open watch machinery. Naming an owner clears vacancy: dead air has a NAMED owner, never an anonymous one.
Close the deadline by evidence — the receipt. On a one-shot ladder this resolves it forever; on a RECURRING obligation (DE franchise tax) it resolves the current occurrence and rolls nextOccurrence forward one cadence — the obligation never closes this way, it recurs.
Choose the enumerated terminal-rung outcome at t-0 — clientNotice, extensionPurchase, proSeHandoff, or outsideCounselHandoff. Nothing else is a legal answer to t-0; 409 off the terminal rung. On a recurring obligation this is the ONLY permanent closure — a handoff ending the platform’s watch.
The families a practice-management client runs on: the append-only journal, the Attestation view, the three exit terminals, the Asset register, document metadata, and the per-practitioner Conflicts Ledger — everything derived from the kernel, never authored beside it.
GET/matters/:id/journal
The append-only Event journal. Stage derives from it; terminals are inserts, never mutations.
One of the three exit terminals, forever: withdrawn requires byClient (the Client terminates, nobody else); lapsed requires confirmedUnresponsiveTwice; referred_out requires referredTo. 'fulfilled' commits only off a filed receipt via the lifecycle.
Append one hashed party name to the practitioner’s Conflicts Ledger — hashes at rest, plaintext held by the practitioner, never pooled across practitioners. There is no update and no delete door. On the top-level surface this family rides a verified practitioner credential and answers a typed BLOCKED naming the upgrade path until id.org.ai license verification is live; inside a sandbox workspace it is open on synthetic state.
The per-grain event tail and its delivery wire — derived from the grain journal by replay, never stored beside it. Three feeds over one tail: timeline (everything, in order), reminders (reminder.* events fired by Deadline Ladder rungs, each addressed to the Monitoring owner — or carrying the vacancy alarm), and time (events carrying a named actor: acks, consents, attestation outcomes, client directions).
GET/events
The tail — typed OK | EMPTY, append-only, cursored with ?after={seq}, filtered with ?feed=timeline|reminders|time, bounded with ?limit (default 100, max 500).
Response
{
"type": "OK",
"appendOnly": true,
"latestSeq": 4,
"results": [{ "seq": 3, "at": "…", "kind": "reminder.notice", "subject": "a_1",
"summary": "t-30 notice — Asset a_1 is 30 days from its statutory deadline",
"deliverTo": "sg-1", "data": { "atDaysRemaining": 30 } }]
}
GET/events/stream
The live wire (Server-Sent Events, under Accept: text/event-stream — what EventSource sends): backlog first, then every new event as it lands — frames named 'grain-event' with the seq as SSE id, so Last-Event-ID resumes a dropped connection. A plain GET answers a typed descriptor naming the subscription contract. A reminder reaching a subscriber here IS the delivery the ladder promises.
Anonymous self-serve provisioning — the no-ask-zone applied to tenancy. A workspace is the practice-management grain (the buyer there is a Customer); a tenant is the demand-substrate integrator grain. Both are keyless, synthetic, TTL-bound, and every envelope under them carries provenance { environment: "sandbox", simulated: true }.
POST/workspaces
Provision an ephemeral workspace with synthetic seed state. The FULL practice contract mounts under /workspaces/:id — same routes, same envelopes, no consequences: Gig escalations are answered in-process and you play the Signer via the workspace’s own gig-result door. Anonymous grains expire on a TTL; creation is bounded per caller (429, typed).
The magic fixtures — named, deterministic, contract-tested identities and scenarios every workspace honors (a Signer that always verifies eligible, one that always fails standing, one whose Coverage has lapsed since verification, an always-conflicting party, an always-ack-due Asset, a notice-eve Asset whose first tick fires the t-30 reminder onto the event tail, and the two Clients: the Declination path and the clean walk to fulfilled). Script against these instead of poking at seed state.
Provision an ephemeral Tenant: declare Offers (flat-priced — the schema cannot express a percent-of-outcome price) and routing mechanics (Tenant Guardrails only; a merits-bearing field is a 422 before it is a policy question), then mint Matters against them.
Provision an ephemeral FIRM grain — the envelope of ADR 0014, never an actor: it holds member-executed Enrollment grants (the caller plays the member, enrolling from the named fixture bench at GET /firms/:id/fixtures) and reads GET /firms/:id/roster — a projection computed per read from the eligibility lattice’s binary facts (credential live, standing fresh, coverage in force). No Register is consulted, nothing is scored, and a revoked Enrollment blanks the row. The production family rides the same grain: PUT /firms/:id/routing (mechanics only — a merits key is a 422 type error; opt-ins member-countersigned), GET /firms/:id/remittances (a rollup view that aggregates — the money mechanics stay individual), and the envelope conflicts posture ledger with its Clearance pre-screen (GET /firms/:id/conflicts, POST /firms/:id/conflicts/entries, POST /firms/:id/conflicts/prescreen).
The data-product rails (empty-but-real until a SKU is live) and the published test suite — proof artifacts, not adjectives.
GET/catalog
The data-SKU catalog. Zero listed today — a typed EMPTY that carries the declaration contract (posted flat price, fee line, Merchant of Record, meter grain, and the data ProofPredicate: "no record, no charge"). A SKU appears only when it is live, priced, and metered.
Response
{ "type": "EMPTY", "skus": [], "message": "no data SKU is listed — …", "meterPromise": { "promise": "No record, no charge." }, "skuContract": { … } }
GET/verify/suite.json
The digest-pinned public-contract suite (api.qa/suite@1): declarative GET rows over the live doors, runnable by anyone — the autonomous-qa verifier against the live origin, the @law/api verify export, or plain curl. The pin is printed on /verify.
Refusals are typed and worded: 404 for a Matter or Asset that does not exist, 409 when the Matter is waiting_on_signer, terminal, or stopped by a Declination, 422 when the Gate refuses a Proposal (mechanics, merits, or a missing Attestation), and 502 when gigs.lawyer refuses a Gig post. The Gate speaks only to refuse — a 2xx is the journal committing.