Endpoint
POST /api/v1/contracts
Host: api.driftguard.dev
Request
curl -s -X POST https://api.driftguard.dev/api/v1/contracts \
-H "X-API-Key: $DRIFTGUARD_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "users_production",
"schema": {
"columns": [
{ "name": "user_id", "type": "integer", "required": true },
{ "name": "email", "type": "string", "required": true },
{ "name": "created_at", "type": "timestamp", "required": true }
]
}
}'
| Header | Value |
|---|
X-API-Key | dg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
Content-Type | application/json |
Body
{
"name": "users_production",
"schema": {
"columns": [
{ "name": "user_id", "type": "integer", "required": true },
{ "name": "email", "type": "string", "required": true },
{ "name": "created_at", "type": "timestamp", "required": true }
]
}
}
Field Reference
| Field | Type | Required | Description |
|---|
name | string | ✅ | Human-readable name for the contract. Must be unique per account. |
schema.columns | array | ✅ | List of column definitions |
schema.columns[].name | string | ✅ | Column name (case-sensitive) |
schema.columns[].type | string | ✅ | Column type — see valid types below |
schema.columns[].required | boolean | ✅ | If true, the column must be present in every check. Removal of a required column scores +40 severity points. Removal of an optional column scores +20. |
Valid Column Types
| Type | Description |
|---|
string | Text values |
integer | Whole numbers |
number | Floating point / decimal numbers |
boolean | True / false values |
date | Date without time (YYYY-MM-DD) |
timestamp | Date with time |
json | Nested JSON / object values |
Any type outside this list will be rejected with a 400 error. Types like float, array, uuid, and unknown are not supported.
Response
{
"id": "your_contract_id_here",
"name": "users_production",
"version": 1,
"schema": {
"columns": [
{ "name": "user_id", "type": "integer", "required": true },
{ "name": "email", "type": "string", "required": true },
{ "name": "created_at", "type": "timestamp", "required": true }
]
},
"created_at": "2026-03-01T18:00:00Z",
"updated_at": "2026-03-01T18:00:00Z"
}
Response Fields
| Field | Type | Description |
|---|
id | string | Unique identifier for the contract — save this to run checks against it |
name | string | The name you gave the contract |
version | integer | Starts at 1. Increments each time the contract schema is updated |
schema.columns | array | The full list of column definitions as saved |
created_at | string | ISO 8601 timestamp of when the contract was created |
updated_at | string | ISO 8601 timestamp of the last update — same as created_at on initial creation |
Save the id from the response. You will need it to run checks via
POST /api/v1/check and to retrieve the contract later.
Error Responses
| Status | Meaning |
|---|
400 | Invalid request body — missing fields, duplicate column names, or unsupported type |
401 | Missing or invalid X-API-Key |
409 | A contract with this name already exists for your account |
429 | Rate limit exceeded — 100 req/min per key |
Run a Check
Use your new contract ID to run your first schema check.
Infer a Contract
Not sure what columns to define? Let DriftGuard infer them from a sample payload.