A data contract is a written specification of a dataset that its producer and its consumers agree on. It states the schema, the quality rules, how often the data refreshes, where it is delivered and where consumers get support. The Open Data Contract Standard (ODCS), at version 3.2.0 since 8 September 2026 and published under the Apache 2.0 license, gives those terms one YAML structure [1, 2].
The early examples describe contracts between teams inside one company: services and the people who consume their data [36], or a data mesh at PayPal [15]. This explainer walks through the standard's sections and applies them to a dataset commissioned from an outside builder.
What a data contract is
ODCS defines a data contract as "the agreement between a data producer and consumers" [1]. The Data Contract Specification, an earlier format deprecated when ODCS v3.1.0 was released, gave a longer definition: a document that defines "the structure, format, semantics, quality, and terms of use" of data exchanged between a provider and its consumers. Its shorthand was "Think of an API, but for data" [17].
The same README draws a line that matters between companies. The term refers to "a specification that is usually owned by the data provider", and it does not mean a contract in the legal sense [17]. The mutual agreement between one provider and one consumer is the "data usage agreement", which refers to a data contract and has its own lifecycle and start and end dates [17]. This explainer describes what the sources state and gives no legal advice.
The term is recent. Andrew Jones writes that he came up with data contracts at GoCardless in August 2020 and first wrote about them publicly in April 2021 [16]. Chad Sanderson's 2022 post called them "API-like agreements" between the engineers who own services and the consumers of their data [36]. PayPal published its template in 2023, and that project became ODCS [15].
What a data contract specifies
The ODCS README lists 13 sections: fundamentals, schema, references, data quality, support and communication channels, pricing, team, roles, the service-level agreement (SLA), infrastructure and servers, authoritative definitions, tags, and custom and other properties [1]. PayPal's 2023 template had six [15]. Six of the thirteen in brief:
- Fundamentals. A unique
id, the contract's ownversion, astatus(the standard's examples run from "proposed" to "retired") and a description of the data's purpose, limitations and recommended usage [5]. - Schema. Objects, such as a table or a document, and their properties, such as columns or fields. Each property has one of eleven logical types, a physical type and flags for
required,uniqueandprimaryKey[6]. Lineage keys name the source objects and the transformation logic behind a property [6]. - Data quality. Rules that pair a metric with an operator and a unit [7].
- SLA. Measured properties such as update frequency, latency and retention [8].
- Servers. Where the data physically sits: an API, an S3 or SFTP location or local files, with the file format for file deliveries [12].
- Support. Channels for questions, issues and announcements [9].
A data contract example in YAML
The skeleton below writes a commissioned dataset in ODCS key names. Values in angle brackets are placeholders.
apiVersion: v3.2.0
kind: DataContract
id: <uuid>
version: 1.0.0
status: proposed
description:
purpose: <the question the data must answer>
limitations: <what the sources cannot support>
schema:
- name: <entity>
logicalType: object
properties:
- name: <entity_id>
logicalType: string
primaryKey: true
required: true
- name: <region>
logicalType: string
quality:
- metric: invalidValues
arguments:
validValues: [<agreed list>]
mustBe: 0
slaProperties:
- property: frequency
value: <n>
unit: d
servers:
- server: <delivery>
type: sftp
location: sftp://<host>:<port>/<path>
format: <file format>
primaryKey and required state the shape [6]. The invalidValues rule allows no region outside the agreed list [7], frequency states how often the data updates [8], and the server entry says where files arrive and in what format [12].
Shape is enforced, content is tested
dbt, a data transformation tool, describes a model contract as upfront guarantees "that define the shape of your model", and fails the build when the model's columns or data types differ from the contract [19]. Constraints go further only on some platforms. In dbt's tables, Postgres enforces all five constraint types, and Redshift, Snowflake, BigQuery and Fabric enforce not_null alone [19]. Databricks' own documentation says it enforces NOT NULL and CHECK, and a violation fails the transaction [21]. dbt's summary is "Most platforms only enforce not_null" [19].
The platforms' own pages agree on keys. Snowflake standard tables do not enforce primary, unique or foreign keys [22]. BigQuery does not enforce primary and foreign keys, and warns that queries over violated constraints "might return incorrect results" [23]. Databricks treats them as informational [21]. So a primaryKey: true line records a guarantee that several warehouses do not check.
dbt leaves that work to tests, "a more flexible mechanism for validating the content of your model after it's built" [19]. The Data Contract CLI runs schema and quality checks against a data source, such as whether a unique field has duplicate values [18]. Measuring content on a sample is worked through in how to test document extraction accuracy before you buy.
Data quality rules, coverage and refresh
An ODCS quality rule names a metric, an operator and a unit. The standard's own example reads "There must be less than 1% null values in the column" [7]. Library metrics count nulls, missing values, invalid values, duplicates and rows, and a rule can name one of seven dimensions: accuracy, completeness, conformity, consistency, coverage, timeliness and uniqueness [7].
The UK Government Data Quality Framework uses six core dimensions defined by DAMA UK, including validity, and warns against confusing completeness with accuracy [29]. Its example: 294 of 300 emergency contact numbers recorded is 98% complete, and those numbers "may not all be correct" [29].
For data joined across sources, primary keys and unique flags state which fields identify each record [6, 32]. Matching the records of one entity across several sources is the subject of how entity resolution matches records across sources.
Coverage and refresh have standard words in the W3C's Data Catalog Vocabulary (DCAT) 3: dcterms:temporal for "The temporal period that the dataset covers", dcterms:spatial for "The geographical area covered by the dataset" and dcterms:accrualPeriodicity for "The frequency at which a dataset is published" [26]. In ODCS, history is a date minimum on the time property and refresh is the SLA's frequency [6, 8].
What a data SLA states
Google's Site Reliability Engineering book separates the indicator, a measured quantity, from the objective, its target, and from the agreement, which adds the consequences of meeting or missing the objective [34]. Its test is to ask "what happens if the SLOs aren't met?" [34]. ODCS's SLA section is a list of properties with values and units, and it recommends twelve, including availability, frequency, latency, retention, time to detect, time to notify and time to repair [8].
dbt notes that for an API, quality and reliability matter "but they are not part of the contract per se" [19]. FISD's voluntary 2021 recommendations for alternative data sort incidents into four severities and leave the response times blank for the parties to fill [30, 31].
How a data contract handles breaking changes
dbt counts removing a column, changing a column's data type, removing or modifying a constraint and removing a contracted model as breaking changes that need a new major version [19]. Compatibility also has a direction. Confluent's Schema Registry checks backward compatibility by default, under which consumers on a new schema can read data written with the old one, and removing a field passes that check [24]. A contract can name the direction it protects as well as its change classes.
For datasets, Croissant recommends MAJOR.MINOR.PATCH versions. A patch changes only serialization or file format, a minor version adds data while the old data stays retrievable, and a major version edits, removes or reshuffles existing records [32]. DCAT 3's adms:versionNotes describe the changes between versions, and where compatibility breaks, a description "SHOULD be specified" [26]. ODCS v3.2.0 adds a deprecated flag, so a field can be retired while it stays documented and validated [6]. FISD recommends at least 90 days' notice before a major change [31].
Applying a data contract to a commissioned dataset
A dataset built to order starts from the buyer's terms: source universe, entities, fields, format, history, geography, refresh cadence and delivery. Entities and fields go in the schema, format in physical types and the server's file format, history in date bounds, refresh in SLA properties, and delivery in servers, roles and support [6, 8, 9, 11, 12]. Source universe and geography have no dedicated field. They go in the description, links to license agreements and terms, value lists and custom properties [1, 5, 6, 7].
The specification behind the contract, from use and size to held-out data and acceptance tests, is set out in how to specify a training dataset before anyone builds it, and the provenance each record carries in datasets that state their limits. Rillor's custom datasets each come with their schema, records with resolved identities, source provenance, lineage, version history, quality notes and stated limits.
Read the full report
The full report lists the 13 sections in the ODCS README and describes nine of them, compares constraint enforcement across platforms, sets the ODCS quality dimensions beside the UK framework's, adds a fuller worked contract and lists all 36 sources.

