Pin the contract your app is built on
Find the REST contract your Anectico deployment serves, verify its digest, and fetch the operations your program calls.
On this page
A program you build on Anectico's REST API must be written against the contract of the deployment it
calls, not against whatever the documentation site describes today. The documentation can be newer
than the deployment, and a URL that contains /api/v1 says nothing about which operations, fields and
limits that deployment actually serves. Every deployment therefore publishes the exact contract it
serves, with a digest, and your agent can fetch and verify it before it writes a line of code.
Until Anectico's first supported release the contract is experimental: routes and response shapes can change without notice, so record the revision and the digest you built against and re-test when either changes (see Compatibility).
Find the contract a deployment serves
GET /api/v1/api-contract answers with the deployment's contract manifest. It needs no credential, so
your agent can read it before any key exists, and it holds no organization, project, person or credential
data: every caller of one deployment receives the same document. It accepts no query parameters; one is
refused with 400 rather than ignored. It never fetches the documentation site's manifest, so it can only
describe the build that answers.
curl --fail-with-body https://app.anectico.com/api/v1/api-contract
{
"schema_version": 1,
"serving_build": "2026.10.15",
"contract_revision": "experimental-03f7a62d28df",
"digest": "sha256:ab7b71b7…",
"audience_counts": { "app_data": 432, "customer_control": 164, "operator": 25, "protocol": 35, "sdk_data_plane": 18 },
"app_qualification_counts": { "supported": 3, "restricted": 277, "experimental": 152, "excluded": 0 },
"active_operation_ids": ["get_analytics_insights_by_id", "…"],
"active_audience_counts": { "app_data": 432, "…": 0 },
"protocol_availability": [{ "operation_id": "mcp", "route": "/mcp", "active": true }],
"artifacts": [{ "partition": "customer", "revision": "experimental-03f7a62d28df", "digest": "sha256:4f9c426f…", "url": "https://anectico.com/docs/api-contract/artifacts/…", "media_type": "application/json", "byte_count": 10635930, "operation_count": 614, "protocol_entry_count": 0, "qualification_boundary": "…" }],
"proof_links": { "viewing": ["…"], "none": ["…"] },
"stability": { "status": "experimental", "pin": "…", "policy_reference": "https://anectico.com/docs/apps/contract/" }
}
| Field | Meaning |
|---|---|
serving_build |
The release or build identity of the deployment that answered. |
contract_revision |
The exact revision of the contract this deployment serves. One revision is one set of bytes: it is derived from the manifest's own content. |
digest |
The SHA-256 of the master contract, written sha256: and 64 lowercase hex characters. The master contract is the complete census, which includes operations that are not part of any customer contract, so it is not downloadable. It is a different hash from the digest of any artifact below. |
audience_counts, app_qualification_counts |
How many operations the revision declares, by audience and by app qualification. These are what the revision contains, not what this deployment mounted. |
active_operation_ids, active_audience_counts, protocol_availability |
What this deployment mounted when it started. An operation that the revision declares but the deployment did not mount is not served here, and is not listed. A configuration change can change these without changing any digest. |
artifacts |
The contracts you can download: customer (every app-data, customer-control and SDK operation, each labeled with its audience and qualification), apps (the app-data operations that are supported, or restricted with the reason stated) and protocol (sign-in, discovery, MCP and receiver flows). Each has its own digest, size, immutable address and a statement of what it does and does not promise. |
proof_links |
Which console proof pages exist and which query parameters each needs, and the resource types that have no proof page. It carries no link and no origin; a link comes only from a result that has a page. |
stability |
experimental until the first supported release. |
An operation's stable ID is its operationId; active_operation_ids lists the ones you can select.
Write the contract to a file
anectico api spec fetches the manifest of the configured deployment, downloads the exact artifact it
names, verifies the artifact, and writes it where you say. It sends no API key, token or cookie to either
host: the contract is public, and the documentation host is not the API.
# The whole customer contract
anectico api spec --out ./anectico-api.json
# Only the operations your program calls, with the schemas they reference
anectico api spec \
--operation get_oncall_schedules_by_id_on_call \
--operation get_analytics_results_by_result_id \
--revision experimental-03f7a62d28df \
--out ./anectico-api.json
| Flag | Meaning |
|---|---|
--out |
The file to write. Required. An existing file is replaced only with --force. It is not the global --output, which chooses how the result is printed. |
--operation |
A stable operation ID; repeat it to select several. Without it the whole contract is written. |
--revision |
Refuse unless the deployment serves exactly this revision. A different revision is an error, never a fallback to the newest published one. |
--digest |
Refuse unless the digest of the source artifact is this. Accepts sha256: followed by 64 hex characters, or the 64 hex characters sha256sum prints. The master digest is refused. |
--partition |
The source contract: customer (default), apps or protocol. |
--force |
Replace an existing --out file. |
Before anything is written the command checks the manifest format, the revision pin, the artifact's size and its SHA-256 against what the manifest advertises, that the artifact is the contract it claims to be, and that every reference inside it resolves. If any check fails, nothing is written: there is never a half-written spec that looks plausible. An operation your deployment did not mount is refused.
Three digests that are not interchangeable
| Digest | What it hashes | Where you meet it |
|---|---|---|
| Master | The complete census | The manifest's digest |
| Source artifact | The exact bytes of one downloadable contract | artifacts[].digest, --digest, and source_digest inside a selected file |
| Selected output | The exact bytes of the file --operation writes |
The selected_output_digest the command prints |
--digest compares the source artifact's digest, so it still holds for every selection cut from that
artifact. Supplying the master digest is refused with a message that says so.
A selected file says it is a selection
The file --operation writes is a valid OpenAPI 3.1 document containing only the operations you named
and the schemas, responses and security schemes they reference. It carries an x-anectico-selection
extension so it cannot be mistaken for the complete contract:
"x-anectico-selection": {
"selected_count": 2,
"source_digest": "sha256:4f9c426f…",
"source_revision": "experimental-03f7a62d28df"
}
source_digest is the digest of the verified source artifact, not of the selected file. The document never
embeds its own digest: selected_output_digest is the SHA-256 of exactly the bytes written, and it is the
same whether you selected through the CLI or through MCP.
Read the contract over MCP
With mcp:read and docs:read, the get_rest_contract read action returns the same manifest, or the
declarations of the operations you name. It spends no tool slot of its own: call it through
execute_read_action.
{
"name": "execute_read_action",
"arguments": {
"action": "get_rest_contract",
"arguments": {
"operation_ids": ["get_oncall_schedules_by_id_on_call"],
"expected_revision": "experimental-03f7a62d28df"
}
}
}
- With no
operation_idsit returns the manifest and nothing larger. - With 1 to 100 unique
operation_idsit returnsselected_count,complete: true, the source revision and digest, theselected_output_digestand thedocument, the exact canonical bytes the CLI would write. Write the document verbatim to keep it verifiable. expected_revisionrefuses an answer from any other revision.- A selection whose document would exceed one MiB is refused with
selection_too_large; nothing is cut to fit,completeisfalseandselected_countis0. Select fewer operations, or use the CLI for the whole file.
| Refusal | Meaning |
|---|---|
invalid_selection |
Zero or more than 100 operation IDs, a repeated or oversized ID, or an unknown partition. |
unknown_operation |
The contract of this revision has no such operation. |
operation_not_active |
The revision declares the operation but this deployment did not mount it. |
revision_mismatch |
The deployment serves another revision than expected_revision. |
selection_too_large |
The selected document would exceed one MiB. |
An ordinary runtime key that only calls the API needs none of this: docs:read is a discovery grant for
the agent that builds your program, not a permission your program holds.
The published copies
The same revision is published, immutably, on the documentation site:
| Address | What it is |
|---|---|
https://anectico.com/docs/api-contract/latest.json |
The manifest of the newest published revision. It selects a revision; it never replaces one. |
https://anectico.com/docs/api-contract/revisions/<revision>.json |
The manifest of one revision. It never changes. |
https://anectico.com/docs/api-contract/artifacts/anectico-<partition>-<sha256>.openapi.json |
One contract. The file name contains the SHA-256 of its bytes, so a name can never refer to two different files. |
Treat latest.json as news about what exists, not as the contract of your deployment: the deployment's own
GET /api/v1/api-contract is. To check a downloaded file yourself:
sha256sum anectico-customer-4f9c426f….openapi.json
The result must equal the 64 characters in the file name and the digest the manifest lists for it.
Compatibility
Until the first supported release there is no compatibility promise:
- routes and response shapes may change without a deprecation period;
- every contract is experimental, including the operations marked supported;
- clients pin the serving build and the digest they tested, and re-test before moving.
At the first supported release, the release notes name the exact set of supported app operations and their
compatibility and deprecation policy, and the manifest's stability records the release the promise starts
in. The promise starts there and is never backdated; an operation that is merely listed in a contract, or in
the REST reference, is not stable because it is listed.
Related
- Build an app on the REST API
- REST API conventions
- Machine-readable documentation
- CLI command reference
Browser aggregate sharing
Read the customer contract partition for owner grant controls and dedicated mint and view protocols. These operations are excluded from the ordinary app-data subset. Pin and inspect their actual credential, confirmation, paging and refusal declarations; a protocol exclusion does not mean unavailable.
See Share a saved aggregate with a browser page for the full credential, theft, lifetime, privacy and external-copy contract.