API docs: Requests and responses
Pagination
List endpoints return up to limit items (default 25, max 100), newest first. When has_more is true, pass next_cursor as the cursor parameter to get the next page. On the last page, next_cursor is null.
Cursors are opaque: pass them back exactly as you received them, and don't store them long-term or try to build your own.
New items never shift existing pages, so polling the first page reliably catches new orders.
curl "https://e2c.store/api/v1/orders?limit=50&cursor=ml-k3Q58S106wVawzKYPjKh88VSVcUhMVINaOHqpYMiBAA" \
-H "Authorization: Bearer $E2C_API_KEY"{
"data": [ { "order_number": 1042, "...": "..." } ],
"has_more": true,
"next_cursor": "ml-k3Q58S106wVawzKYPjKh88VSVcUhMVINaOHqpYMiBAA"
}Rate limits
Each key can make 60 requests per minute. Responses that pass authentication and the permission check include these headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | When the window resets, as Unix time. |
A request rejected before the permission check (bad key, wrong scope) has no rate-limit headers. Over the limit you get a 429 with a Retry-After header in seconds.
Dates and money
Times are ISO 8601 in UTC, like 2026-09-26T14:03:00Z. Date filters accept a date (2026-09-01, meaning midnight UTC) or a full date-time with an offset.
Order and product times recorded before June 20, 2026 were stored in US Eastern time and may read up to 5 hours early.
Money values are numbers with up to two decimals, with a currency code on the same object.
Writing data
Create with POST and edit with PATCH, sending a JSON object with Content-Type: application/json. A PATCH changes only the fields you send; leave a field out to keep its current value. Send null (or "") to clear an optional field. Unknown fields are rejected, so a typo never fails silently.
A successful POST returns 201 and a successful PATCH returns 200, both with the saved record in data, exactly as a GET would return it. Writes count toward the same rate limit as reads, and each one appears in your store's audit history under the API key's name.
The API never deletes anything. Hide a product or category by setting its status to inactive; delete it in the dashboard.
Errors
Errors use standard HTTP status codes and a JSON body with a stable, machine-readable code and a human-readable message.
{ "error": { "code": "insufficient_scope", "message": "This API key needs the 'products:read' permission." } }| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_parameter | A query parameter or body field is missing, or outside its expected format or range. The message names it. |
| 400 | invalid_body | The request body is not a JSON object. |
| 400 | prohibited_content | The text contains content that isn't allowed on E2C stores. |
| 401 | invalid_api_key | The key is missing, wrong, revoked, or expired - or was sent in the URL instead of the header. |
| 403 | insufficient_scope | The key is valid but lacks the permission this endpoint needs. |
| 404 | not_found | The endpoint, order, product, or category does not exist in your store. |
| 405 | method_not_allowed | The endpoint doesn't support this HTTP method. The Allow header lists the ones it does. |
| 409 | conflict | The change clashes with your store as it is now, such as a name or code that's already taken. The message says what to fix. |
| 409 | limit_reached | Your store already has the most categories or listings it can hold. |
| 413 | payload_too_large | The request body is larger than 64 KB. |
| 415 | unsupported_media_type | A write request was sent without Content-Type: application/json. |
| 429 | rate_limited | Too many requests. Wait for the number of seconds in the Retry-After header. |
| 500 | internal_error | Something went wrong on our side. Retry later. |