Governed Read Contract
Fetch or publish the versioned read contract that lets Apps and cross-pipeline rules consume a data product through a frozen field shape and record identity.
A data product does not become a machine-consumable source merely because it exists. Cross-pipeline consumers — Business Rules and Apps — read a product only through its governed read contract: a versioned snapshot that freezes the served field shape, the declared record identity, the permitted match-key sets, and the serve representation. The contract is what makes a read reproducible and auditable: consumers pin a contract version, and a later shape change creates a new version rather than silently retargeting them.
Two endpoints manage the contract. GET /v1/data-products/{id}/read-contract returns the currently active version, and POST /v1/data-products/{id}/read-contract/publish publishes one from the product's currently served shape. Publishing is idempotent on shape: if the active contract already matches the served fields, the same version is returned unchanged; if the shape drifted, the old version is superseded (its supersededAt is stamped) and the next contractVersion is minted.
Every contract declares exactly one record identity. By default it is derived from the product schema's field tags (record_key, business_key, or unique). When the schema carries no such tag — common for spec-built products that cannot be re-tagged through the API — declare the identity in the publish body: either record_key_fields (1-8 served, non-restricted field names) or record_key_anchored: true, which identifies rows by the record anchor itself, the only option for a per-document product with no unique served field. Declaring both is rejected with 400: a contract has one record identity.
Uniqueness is never caller-asserted. The declared key is validated against the product's actual rows, and a key that is missing values or not unique within the publication fails the publish with 422. The same 422 with a machine-readable code covers every other reason the product cannot be frozen — an incomplete publication, an empty served schema, or a product that is not an active pipeline-backed source.
/v1/data-products/{id}/read-contractPath parameters
Contract Response
Response fields
curl
curl -s https://api.talonic.com/v1/data-products/6ecb46fa-24ba-4b5d-93ee-b8b6c6b97655/read-contract \
-H "Authorization: Bearer tlnc_your_api_key"Response
{
"dataProductId": "6ecb46fa-24ba-4b5d-93ee-b8b6c6b97655",
"workspaceId": "0b54c3e1-9a4d-4f0e-8b2a-7c6d5e4f3a21",
"contractVersion": "2",
"schemaHash": "sha256:9f8e7d6c5b4a",
"servePathId": "pipeline-output-reader",
"serveRepresentationVersion": "1",
"fields": [
{ "fieldId": "load_number", "name": "load_number", "type": "string", "nullable": false, "sensitivity": "internal" },
{ "fieldId": "carrier_name", "name": "carrier_name", "type": "string", "nullable": true, "sensitivity": "internal" }
],
"recordKeyFieldIds": ["load_number"],
"recordKeyUniqueWithinPublication": true,
"recordKeyAnchored": false,
"permittedMatchKeySets": [["load_number"]],
"publicationRetention": {
"minimumDays": 0,
"historicalPublicationsQueryable": false,
"retentionHoldSupported": true
},
"publishedAt": "2026-08-10T09:00:00.000Z",
"supersededAt": null
}Publish a Contract Version
Publish (or refresh) the contract from the product's currently served shape. The endpoint is write-scoped: the same authority that can create products can freeze the contract consumers read through, which is what makes a freshly built product consumable by Apps without a manual relay. The body is optional — send it only to declare the record identity when the schema carries no key tag.
/v1/data-products/{id}/read-contract/publishBody parameters
curl
curl -s -X POST https://api.talonic.com/v1/data-products/6ecb46fa-24ba-4b5d-93ee-b8b6c6b97655/read-contract/publish \
-H "Authorization: Bearer tlnc_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "record_key_fields": ["load_number"] }'Errors
Error responses