Hanzo

Company

Package company is incorporation end to end: pick a structure, add founders, pay, file, and e-sign.

Package company is incorporation end to end: pick a structure, add founders, pay, file, and e-sign.

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

Specification

HIP-1312 · Company — The Formation Machine — Draft · read the specification →

/v1/company brings a legal entity into existence and records who owns it: choose a structure, add founders, clear identity, pay the formation fee, generate documents, route signature, anchor the equity genesis. The implementation is hanzoai/cloud apps/company.

The capability is a guarded state machine — a closed table of stages and the edges between them (apps/company/machine.go) — plus provider seams that reach the outside world (apps/company/providers.go). HIP-0903 argues why a firm should run this way; this is the contract the surface answers to.

Motivation

Formation is a sequence where every step depends on a fact an earlier one established, and most of those facts are legal rather than technical: money must not move before identity clears, and an entity must not be reported as formed before it is.

Enumerating what a caller may do — a permission list — fails in the direction that matters here. A list has gaps, and a gap is a company incorporated without a verified person behind it. A closed edge table has none: the illegal move is not forbidden, it is absent.

Specification

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

§1 The machine

Two paths reach the terminal stage, every edge carrying a guard (apps/company/machine.go): incorporatestructure → founders → payment → documents → esign → genesis → company, guarded by structure chosen, identity verified, fee paid, documents generated, signature complete, genesis recorded; and importstructure → import → company, for an entity that already exists and brings its own cap table and documents.

The table MUST stay closed: an edge that is not listed does not exist, so no request shape, argument or ordering advances a formation past a guard. A new step is a new edge with a new guard in the table, never a condition in a handler.

§2 The addresses

Twenty-one paths, every one under /v1/company (manifest/apps.go:433, plugin/company/openapi.json): the machine's edges (/structure, /founders, /kyc, /kyc/decision, /kyc/refresh, /payment, /documents, /esign, /esign/complete, /genesis, /advance, /skip), the import pair, the fundraise trio, the platform book (/register, /register/summary, /review) and the GET|POST /v1/company root.

Twenty operations are typed. Two are declared with prose beside the route and held to that count by a test (apps/company/typed_wire_test.go): the deck upload takes a PDF as the raw request body, which has no value to name, and POST /payment answers denial with the fleet's nested error body, which a typed operation cannot emit. Both declare their bodies through openapi.Register, so neither publishes an address nobody can explain.

§3 The store, and the tenant

One SQLite file in the system namespace — company — holds each org's formation as a single row keyed by the org, at most one formation per org (apps/company/store.go:22-28). Documents, cap-table rows and signing material are NOT here: they live with dataroom, captable and kms behind the provider seams (apps/company/providers.go), and a formation row that also held them would make this capability the second owner of three other stores.

The org is principal.Org, the validated IAM owner claim (HIP-0026), on every read and write; a caller with no validated principal is refused.

Two surfaces are SuperAdmin's and cross-tenant by nature: the platform book (/register, /register/summary, /review) and the identity decision (/kyc/decision). Hanzo forms the entity, so Hanzo carries the formation identity obligation, and discharging it is the platform's own act rather than a predicate over the customer's. The two planes MUST stay orthogonal — the SuperAdmin operation writes a fact, the machine's guard reads it, neither calls the other — and a reviewer's confirmation MUST be recorded as its own distinct value, never as a provider verification. "A human confirmed this" and "a provider verified this" stay different facts to an auditor forever. Every privileged decision carries the deciding reviewer.

§4 The genesis anchor

The founding allocation — entity plus founders, ordered deterministically — is hashed to a keccak root and committed to the Hanzo L1 (chain 36963) by a KMS-signed transaction (apps/company/genesis.go). The chain is the source of truth, so a holder of the allocation recomputes the root without trusting this platform. When the RPC or the signer is unconfigured, the root MUST be returned with an honest pending status: a transaction hash is never fabricated and formation is never blocked on an unreachable chain.

§5 Price, events, emission, stage, upstream

The capability is metered: Price: cloud.Metered (plugin/company/main.go:27; spend.go:294) — the surface moves a four-figure sum, so the edge requires standing. The one charge is the one-time formation fee — 99900 cents (formationFeeCents, apps/company/providers.go:146; operator override CLOUD_COMPANY_FEE_CENTS, apps/company/company.go:290-297) — taken at POST /v1/company/payment through the charge seam onto the org's own ledger. Insufficient balance is 402 and an unreachable balance is 503; neither advances the stage, because the paid guard reads the receipt rather than the attempt (apps/company/machine.go:332-335).

It publishes no events on the bus, so a customer's webhooks (HIP-1310) receive nothing from it — provider completion arrives INBOUND at /esign/complete and /kyc/decision, it is not emitted. It emits nothing to observability beyond the request span every route gets.

The stage is beta (HIP-0139 §8): a vertical application rather than core, so an org reaches it by the company flag. The manifest row declares it (manifest/apps.go:433, Stage: Beta). It derives from no OSS upstream — the identity and filing providers are hand-written clients behind the seams (apps/company/providers.go, apps/company/filing.go).

Rationale

The alternative to the closed edge table is scopes: enumerate what each caller may invoke and check the enumeration in every handler. It costs one gap to be wrong, the gaps are invisible until exploited, and each new stage multiplies the checks that must agree. The table has one place to be right.

The alternative to the platform book is per-tenant records only, which cannot answer what the obligation actually poses: how many formations await review, and which have waited longest. That question is cross-tenant because the duty is.

Security Considerations

The wrong implementation hands an attacker one of three things. Another org's formation row is its founders' identity documents and personal data — the most sensitive record this platform holds outside secrets. A decision operation reachable by a non-SuperAdmin is laundered identity approval: a self-declared founder who then clears the guard. And an edge table with one extra entry is a company formed without payment or without a verified person behind it — a real entity, in a real jurisdiction, traceable to us. The anchor adds a fourth: a fabricated transaction hash is a false claim of public verifiability, worse than no claim, because a reader who checks the chain and finds nothing has already relied on it.

Four surfaces

SurfaceReaches this capability asCoverage
RESTcompany at its own prefix23 operations
CLIhanzo company …22 of 23 — the CLI pins the document on its own clock
SDKCompanyApi in every published client22 of 23 — the clients are generated at their own release
MCPtool company on https://api.hanzo.ai/v1/mcp22 operations, 4 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/company, operation get_company:

hanzo company get

Answers 200 with object — ok.

Endpoints

EndpointWhat it does
POST /v1/company/advanceAdvance runs the ONE guarded transition of the formation machine.
POST /v1/company/documentsRenders the formation documents for the chosen structure and jurisdiction, ingests each into the org's data room, and submits the state filing…
POST /v1/company/esign/completeRecords whether the formation documents have been signed.
POST /v1/company/esignSends the generated formation documents for signature by every founder and records the provider's reference on the formation.
POST /v1/company/foundersReplaces the formation's founders.
POST /v1/company/fundraise/deckShare a pitch deck in the org's data room
POST /v1/company/fundraise/roundRecords a fundraising round on the org's canonical cap table.
POST /v1/company/fundraise/safeRaises an e-signature request over documents already in the org's data room — a SAFE, a convertible note, or any other fundraising paper.
POST /v1/company/genesisSeeds the canonical cap table with the founding allocation (stakeholders, a common share class, issued shares) and anchors the deterministic…
POST /v1/company/import/captableReads an existing company's cap table from a Google Sheet and adds its stakeholders to the canonical cap table.
POST /v1/company/import/documentsIngests an existing company's corporate documents from a Google Drive folder into the org's data room.
POST /v1/company/kyc/decisionDecideKYC records a privileged reviewer's MANUAL decision on a founder's KYC — the human-in-the-loop path, and the ONLY route to a pass when no real…
POST /v1/company/kyc/refreshRefreshKYC reconciles each pending founder's KYC with the WIRED provider — the PULL path to a provider-reported terminal status.
POST /v1/company/kycStartKYC opens an identity-verification session for every founder with the wired provider and records each session's reference on the formation.
POST /v1/company/paymentCharges the caller's own org the one-time Hanzo Company formation fee.
GET /v1/company/register/summaryCounts the platform's formations by stage — the register's shape in one read, so a queue that is growing is visible as a number rather than inferred…
GET /v1/company/registerReturns the platform's whole formation register, newest activity first — every org's formation, not the caller's.
GET /v1/company/reviewReports the founders whose KYC is not yet settled, oldest formation first, so the queue drains in the order founders have been waiting.
POST /v1/company/skipSkip marks the org as already incorporated and moves it onto the import path, so an existing company brings its documents and cap table in instead of…
PUT /v1/company/structureRecords the entity kind, the state of formation and the proposed name.
POST /v1/company/tariffItemises what a formation costs before anyone commits to it.
GET /v1/companyGet returns the caller org's formation and the stages reachable from it, or 404 when the org has not begun one.
POST /v1/companyBegin starts the org's one formation and returns it with the stages reachable from it.

All Hanzo APIs · Interactive reference

How is this guide?

On this page