API v1
Public API v1 contract
The thirty current operations, authentication, pagination, idempotent writes, errors, fixed-window rate limits, and limitations.
The current base path is /api/v1. Send an installation-bound access token from your server as Authorization: Bearer <ACCESS_TOKEN>. The Marketplace feature must be enabled; otherwise the surface is unavailable.
Current operations
| Method and path | Required scope | Current resource coverage |
|---|---|---|
GET /api/v1/catalog/products | catalog:read | Product list fields. |
GET /api/v1/orders | orders:read | Order summary fields. |
GET /api/v1/webhooks | webhooks:manage | Installation subscriptions. |
POST /api/v1/webhooks | webhooks:manage | Create or rotate a subscription secret. |
DELETE /api/v1/webhooks/{id} | webhooks:manage | Disable one installation subscription. |
GET /api/v1/customers | customers:read | Name, phone, email and creation time; no addresses or notes. |
GET /api/v1/discounts | discounts:read | Currently active rules; no customer redemptions. |
GET /api/v1/inventory/locations | inventory:read | Location names, type and active/default state. |
GET /api/v1/inventory/levels | inventory:read | Product, variant and location IDs; available, reserved and total quantities. |
GET /api/v1/inventory/movements | inventory:read | Product/location IDs, quantity delta, reason and creation time; no notes or staff identity. |
GET /api/v1/store | store:read | Store names, ID, subdomain and creation time; no private settings or bank details. |
GET /api/v1/catalog/products/{id} | catalog:read | One product with descriptions, options and variants. |
POST /api/v1/catalog/products | catalog:write | Create a product with basic fields. |
PATCH /api/v1/catalog/products/{id} | catalog:write | Update basic product fields. |
GET /api/v1/catalog/categories | categories:read | Active categories. |
GET /api/v1/orders/{id} | orders:read | One order summary. |
GET /api/v1/orders/{id}/items | orders:read_items | Line items without customer data. |
POST /api/v1/orders/{id}/tags | orders:write_tags | Add an internal tag owned by this app. |
DELETE /api/v1/orders/{id}/tags/{tag} | orders:write_tags | Remove a tag this app created. |
POST /api/v1/orders/{id}/fulfillments | orders:write_fulfillments | Record carrier and tracking and ship a confirmed or preparing order. |
GET /api/v1/customers/{id} | customers:read | One customer contact. |
POST /api/v1/customers/{id}/tags | customers:write_tags | Assign a customer tag. |
DELETE /api/v1/customers/{id}/tags/{tag} | customers:write_tags | Remove an assignment this app made. |
POST /api/v1/inventory/adjustments | inventory:write | Adjust stock at an active location. |
POST /api/v1/discounts | discounts:write | Create a discount code. |
PATCH /api/v1/discounts/{id} | discounts:write | Update a code this app created. |
GET /api/v1/app-data | app_data:manage | List private app data by owner record. |
GET /api/v1/app-data/{key} | app_data:manage | Read one private entry. |
PUT /api/v1/app-data/{key} | app_data:manage | Create or replace one private entry. |
DELETE /api/v1/app-data/{key} | app_data:manage | Delete one private entry. |
Generic order mutation, payment, refunds, shipping labels and messaging have no public API contract. Every referenced ID must belong to the installation store; other stores' records return 404.
Writes and idempotency
Every POST, PUT, PATCH and DELETE operation above requires an Idempotency-Key header of 8 to 128 characters from A-Z a-z 0-9 _ . : -. Retrying the same key with the same route, target and body within 24 hours returns the stored result without writing again. Reusing a key for a different request returns 409 idempotency_conflict. Bodies must be application/json objects of at most 32,768 bytes; unknown fields return 400 invalid_request. The database revalidates the token, grant, contract and release gate in the same transaction as the write, and every successful write is recorded in the Marketplace audit log. Changes made through these operations emit the existing resource webhooks, for example products.updated or orders.fulfilled.
Pagination
The product and order list operations accept limit from 1 through 100, default 25, and an ISO timestamp before. Responses contain meta.limit and meta.next_before. A non-date cursor returns 400 with invalid_before_cursor.
The cursor read endpoints (customers, discounts, inventory, store and categories) return data and meta.next_cursor. Pass both before and before_id exactly as returned, preserving timestamp microseconds. Rows sort by (created_at, id) descending, so equal timestamps do not skip rows. A null cursor means the page is final. limit defaults to 25 and must be an integer from 1 to 100. Partial cursors, repeated or unknown query parameters (including tenant_id) return 400 invalid_pagination. The database rechecks the original token, current grant and release gate in the same transaction as the data read; previously resolved access cannot outlive a committed revocation.
Error behavior
API v1 errors use this envelope:
{"error":{"code":"invalid_token"}}Known status classes include 400 invalid input (invalid_request, invalid_json, invalid_pagination), 401 invalid token, 403 unsupported capability or denied webhook creation, 404 unavailable surface or a record outside your store, 409 idempotency_conflict, invalid_transition or conflict, 413 oversized body, 415 non-JSON write body, 422 validation_failed or quota_exceeded, 429 rate limit, 500 query/mutation failure, and 503 rate-limit service unavailable. Write errors may include error.field naming the rejected input. Use the code, not prose matching. Retry writes only with the same Idempotency-Key and bounded backoff.
Rate limits
The actual policy is 60 requests per 60-second fixed window, per installation, per route key. Successful authorization returns RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A 429 also returns Retry-After. The limit is not per token, per app globally, or per tenant globally.
Versioning and limitations
The path version is v1. Formal deprecation governance and migration guides are PLANNED; consult the changelog before upgrades. Order summaries do not include customer records; line items require orders:read_items. Response fields are defined by the OpenAPI reference and may be narrower than internal commerce models.