Hanzo

Legal

Package legal is the paperwork your company needs, drafted, signed and filed.

Package legal is the paperwork your company needs, drafted, signed and filed.

Base URLhttps://api.hanzo.ai
Operations11
AuthAuthorization: Bearer $HANZO_API_KEY

Specification

HIP-1135 · Legal — Documents Drafted, Signed and Filed — Draft · read the specification →

/v1/legal is the paperwork an org needs, drafted, signed and filed: a versioned, org-overridable library of standardized templates, a pure merge-field engine that renders them from the org's own data, a sealed store for the generated documents, and the e-signature and filing seams that carry a document to execution. It is implemented in hanzoai/cloud at apps/legal (HIP-0106).

Motivation

Formation and securities paperwork is templated work over data the platform already holds — the company record, the cap table. What must never be templated away is the boundary: the platform manages documents; it does not give legal advice and does not determine that a document is valid or sufficient. That boundary is a design invariant enforced in the engine and the data model, not a disclaimer pasted on a page (apps/legal/model.go:10-18).

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in RFC 2119.

§1 The store and the renderer

One encrypted SQLite file, the deployment's own legal, opened through the one opener so it is born encrypted (apps/legal/store.go:30) — a rendered contract carries names and terms and is sealed on disk. The renderer is text/template and pure: deterministic, no clock, no I/O, so the same inputs yield identical bytes and a rendered contract is reproducible (apps/legal/model.go:20-24).

§2 The boundary in the model

There is no legally_valid state: a document is draft, out_for_signature, signed or voided, nothing more. Formation and securities templates carry a mandatory counsel-review notice the engine prepends to every rendered document — the platform can never emit such a document without it (apps/legal/model.go:13-18). A disclaimer rides on every generation and template response.

§3 The address

Eleven operations under /v1/legal, all typed except one. The exception is POST /v1/legal/documents/{id}/sign/complete, untyped by design: it discards its decode error so a provider-reported completion still lands when the callback body is unparseable — the typed layer refuses such a body before the handler runs, so typing it would turn today's 200 into a 400 (apps/legal/legal.go:87-91). The provider's own status is checked first; an explicit body signal exists for the stub (apps/legal/legal.go:170-182). A 1 MiB body cap sits in front of every route, registered before the typed ops because a size check inside one would run after the parse it exists to precede (apps/legal/legal.go:66-77).

§4 The seams fabricate nothing

E-signature and filing are provider-agnostic seams with honest stub defaults: a seam with no real backend records an honest state and never fakes a completed signature or a filed record (apps/legal/providers.go:10-16). Every generate, sign and file action is recorded on the shared tamper-evident audit plane, referencing opaque document ids (apps/legal/model.go:26-28).

§5 Tenancy, money, events, observability, stage, upstream

The tenant is principal.Org off the validated principal (HIP-0026), read back from what the composer's bridge parked — never a header, never an In field (apps/legal/legal.go:156). Free (cloud.Free, plugin/legal/main.go). It publishes nothing on the bus and emits nothing beyond the request span; the audit records above are the audit plane's, not telemetry. Stage beta: a vertical application. It derives from no upstream — the renderer is the Go standard library's text/template and the templates are authored here.

Rationale

The alternative to a pure renderer is one that reaches for live data at render time, which makes a contract unreproducible: the same request on two days yields two different documents and no record of why. Determinism is what makes the sealed store an archive rather than a cache. The alternative to honest stubs is refusing to mount without providers, which would couple a template library to two vendor contracts nobody needs on day one.

Security Considerations

A legal store is a disclosure surface — names, terms, equity — so documents are sealed at rest and the tenant is never an input. The execution path is where a wrong implementation does real-world harm: a seam that fabricated a "signed" or "filed" state would manufacture legal evidence, which is why the stubs are honest and completion consults the provider before any caller-supplied signal. The completion endpoint is org-scoped and moves only the document's status; it mints no provider record.

Four surfaces

SurfaceReaches this capability asCoverage
RESTlegal at its own prefix11 operations
CLIhanzo legal …11 of 11
SDKLegalApi in every published client11 methods
MCPtool legal on https://api.hanzo.ai/v1/mcp11 operations, 1 under the document's own id — ask describe for the rest

Quickstart

export HANZO_API_KEY=sk-...   # console.hanzo.ai → API keys

Then the first call — a read that needs nothing but the key. GET /v1/legal/health, operation get_legal_health:

hanzo legal health

Answers 200 with object — ok.

Endpoints

EndpointWhat it does
POST /v1/legal/documents/{id}/sign/completeRecord that a generated document's signature request completed
POST /v1/legal/documents/{id}/signOpens an e-signature request over one document and moves it to out_for_signature, returning the provider's reference for the request.
GET /v1/legal/documents/{id}Returns one of the org's documents WITH its rendered body.
GET /v1/legal/documentsReturns the org's generated documents, newest first, WITHOUT their rendered content — fetch one document to read its body.
POST /v1/legal/documentsRenders a document from a template and the caller's own merge data, seals it in the org's store, and returns it with its rendered body.
GET /v1/legal/filingsReturns the org's filing records, newest first — which documents were filed where, through which provider, and what the filing's honest status is.
POST /v1/legal/filingsRecords a filing of one or more of the org's documents with a state or agency, and returns the tracking record.
GET /v1/legal/healthReports that the legal subsystem is serving and how many built-in templates its catalog carries.
GET /v1/legal/templates/{id}Returns one template resolved for the caller's org — the org's own override if it has saved one, else the built-in — with its full text/template body…
PUT /v1/legal/templates/{id}Saves the org's own version of a template — a custom NDA, a house MSA — and returns it with its new version number.
GET /v1/legal/templatesReturns the org's effective template catalog: every built-in template, with any the org has overridden replaced by its own latest version.

All Hanzo APIs · Interactive reference

How is this guide?

On this page