REST API (v2)
POST /schemas/:version/validate
Validate a datachain instance against a schema version.
The HTTP status is 200 for both
ok: true and ok: false. Validation success/failure is a semantic answer carried in the body — it is not a transport failure.Summary
Validate a DTPR datachain instance against a schema version. The response carries structured errors with fix_hints that an agent can feed into a repair loop.
Request
POST https://api.dtpr.io/api/v2/schemas/:version/validate
Content-Type: application/json
{
"id": "acme-resume-screener",
"title": [{ "locale": "en", "value": "Acme resume screener" }],
"description": [{ "locale": "en", "value": "Pre-screens job applicants against the role brief." }],
"schema_version": "dtpr@2026-09-01-beta",
"created_at": "2026-09-01T00:00:00Z",
"elements": [
{ "element_id": "employment" },
{
"element_id": "organization",
"context_type_id": "deployer",
"variables": [
{ "id": "title", "value": [{ "locale": "en", "value": "Acme Corp" }] },
{ "id": "description", "value": [{ "locale": "en", "value": "Runs the screener and makes the final hiring call." }] }
]
},
{
"element_id": "people",
"context_type_id": "subject",
"variables": [
{ "id": "title", "value": [{ "locale": "en", "value": "Job applicants" }] },
{ "id": "description", "value": [{ "locale": "en", "value": "Anyone who submits a resume for an open role." }] }
]
},
{ "element_id": "recommends", "context_type_id": "human_decides" }
]
}
| Param | In | Description |
|---|---|---|
version | path | Canonical version. |
| (body) | JSON | A DatachainInstance. id, schema_version, created_at, and a non-empty elements[] are required; everything else defaults. Shape is published in the schema's schema_json. The optional authoring_provenance block is accepted on this endpoint — see Authoring provenance. |
Response — valid
HTTP/1.1 200 OK
Content-Type: application/json
DTPR-Content-Hash: sha256-…
Cache-Control: no-store
{
"ok": true,
"warnings": []
}
Response — invalid
HTTP/1.1 200 OK
Content-Type: application/json
DTPR-Content-Hash: sha256-…
Cache-Control: no-store
{
"ok": false,
"errors": [
{
"code": "REQUIRED_CATEGORY_MISSING",
"message": "Instance is missing at least one element from required category 'purpose'",
"severity": "error",
"path": "instance.elements[].category_id",
"fix_hint": "Add at least one element whose category_id is 'purpose' (category defined at categories[9])."
}
],
"warnings": []
}
Response — malformed JSON body
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"ok": false,
"errors": [
{
"code": "bad_request",
"message": "Invalid JSON body.",
"fix_hint": "Send a valid JSON datachain-instance payload."
}
]
}
Response — shape errors (400-adjacent)
When the JSON parses but the datachain shape fails Zod validation, the status stays 200 and the body carries code: parse_error entries:
{
"ok": false,
"errors": [
{
"code": "parse_error",
"message": "Invalid input: expected string, received undefined",
"path": "created_at",
"fix_hint": "Fix the field shape and retry."
}
]
}
Errors
| Code | HTTP | Meaning |
|---|---|---|
bad_request | 400 | Invalid JSON body or malformed :version. |
not_found | 404 | Version is not registered. |
parse_error | 200 | Datachain shape failed Zod validation. |
element_provenance_unknown_element | 200 | A key in authoring_provenance.element_provenance does not match any placement element_id. |
variable_rationale_unknown_variable | 200 | A key inside an element_provenance[<id>].variable_rationale map references a variable not declared on the placed element's category. |
| Semantic validator codes | 200 | Shape-valid but semantically wrong. SCREAMING_SNAKE codes such as REQUIRED_CATEGORY_MISSING, INSTANCE_ELEMENT_UNKNOWN, INSTANCE_REQUIRED_VARIABLE_MISSING, CONTEXT_TYPE_UNKNOWN. |
Example
curl -s https://api.dtpr.io/api/v2/schemas/dtpr@2026-09-01-beta/validate \
-H 'content-type: application/json' \
--data '{
"id": "acme-resume-screener",
"schema_version": "dtpr@2026-09-01-beta",
"created_at": "2026-09-01T00:00:00Z",
"elements": [
{"element_id":"employment"},
{"element_id":"organization","context_type_id":"deployer","variables":[
{"id":"title","value":[{"locale":"en","value":"Acme Corp"}]},
{"id":"description","value":[{"locale":"en","value":"Runs the screener."}]}]},
{"element_id":"people","context_type_id":"subject","variables":[
{"id":"title","value":[{"locale":"en","value":"Job applicants"}]},
{"id":"description","value":[{"locale":"en","value":"Anyone who submits a resume."}]}]},
{"element_id":"recommends","context_type_id":"human_decides"}
]
}'
POST /api/v2/schemas/dtpr@2026-09-01-beta/validate HTTP/1.1
Host: api.dtpr.io
Content-Type: application/json
{"schema_version":"dtpr@2026-09-01-beta","elements":[…]}
See also
- POST /schemas/:version/resolve — compose a thin instance + schema slice into a
ResolvedDatachainInstance. - POST /schemas/:version/validate_resolved — validate a snapshot-pinned resolved form.
- MCP
validate_datachain— same validator with the MCP soft-failure envelope. - MCP envelope — soft-failure
- Datachains