Conventions
This page covers what every endpoint in this reference has in common, so the per-endpoint pages can stay short.
Requests and responses
Requests and responses are JSON over HTTPS. Send Content-Type: application/json on anything with a
body. Timestamps are ISO 8601 in UTC (2026-01-15T09:30:00Z), and IDs are short opaque
strings such as A4Ws1igz. Treat an ID as text. It is stable for the record's life, but
do not rely on its shape.
Every request goes to your store's own address, which the examples here write as
https://your-store.meisei.app/api. See
Your base URL for where to find yours.
A single record is the whole response body, with no envelope around it:
A list comes back under data, alongside the paging fields described below.
A request body works the same way. One record's fields are the body itself, and a list of
records, such as the rows of an import, goes under data beside any options:
The top level of a request body may only carry the fields the endpoint documents. A key it
does not know, including a misspelled field or a body wrapped in data, is refused with a
400 VALIDATION_ERROR naming the key, rather than ignored:
A PATCH changes only the fields you send, so send only the ones you mean to change rather
than a whole record read back from a GET.
Pagination
List endpoints are cursor paginated. Ask for a page size with limit (1 to 250, 50 by
default), and read nextCursor off the response:
Pass that value back as cursor for the next page. When nextCursor is null you have
reached the end.
Cursors encode the sort position of the last record returned, so a record added while you
are paging does not shift the pages underneath you and nothing is skipped or repeated.
Keep sort and filter the same across a run. If you change either, the cursor no longer
describes where you were.
There is no total count. Walking to the end is the way to count records, and at 250 a page that is one request per 250 records.
Sorting
Pass a field name to sort, prefixed with - to reverse it. Each endpoint lists the
fields it accepts. Most default to -createdAt, newest first.
Searching and filtering
search is a free-text term matched case-insensitively against a record's most
identifying fields.
filter is a JSON document describing exactly which records you want, URL-encoded on a
GET. Each endpoint lists its filterable fields.
Both can be sent together, and are combined with AND. See Filtering for the full operator set, association filters and logical operators.
Extra fields
Some list endpoints can compute values that are not stored on the record, such as a
customer's order count or loyalty balance. Ask for them by name with include:
Each one costs an additional query per request, so ask only for what you are about to use. Available values are listed on each endpoint.
File links
A link to a stored file (a review photo, an export's download, a brand asset, a shopper's
wishlist photo) is on your store's own address, under
https://your-store.meisei.app/api/files/, and it only works there. The same path
on another store's address answers 404, and https://meisei.app refuses it. An
organization's logo and a team member's picture belong to the account rather than to one
store, so their links are on https://meisei.app/api/files/. Use a link exactly as
the API returns it rather than building one.
Bulk and import endpoints
Three shapes recur, and they behave differently:
-
POST /<resource>/importcreates or updates many records at once, matching on a natural key such as an email address, a product slug or your ownremoteId. Every column you send overwrites what is stored, so send complete records rather than partial ones. This is the endpoint to use both for a first backfill and for a single record changing in your store. A row only has to carry the fields that identify the record, plus anything the record cannot exist without (a product names at least one site). Leave a field out and nothing is stored under it; leave a collection such asvariantsoritemsout and whatever is already stored stays, while sendingnullreplaces it with nothing.An import answers with two lists:
data, the records as they now stand, andskipped, the rows that named something that could not be found, with the reason. Reviews are the one exception in name only, answering withimportedandskipped, because the review bodies are not what the response is about. -
PATCH /<resource>/bulk-updateapplies one change to every record matching a filter. Sending no filter applies it to every record in the organization. -
PATCH /<resource>/{id}updates one record, and only the fields you send.
Import and bulk endpoints do more work than ordinary ones and spend more of your rate limit budget. Where an endpoint costs more, this reference says so beside its permission.
Idempotency
Endpoints that record an event rather than a record take an idempotency key of their own,
so a retry after a timeout does not double-count. POST /loyalty-events works this way. The
key is scoped to the customer, and sending it again returns the event recorded the first
time with "duplicate": true. See Custom loyalty events.
No other endpoint takes an idempotency key. An import matches on a natural key and can be
replayed safely, while a POST that creates a record will create a
second one if you send it twice.
Rate limits
The admin API is limited per organization, not per key, so a second key does not add a second
allowance. Requests you make from the dashboard while signed in do not count. Exceeding
the limit returns 429 with a Retry-After header. See
Rate limits.
Changes to this API
New fields on a response and new optional parameters can appear at any time, so parse responses in a way that tolerates fields you do not recognize. Removing a field, removing an endpoint or changing what an existing parameter means is a breaking change, and is not something Meisei does silently.
There is no API version in the URL today, and no dated version to pin to.