Skip to main content

The two API surfaces

GreatBook exposes two HTTP APIs, and conflating them is the fastest way to build the wrong integration.

The DevCenter API

What the product itself calls. The intake queue, both maker-checker gates, the Typewriter document surface, uploads, actions, payments, and the read endpoints the Books screens use.This is the surface that carries the money path.

The backend GL read API

The book of record, read-only. Journal entries, entry detail, the trial balance, the tie-out and a thin sub-ledger view, served straight off the canonical general ledger.Use it when you want the ledger, not the workflow.

Which one to use

Both surfaces have a router mounted at /gl, and they are not the same endpoints. The DevCenter’s /gl/* serves the Books screens and preserves a legacy response contract; the backend’s /gl/* is the read API over the canonical ledger. They run as different services on different ports, so check which base URL you are pointed at before matching a response shape.

The shape of each

Neither surface declares response models, so there is no generated schema worth rendering as an endpoint explorer. These pages are written from the route handlers and their test suites instead, which is why each response below states the keys it actually returns rather than a type name.

Endpoints by lane

Plus the DevCenter’s own service routes: GET /ok, GET /connectors, POST /connectors/{id}/check, POST /connectors/check-all, the deliberately inert QuickBooks OAuth redirect boundaries, and POST /cache/invalidate.

Reviewed master maintenance

The DevCenter also mounts typed item and employee master-maintenance families under /masters. Each family has native-record list, proposal list/detail, proposal creation, and exact approval routes. Proposal creation and approval require a named human with workflow.write; reads accept workflow.write or books.read. Approval reloads the stored proposal, binds its exact version and content hash, requires a different human, calls the existing item or employee writer, and appends the approval evidence in the same transaction. This is not a generic table editor. Item proposals accept identity, name, item type, and unit of measure only. Employee proposals accept identity, name, and employee type only; pay, allocation, employment status, and effective-dated terms stay outside the contract. The web routes are /masters/items, /masters/items/proposals, /masters/employees, and /masters/employees/proposals, with proposal-specific review pages beneath each family. These routes and pages are verified in source; this documentation cut did not complete the workflow in production.

Three rules that hold everywhere

1. Nothing is unauthenticated. Every route on both surfaces requires a verified identity. On the DevCenter only /ok, the OpenAPI documents and the OAuth redirect boundaries are open. Open callbacks are not an active connector: the current migration creates no OAuth client and activates no trusted binding. 2. The acting identity is derived, never supplied. A browser cannot choose who it is acting as. That is not a hardening detail, it is the whole of the maker-checker control, because the actor string is what the maker != checker comparison is made against. 3. Reads are org-scoped by row-level security. A cross-org caller sees zero rows, enforced by the database rather than by a filter in application code. All three are set out on Auth, actors and org scoping.

A first call