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.