Skip to main content
The BitGo repo demo exposes one repurchase agreement between two custodian clients: Canton test collateral (tcanton) against an ERC-20 cash leg on Sepolia. The API holds the agreed terms and the identities of the four movements as a durable record. It does not execute, sign, hold, settle or confirm anything: provider execution is a separate, later integration, and until it is qualified every record stays in its initial state.
The demo exists only in non-production deployments that carry a trusted configuration. In production the routes are not mounted, and a deployment refuses to start with the configuration set. Without a configuration the routes are not mounted either: the paths answer the API’s ordinary 404 HTTP_ERROR Not Found before any credential is read, and they are absent from that deployment’s /openapi.json. This reference documents them from a configured application.

What the record is, and is not

The repayment is whatever amount the operator approved in the template. It may be below the principal; the API derives no rate from the pair.

Who may call

Every route needs a platform credential with settlements:read (reads) or settlements:write (create, commands), under an active environment. A scope admits you to the route; it never makes you an actor. The operator’s configuration binds each authenticated identity (a user’s subject or an environment’s M2M client) to exactly one actor: A session token is never an actor. An identity the configuration does not bind, a credential from another environment, or a deactivated platform or environment is refused with 403. A repo your actor holds no role on is 404 Repo not found, exactly as an unknown id. The view query parameter narrows: omitted, the sole granted view is answered; with several granted, one must be named; naming a view you are not granted is 403. Every view carries the same economics and the same shared progress. No view carries a wallet, a party, a participant address, a participant’s platform or environment, or a provider record.

Endpoints

All bodies and responses use the bitgo-repo-demo.v1 wire: camelCase keys only, every quantity, revision and cursor a canonical decimal string, every instant UTC. A snake_case key, an unknown key, a number where a string is expected, or any field that would name a wallet, a state or an amount is refused 422 with nothing written.

Create

templateId names a template the operator configured; a name that is not configured is a field-level 422. The same idempotencyKey with the same body answers 200 with the record as it was created, under the terms of that day, whatever the template says now. The same key with a different body is 409 IDEMPOTENCY_CONFLICT.

The snapshot

The movements are always the four above in that order, and the cash assetId is eip155:11155111/erc20: followed by the lowercase token address. In this release every status is its initial literal, nextActions is empty, evidence is empty and both phases are incomplete: the schema admits nothing else, so no response can claim a movement started, a signature, an acceptance, a ledger effect, a book posting, a live reservation or a Registry decision. Those vocabularies are added only together with the provider evidence that proves them.

Events

An event names what happened and when. It carries no payload. cursor is the last sequence you hold, a canonical decimal string of at most 9223372036854775807, the last sequence the log can hold; a cursor past that is refused 422 naming query.cursor. When hasMore is true, nextCursor is the sequence to continue after.

Commands

POST /v1/demo/repos/{repo_id}/commands takes {"schemaVersion", "actionId", "expectedRevision", "idempotencyKey"}. In this release no action is offered, so after your credential, your actor and the repo are verified, every command answers 503 HTTP_ERROR with Repo execution is not qualified, and no command, event or revision is written. A 503 is not an accepted command, and nothing retries it for you.

Errors

No error carries a configured value: not a wallet, a party, an address, an identity, a template’s terms or the manifest.

Digests

termsDigest and templateDigest are SHA-256 over the UTF-8 bytes of the RFC 8785 canonical JSON of a closed document (strings, booleans, null, arrays and objects only; every integer a decimal string; instants spelled YYYY-MM-DDTHH:MM:SS.ffffffZ; UUIDs lowercase; EVM addresses lowercase), rendered as 64 lowercase hex characters.
  • templateDigest binds {"schemaVersion": "bitgo-repo-demo.v1", "kind": "repo-template", "template": {templateId, collateral, cash, maturityAt}}.
  • termsDigest binds {"schemaVersion": "bitgo-repo-demo.v1", "kind": "repo-terms", "template", "roles", "source", "participants"}: the same template economics, the fixed roles, the source’s platform and environment, and both participants in order with their platform, environment and pinned wallet routing on each network. Grants and anything mutable are outside it, so the digest never moves with a permission.
The participants’ wallet routing is inside the digest but never inside a response. The accepted-shape golden vector at tests/fixtures/demo_repo/golden_vectors.json holds synthetic documents whose every identifier is in the shape the runtime admits (32-hex wallet ids, a printable hint and a 68-hex fingerprint per Canton party, lowercase non-zero EVM addresses), their exact canonical text and their digests, for independent implementations to reproduce. It is synthetic throughout and claims no provider support for a coin and no control of a wallet.