# Create and edit contracts

With Git-managed contracts, you define your expectations as code using YAML. This gives you full control over how your data is validated, and allows you to manage contracts just like any other code artifact: versioned, tested, and deployed via Git.

> To learn all about the structure and supported features, refer to the full specification in the [Contract Language reference](https://docs.soda.io/reference/contract-language-reference).

The contract structure includes:

* Dataset and column structure
* Available check types (`missing`, `invalid`, `duplicate`, `freshness`, etc.)
* Filters (dataset-level and check-level) — Optional
* Threshold configuration — Optional
* Use of variables — Optional
* Scheduling — Optional
* ...and more

## Create a contract

{% hint style="warning" %}
Creating a contract requires having installed the `soda` package using **the** [**Private PyPi installation flow**](https://docs.soda.io/deployment-options/soda-python-libraries#private-pypi-installation-flow) available both for Team and Entreprise license, unless you are using an Agent.

Need access to the private PyPI? Please [contact us](mailto:support@soda.io).
{% endhint %}

`soda contract create` bootstraps a contract by introspecting a dataset's schema. It writes a YAML file that lists every column with its data type and adds a single `schema:` check. You then edit the file to add data-quality checks (`missing`, `invalid`, `duplicate`, `freshness`, etc.).

### Prerequisites

* A data source configuration file (for local execution), or a Soda Cloud configuration file (for agent execution).
* Access to Soda's private PyPI (see include above) for installing the library.

### Local execution

Runs introspection from your machine against the data source.

{% code overflow="wrap" %}

```shellscript
soda contract create -d <DATA_SOURCE>/<DATABASE>/<SCHEMA>/<TABLE> -ds ds_config.yml -f contract.yml
```

{% endcode %}

### Agent execution

Delegates introspection to a running Soda Agent. Useful when the data source is only reachable from the agent's network.

{% code overflow="wrap" %}

```shellscript
soda contract create -d <DATA_SOURCE>/<DATABASE>/<SCHEMA>/<TABLE> -sc sc_config.yml -f contract.yml --use-agent
```

{% endcode %}

Omit `-f` to send the generated skeleton to Soda Cloud as a draft contract instead of writing a local file.

### Parameters

| Parameter                    | Required    | Description                                                                                                         |
| ---------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------- |
| `--dataset, -d`              | Yes         | Fully qualified dataset name, slash-separated: `<DATA_SOURCE>/<DATABASE>/<SCHEMA>/<TABLE>`.                         |
| `--file, -f`                 | Conditional | Path to the contract YAML file to create. Directories are created if needed. Required unless `--soda-cloud` is set. |
| `--data-source, -ds`         | Conditional | Path to a data source YAML config file. Required for local execution; ignored when `--use-agent` is set.            |
| `--soda-cloud, -sc`          | Conditional | Path to a Soda Cloud YAML config file. Required when `--use-agent` is set, or when `--file` is omitted.             |
| `--use-agent, -a`            | No          | Run introspection on Soda Agent instead of locally. Default: `false`.                                               |
| `--no-type-parameters, -ntp` | No          | Omit data type parameters (precision, scale, length) from generated columns.                                        |
| `--verbose, -v`              | No          | Display detailed logs during execution. Default: `false`.                                                           |

### What the skeleton contains

A skeleton generated for a `retail_orders` dataset in PostgreSQL looks like this:

{% code title="contract.yml" %}

```yaml
dataset: <DATA_SOURCE>/<DATABASE>/<SCHEMA>/<TABLE>
columns:
  - name: order_id
    data_type: character varying
    character_maximum_length: 50
  - name: product_id
    data_type: character varying
    character_maximum_length: 50
  - name: customer_id
    data_type: character varying
    character_maximum_length: 50
  - name: order_quantity
    data_type: integer
  - name: discount
    data_type: real
  - name: shipping_address
    data_type: character varying
    character_maximum_length: 64
  - name: total_order_value
    data_type: real
checks:
  - schema:
```

{% endcode %}

{% hint style="info" %}
The skeleton contains **only a `schema:` check**. No column-level checks (`missing`, `invalid`, `duplicate`, etc.) are generated — add these yourself after reviewing the columns.
{% endhint %}

Use `--no-type-parameters` to suppress `character_maximum_length`, `numeric_precision`, `numeric_scale`, and `datetime_precision` entries if you prefer a shorter contract.

### Common errors

* `Either --file or --soda-cloud must be provided` — supply one as an output destination.
* `--use-agent requires --soda-cloud` — agent mode needs a Soda Cloud config to reach the agent.

You can now edit the contract and add checks by modifying the file.

> Get the most out of your data contracts: head to the [Contract Language reference](https://docs.soda.io/reference/contract-language-reference) to learn more.

## Test your contract

Before publishing or verifying your contract, you can run a **test command** to ensure the contract is correctly defined and points to a valid dataset.

```shellscript
soda contract test --data-source ds_config.yml --contract contract.yml
```

This will:

* Validate the YAML syntax
* Confirm that the referenced dataset exists
* Check for any issues with variables, filters, or structure

{% hint style="info" %}
Run this as part of your development workflow or CI to catch errors early.
{% endhint %}

## Verify your contract

Before publishing your contract, you may want to execute it to verify that it runs correctly.

> Read more about how to [verify-a-contract](https://docs.soda.io/data-testing/git-managed-data-contracts/verify-a-contract "mention")

## Publish the Contract

If you have Soda Cloud, once your contract is finalized and tested, you can publish it to Soda Cloud, making it the authoritative version for verification and scheduling.

{% hint style="warning" %}
This action requires the "**Manage contract**" permission on the dataset; the user is identified based on the API key provided in the Soda Cloud configuration.

Learn more about permissions here: [dataset-attributes-and-responsibilities](https://docs.soda.io/dataset-attributes-and-responsibilities "mention")
{% endhint %}

```sh
soda contract publish --contract contract.yml --soda-cloud sc.yml
```

> Learn how to connect the CLI to Soda Cloud: [#connect-to-soda-cloud](https://docs.soda.io/reference/cli-reference#connect-to-soda-cloud "mention")

Publishing:

* Uploads the contract to Soda Cloud
* Makes it available for manual, scheduled, or programmatic verifications
* Enables visibility and collaboration through the UI

Once published, the contract becomes the **source of truth** for the dataset until a new version is published.

You’re now ready to start verifying your contract and monitoring your data.

<br>

***

{% if (visitor.claims.plan === 'datasetStandard')%}
{% hint style="success" %}
You are **logged in to Soda** and seeing the **Free license** documentation. Learn more about [documentation-access-and-licensing](https://docs.soda.io/reference/documentation-access-and-licensing "mention").
{% endhint %}
{% endif %}

{% if (visitor.claims.plan === 'enterprise')%}
{% hint style="success" %}
You are **logged in to Soda** and seeing the **Team license** documentation. Learn more about [documentation-access-and-licensing](https://docs.soda.io/reference/documentation-access-and-licensing "mention").
{% endhint %}
{% endif %}

{% if (visitor.claims.plan === 'enterpriseUserBased')%}
{% hint style="success" %}
You are **logged in to Soda** and seeing the **Enterprise license** documentation. Learn more about [documentation-access-and-licensing](https://docs.soda.io/reference/documentation-access-and-licensing "mention").
{% endhint %}
{% endif %}

{% if !(visitor.claims.plan === 'enterprise' || visitor.claims.plan === 'enterpriseUserBased' || visitor.claims.plan === 'datasetStandard')%}
{% hint style="info" %}
You are **not logged in to Soda** and are viewing the default public documentation. Learn more about [documentation-access-and-licensing](https://docs.soda.io/reference/documentation-access-and-licensing "mention").
{% endhint %}
{% endif %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.soda.io/data-testing/git-managed-data-contracts/create-and-edit-contracts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
