API Reference
Measured exposes a REST API for everything in the platform, and the same API your agents use over MCP.
- Platform API (
/api/v2), data sources, assets, asset rules, rule groups, runs, results, alerts, and incidents, scoped by organization and workspace. - GX Core compatibility API (
/api/v1), the GX Cloud-compatible surface that lets existing GX Core pipelines talk to Measured unchanged (see Migrate from GX Cloud).
The endpoints below show the GX-compatibility surface; the platform API mirrors the same resources under /api/v2/organizations/{org}/workspaces/{ws}/… with rule-groups in place of checkpoints.
Base URL
https://app.measured.cloud/api/v1 # GX Core compatibility
https://app.measured.cloud/api/v2/organizations/{org}/workspaces/{ws} # platform
Authentication
All API requests require a Bearer token:
curl https://dq.your-company.com/api/v1/datasources \
-H "Authorization: Bearer $DQ_TOKEN"
Generate tokens in Settings → API Tokens → New token.
Tokens have configurable expiry (default: no expiry for long-lived service tokens). User session tokens expire after 15 minutes; use API tokens for automation.
Data Sources
List data sources
GET /api/v1/datasources
Get a data source
GET /api/v1/datasources/{id}
Create a data source
POST /api/v1/datasources
{
"data": {
"type": "datasource",
"attributes": {
"name": "Production Snowflake",
"type": "snowflake",
"connection_string": "snowflake://user:pass@account/db/schema"
}
}
}
Update a data source
PATCH /api/v1/datasources/{id}
Delete a data source
DELETE /api/v1/datasources/{id}
Test a data source connection
POST /api/v1/datasources/{id}/test
Returns {"success": true} or an error message.
Data Assets
List data assets
GET /api/v1/data-assets
Filter by datasource: GET /api/v1/data-assets?datasource_id={id}
Create a data asset
POST /api/v1/data-assets
{
"data": {
"type": "data-asset",
"attributes": {
"name": "orders",
"datasource_id": "abc123",
"asset_type": "table",
"schema": "public",
"table": "orders"
}
}
}
Rules
Rules live on a data asset.
Get an asset's rules
GET /api/v2/organizations/{org}/workspaces/{ws}/data-assets/{id}/rules
Replace an asset's rules
PUT /api/v2/organizations/{org}/workspaces/{ws}/data-assets/{id}/rules
{
"data": {
"rules": [
{ "rule_type": "expect_column_values_to_not_be_null", "kwargs": { "column": "order_id", "severity": "error" } },
{ "rule_type": "expect_table_row_count_to_be_between", "kwargs": { "min_value": 1000 } }
]
}
}
Note: PUT replaces the asset's entire rules array. To add a single rule without losing others, GET the current rules first, append to the array, and PUT the full array back.
Rule groups
List rule groups
GET /api/v2/organizations/{org}/workspaces/{ws}/rule-groups
Create a rule group
POST /api/v2/organizations/{org}/workspaces/{ws}/rule-groups
{
"data": {
"name": "Daily orders quality",
"schedule": "0 8 * * *"
}
}
Run a rule group
POST /api/v2/organizations/{org}/workspaces/{ws}/rule-groups/{id}/run
Returns a validation result ID for polling.
Validation Results
List results for a checkpoint
GET /api/v1/checkpoints/{id}/validation-results
Get a specific result
GET /api/v1/validation-results/{id}
Response:
{
"data": {
"id": "run-001",
"type": "validation-result",
"attributes": {
"status": "passed",
"run_time": "2026-05-25T08:00:01Z",
"duration_ms": 1432,
"statistics": {
"evaluated_expectations": 5,
"successful_expectations": 5,
"unsuccessful_expectations": 0,
"success_percent": 100.0
},
"results": [
{
"rule_type": "expect_column_values_to_not_be_null",
"kwargs": { "column": "order_id" },
"success": true,
"result": { "element_count": 50000, "unexpected_count": 0 }
}
]
}
}
}
Error responses
All errors use standard HTTP status codes:
| Code | Meaning |
|---|---|
| 400 | Bad request, invalid JSON or missing required field |
| 401 | Unauthorized, missing or expired token |
| 403 | Forbidden, token doesn't have permission for this resource |
| 404 | Not found |
| 409 | Conflict, e.g. duplicate name |
| 500 | Internal server error |
Error response format:
{
"errors": [
{
"status": "404",
"title": "Not found",
"detail": "Datasource with id 'abc123' does not exist"
}
]
}
Pagination
List endpoints support cursor-based pagination:
GET /api/v1/validation-results?page[size]=25&page[after]=cursor123
The response includes a meta.pagination object:
{
"meta": {
"pagination": {
"total": 1200,
"next_cursor": "cursor456",
"has_more": true
}
}
}
Rate limiting
The API is rate-limited to 1,000 requests/minute per token. The X-RateLimit-Remaining header shows remaining budget for the current window.