# API reference (https://docs-ecmrhub-v2.lucaspiera.com/docs/api)

> The Hub HTTP API from its OpenAPI contract. Base URL, headers, conventions, and one page per endpoint.

The pages in this section are generated from the OpenAPI contract of the Hub backend, the same
file the backend is tested against. The machine-readable contract for code generators and agents
is at [`/openapi.json`](https://docs-ecmrhub-v2.lucaspiera.com/openapi.json).

| | |
| --- | --- |
| Base URL | `https://api-ecmr-dev.lucaspiera.com` |
| Required headers | `apikey: <public anon key>`, `Authorization: Bearer <access token>` |
| Body | JSON, UTF-8 |
| Errors | JSON `{code, message}`, from the approval gate `{error: {status, code, message, retryable, approval}}`; see [Errors](https://docs-ecmrhub-v2.lucaspiera.com/docs/errors.md) |

How to get the token: [Authentication](https://docs-ecmrhub-v2.lucaspiera.com/docs/authentication.md). The company always comes from the
token.

## Three kinds of endpoints [#three-kinds-of-endpoints]

| Path | What it is |
| --- | --- |
| `/functions/v1/...` | Edge Functions: issuing, PDFs, signing pages. Return the model directly. |
| `/rest/v1/<table>` | Read-only views, filtered to your company. Return an array; an id you cannot see returns an empty array, not 404. |
| `/rest/v1/rpc/<name>` | Remote procedures (POST with a JSON body): drafts, signing links, evidence. |

## Conventions [#conventions]

- **Revisions.** A draft has a `revision`. Every save sends the revision it started from; a newer
  one on the server answers `409 VERSION_CONFLICT`. Read the draft again and retry.
- **Idempotency.** Endpoints that take an `Idempotency-Key` header (or an `operationId` /
  `idempotencyKey` field) return the first result again for the same key and payload; the same key
  with a different payload answers `409 IDEMPOTENCY_CONFLICT`. Keys are kept 30 days. Store the key
  before sending and reuse it on retry.
- **Issuing is idempotent per draft.** Issuing the same draft again returns the same document.
- **Unknown result after a transport error.** If the connection drops after a write, repeat the
  same request with the same keys; do not create a new one.
- **Approvals.** Operations that need a person's approval answer `428 APPROVAL_REQUIRED` for
  connections with approvals on. Repeat with `x-ecmr-approval: <id>`; see
  [Human approvals](https://docs-ecmrhub-v2.lucaspiera.com/docs/approvals.md).

## Coverage [#coverage]

The contract covers drafts, issuing, documents and versions, PDFs, evidence, signing links,
approvals (`/functions/v1/approvals`), connections (`/functions/v1/connections`), `whoami` and the
`x-ecmr-approval` header. Other catalog operations (address book, tracking) are available through
the SDK, the [CLI](https://docs-ecmrhub-v2.lucaspiera.com/docs/cli.md) and [MCP](https://docs-ecmrhub-v2.lucaspiera.com/docs/mcp.md). They will be added to this reference as the
contract grows.

> **In build (backend):** Approvals, connections and the `x-ecmr-approval` header are part of phase 1 and are not released
> on the production API yet.

There is no request playground on these pages: Hub accepts browser calls only from its own
dashboard. Use the request samples on each page from your code, the CLI or `curl`.
