/api/v1 surface. They are deliberately agent-friendly:
the same filtering engine and error shapes power the REST API and the MCP server, so semantics never
diverge.
Examples use
https://www.merchkit.com as the base URL.Pagination
List endpoints return their results in an envelope: the rows underdata, and the cursor metadata
under pagination.
Page size. Defaults to 50, with a maximum of 200. Larger pages mean fewer round-trips,
which agents generally prefer.
How many rows to skip. Combine with
limit to page through results.The total number of rows matching the query, across all pages.
Whether more pages exist after this one. Read
has_more rather than computing it yourself — it
is the canonical signal to stop paging.Filtering and sorting
Filter with the query-string DSL:filter[<key>][<op>]=<value>. Combine multiple filters with
filter_join, and order results with sort.
One filter clause: an attribute key, an operator, and a value.
How multiple filter clauses combine.
A comma-separated list of fields. Prefix a field with
- for descending order (e.g.
sort=-updated_at).Operators
| Operator | Meaning |
|---|---|
contains | Value contains the substring |
notContains | Value does not contain the substring |
equals | Exact match |
notEquals | Not an exact match |
startsWith | Value begins with |
endsWith | Value ends with |
blank | Attribute is empty / unset |
notBlank | Attribute is set |
greaterThan | Numeric / date greater than |
lessThan | Numeric / date less than |
greaterThanOrEqual | Numeric / date ≥ |
lessThanOrEqual | Numeric / date ≤ |
blank / notBlank answer the most common enrichment question — “which products are missing an
attribute?” For example, filter[description][blank]=true finds every product without a
description, and notBlank finds the inverse.Error envelope (machine-recoverable)
Every non-2xx response uses one shape, designed so an agent can recover without a human in the loop.A stable machine code. Common codes:
unauthorized, insufficient_scope, not_found,
validation_failed, conflict, internal_error.A human-readable explanation of what went wrong.
Whether retrying the same request could succeed. If
true, honor retry_after_seconds.How long to wait before retrying, when the error is retriable.
A link to documentation for this specific error code.
A suggested next step that may resolve the problem.
An identifier echoed in logs — include it when contacting support.
Per-field details. Each entry has a
field, an issue, and — critically —
acceptable_values: the exact set of values that would have passed validation.field_errors[].acceptable_values is the strongest self-correction signal in the API. When a value
is rejected, the response tells you exactly which values are acceptable, so an agent can fix the
payload and retry without asking a human.Async jobs
Long-running operations — bulk writes, imports, exports — do not block. They return202 with a
job handle, and you poll for completion.
Poll the job rather than blocking on the original request. The job status endpoint is the source of
truth for both progress and the final result.
Reference attributes
Some attributes are references — they point at another entity (a product pointing at a vendor or an asset, for example). Instead of returning a raw UUID, a reference attribute returns a compact summary:label is enough to render or reason about the relationship inline. When you need the full
record, fetch it with GET /api/v1/products/{id} (or the corresponding resource endpoint) using the
entityId.