Skip to content

Data API

Errors

Error response format and HTTP status codes for the Parcel Data API.

Data API errors use one of two JSON shapes, depending on where the error is raised.

Handler errors (authentication, plan and permission, not found, rate limiting, a missing workspace_id, an invalid search_after cursor, an unknown include key) use a consistent envelope:

Error envelope
{
"error": {
"code": "<string>",
"message": "<string>"
}
}

code is a machine-readable identifier; message is a human-readable description.

Request-body validation errors (a malformed body, a value that fails schema validation such as limit over 100, an unknown filter or sort key, or an out-of-vocabulary value on an enum field) are caught by the schema validator before the handler runs. They return 400 with a different shape:

Validation error (400)
{
"success": false,
"error": {
"issues": [
{
"code": "unrecognized_keys",
"keys": ["bogus_key"],
"path": ["filters"],
"message": "Unrecognized key(s) in object: 'bogus_key'"
}
],
"name": "ZodError"
}
}

An out-of-vocabulary value on an enum-backed filter (for example stage, primary_use, signal_type, account_type, or role) fails validation with a single clean issue naming the allowed values. Because a filter value may be a single value or an array, the issue code is invalid_union, but the message is the clean, actionable one (the same for a bad scalar and a bad array element):

Invalid enum value (400)
{
"success": false,
"error": {
"issues": [
{
"code": "invalid_union",
"path": ["filters", "stage", "value"],
"message": "Invalid value for this field. Provide one of the allowed values, or an array of them: pre_filing, filed, under_review, approved, permitted, under_construction, completed."
}
],
"name": "ZodError"
}
}

Enum fields are matched exactly, so they do not accept exact_match; passing it on an enum filter is also a 400.

When handling errors, check the HTTP status first, then branch on error.code (envelope) or error.issues (validation).


Status code reference

StatusCodeWhen it occurs
400bad_request (handler) or a ZodError (body validation)A malformed body or a value that fails schema validation (e.g. limit over 100, an unknown filter or sort key, an out-of-vocabulary enum filter value) use the validation shape. An invalid search_after cursor, an unknown include key, or a missing workspace_id use the envelope.
401unauthorizedMissing or invalid Authorization: Bearer token.
403forbiddenAPI key is not permitted for this resource, or the workspace plan does not include Data API access.
404not_foundRecord ID not found (GET by ID), or unknown route.
429rate_limitedWorkspace has exceeded the 250,000-credit rolling 24-hour ceiling.

400 Bad request

Handler-level 400s use the envelope with code bad_request (an invalid search_after cursor, an unknown include key, or a missing workspace_id on a user-token request):

400 response (handler)
{
"error": {
"code": "bad_request",
"message": "workspace_id is required for user tokens."
}
}

Request-body schema failures (a malformed body, limit over 100, an unknown filter or sort key, or an out-of-vocabulary value on an enum-backed filter) instead return the ZodError validation shape shown at the top of this page.


401 Unauthorized

401 response
{
"error": {
"code": "unauthorized",
"message": "Missing bearer token"
}
}

If you are using a Supabase user JWT (e.g. via the MCP server), include ?workspace_id=<uuid> on every request. Omitting it returns a 400 bad_request (not a 401): the token is valid, but the request is missing required attribution.


403 Forbidden

Plan access

The Data API requires the Pro plan. Free and Starter workspaces receive this response on every Data API call.

403 response (plan)
{
"error": {
"code": "forbidden",
"message": "The Data API requires the Pro plan."
}
}

Key not permitted

An API key that has been restricted or revoked also returns 403 with code forbidden.


429 Rate limited

Returned when the workspace has used all 250,000 credits in the current rolling 24-hour window.

429 response
{
"error": {
"code": "rate_limited",
"message": "Workspace Data API credit ceiling reached (used/ceiling in the last 24h). Upgrade your plan or retry later."
}
}

The response includes a Retry-After: 86400 header. Wait until the oldest credits in the window age out (up to 24 hours) before retrying, or upgrade your plan for a higher ceiling.


404 Not found

404 response
{
"error": {
"code": "not_found",
"message": "Project not found"
}
}

On GET /data/{dataset}/{id}, a 404 means no record with that UUID exists. The Data API serves a global index and uses workspace_id only for usage attribution, so 404 is not workspace-scoped.