ReferenceAPI ReferenceQuality Tests

Quality Tests

Quality tests are SQL assertions that validate your data after each pipeline run. If a quality test with error severity fails, the pipeline run’s ephemeral Nessie branch is deleted and the run fails — bad data never reaches production. Tests with warn severity log a warning but allow the branch to merge.


Endpoints

MethodEndpointDescription
GET/api/v1/pipelines/{ns}/{layer}/{name}/testsList quality tests for a pipeline
POST/api/v1/pipelines/{ns}/{layer}/{name}/testsCreate a quality test
DELETE/api/v1/pipelines/{ns}/{layer}/{name}/tests/{testName}Delete a quality test
POST/api/v1/pipelines/{ns}/{layer}/{name}/tests/runRun all quality tests

List Quality Tests

GET /api/v1/pipelines/{ns}/{layer}/{name}/tests

Returns all quality tests for a pipeline. Tests are annotated with published status based on the pipeline’s published versions — a test is “published” if its SQL file was included in the last publish snapshot.

Path Parameters

ParameterTypeDescription
nsstringNamespace
layerstringData layer
namestringPipeline name

Request

curl http://localhost:8080/api/v1/pipelines/default/silver/orders/tests

Response — 200 OK

{
  "tests": [
    {
      "name": "no-null-ids",
      "sql": "SELECT count(*) FROM {{ ref('silver.orders') }} WHERE id IS NULL",
      "severity": "error",
      "description": "IDs must not be null",
      "published": true,
      "tags": ["data-quality"],
      "remediation": "Check upstream data source for missing IDs"
    },
    {
      "name": "positive-amounts",
      "sql": "SELECT count(*) FROM {{ ref('silver.orders') }} WHERE amount <= 0",
      "severity": "warn",
      "description": "Order amounts should be positive",
      "published": true,
      "tags": ["data-quality", "financial"],
      "remediation": "Review orders with zero or negative amounts"
    }
  ],
  "total": 2
}

Response Fields

FieldTypeDescription
testsarrayList of quality test objects
tests[].namestringTest name (used as filename: {name}.sql)
tests[].sqlstringSQL query that defines the assertion
tests[].severitystringSeverity level: error or warn
tests[].descriptionstringHuman-readable description
tests[].publishedbooleanWhether this test is included in the published version
tests[].tagsarrayTags for categorization
tests[].remediationstringSuggested fix when the test fails
totalintegerTotal number of tests

Quality test SQL files are stored in S3 at {namespace}/pipelines/{layer}/{pipeline}/tests/quality/{testName}.sql. The SQL should return a count of failing rows — if the count is greater than 0, the test fails.

Error Responses

StatusCodeDescription
404NOT_FOUNDPipeline not found

Create Quality Test

POST /api/v1/pipelines/{ns}/{layer}/{name}/tests

Creates a new quality test by writing a SQL file to the pipeline’s tests/quality/ directory in S3.

Path Parameters

ParameterTypeDescription
nsstringNamespace
layerstringData layer
namestringPipeline name

Request Body

FieldTypeRequiredDescription
namestringYesTest name (lowercase, alphanumeric, hyphens; used as filename)
sqlstringYesSQL assertion query (must return a count of failing rows)
severitystringYesSeverity level: error or warn
descriptionstringNoHuman-readable description

Request

curl -X POST http://localhost:8080/api/v1/pipelines/default/silver/orders/tests \
  -H "Content-Type: application/json" \
  -d '{
    "name": "no-null-ids",
    "sql": "SELECT count(*) FROM {{ ref('\''silver.orders'\'') }} WHERE id IS NULL",
    "severity": "error",
    "description": "IDs must not be null"
  }'

Response — 201 Created

{
  "name": "no-null-ids",
  "severity": "error",
  "path": "default/pipelines/silver/orders/tests/quality/no-null-ids.sql"
}

Response Fields

FieldTypeDescription
namestringTest name
severitystringSeverity level
pathstringS3 path where the test SQL file was written

Error Responses

StatusCodeDescription
400INVALID_ARGUMENTMissing name or sql, invalid test name
404NOT_FOUNDPipeline not found
409ALREADY_EXISTSA test with the same name already exists

Delete Quality Test

DELETE /api/v1/pipelines/{ns}/{layer}/{name}/tests/{testName}

Deletes a quality test by removing its SQL file from S3.

Path Parameters

ParameterTypeDescription
nsstringNamespace
layerstringData layer
namestringPipeline name
testNamestringQuality test name

Request

curl -X DELETE http://localhost:8080/api/v1/pipelines/default/silver/orders/tests/no-null-ids

Response — 204 No Content

No response body.

Error Responses

StatusCodeDescription
404NOT_FOUNDPipeline or test not found

Run Quality Tests

POST /api/v1/pipelines/{ns}/{layer}/{name}/tests/run

Executes all quality tests for a pipeline against the current production data (main branch). Returns individual test results with pass/fail status, values, and execution times.

Path Parameters

ParameterTypeDescription
nsstringNamespace
layerstringData layer
namestringPipeline name

Request

curl -X POST http://localhost:8080/api/v1/pipelines/default/silver/orders/tests/run

Response — 200 OK

{
  "results": [
    {
      "name": "no-null-ids",
      "status": "passed",
      "severity": "error",
      "value": 0,
      "expected": 0,
      "duration_ms": 120
    },
    {
      "name": "positive-amounts",
      "status": "failed",
      "severity": "warn",
      "value": 3,
      "expected": 0,
      "duration_ms": 85
    }
  ],
  "passed": 1,
  "failed": 1,
  "total": 2
}

Response Fields

FieldTypeDescription
resultsarrayIndividual test results
results[].namestringTest name
results[].statusstringTest result: passed or failed
results[].severitystringSeverity level: error or warn
results[].valueintegerActual count returned by the test query
results[].expectedintegerExpected count (always 0 — tests pass when no failing rows exist)
results[].duration_msintegerTest execution time in milliseconds
passedintegerNumber of tests that passed
failedintegerNumber of tests that failed
totalintegerTotal number of tests executed

Error Responses

StatusCodeDescription
404NOT_FOUNDPipeline not found
503UNAVAILABLEExecutor (runner) not available
⚠️

Running quality tests via this endpoint executes against the production data on the main branch. This is different from the quality tests that run automatically during a pipeline run, which execute against the ephemeral branch data before it is merged.


How Quality Tests Work

Quality test SQL must return a count of failing rows. If the count is 0, the test passes. If the count is greater than 0, the test fails.

Example: Assert No Nulls

tests/quality/no-null-ids.sql
SELECT count(*)
FROM {{ ref('silver.orders') }}
WHERE id IS NULL

Example: Assert Referential Integrity

tests/quality/valid-customer-refs.sql
SELECT count(*)
FROM {{ ref('silver.orders') }} o
LEFT JOIN {{ ref('silver.customers') }} c ON o.customer_id = c.id
WHERE c.id IS NULL
  AND o.customer_id IS NOT NULL

Example: Assert Value Ranges

tests/quality/positive-amounts.sql
SELECT count(*)
FROM {{ ref('silver.orders') }}
WHERE amount <= 0

Severity Levels

SeverityOn FailureDescription
errorRun fails, branch deletedHard failure — bad data is blocked from production
warnRun succeeds with warningSoft failure — data quality issue is logged but data proceeds