Skip to main content
This page is the Dev API overview, not the best first page for every workflow.Use this quick routing:

Guide vs Reference

  • /themes/* explains the theme workflow and when to use inspect, apply, validate, preview, and publish
  • /api-reference/* explains the Dev API shape, auth, scopes, and endpoint details
Use the theme pages to understand the workflow. Use the API reference when you already know the workflow and need the exact request shape.

Official SDKs

If you do not want to hand-write requests, use an official SDK: For example, your Node backend creating orders uses @shoppexio/sdk, a Python cron job reading customers uses shoppexio, and a Laravel admin tool rotating webhooks uses shoppexio/shoppex-php.

SDKs & Libraries

Official Shoppex SDKs, install commands, public repos, and language examples.

Base URL

All API requests should be made to:
https://api.shoppex.io/dev/v1

Authentication

The Shoppex API uses Bearer token authentication. You can authenticate with:
  • an API key like shx_...
  • an OAuth2 access token like shpat_...
An internal sync worker would use Authorization: Bearer shx_your_api_key_here, while an installable ERP app would use Authorization: Bearer shpat_your_access_token_here. Include the token in the Authorization header:
Authorization: Bearer shx_your_api_key_here
Keep your API keys secure. Never expose them in client-side code or public repositories.
API keys can be limited with scopes.
  • orders.read
  • disputes.read
  • subscriptions.write
  • payment_links.write
  • products.read
  • customers.write
  • analytics.read
  • analytics.write
  • affiliates.read
  • affiliates.write
  • webhooks.write
  • themes.read
  • themes.write
  • licenses.read
  • licenses.write
  • security.read
  • security.write
  • store.read
  • store.write
  • * for full access
OAuth2 access tokens use the same Dev API scopes. For instance, your app requests orders.read customers.read, the merchant approves, and the exchanged shpat_... token can then only read orders and customers.

Getting Your API Key

  1. Log in to dashboard.shoppex.io
  2. Go to Settings → API Keys
  3. Click Generate New Key
  4. Choose the scopes your integration needs
  5. Copy and store your key securely (it starts with shx_)
API keys are shown only once when created. Store them in a secure location like a password manager or environment variables.
If your goal is theme automation, the usual beginner setup is:
  • API key auth
  • themes.read
  • themes.write
Claude Code or Codex editing your theme through the Shoppex theme workflow usually needs themes.read themes.write.

Capabilities Endpoint

Use GET /me/capabilities to inspect the active key at runtime.
curl https://api.shoppex.io/dev/v1/me/capabilities \
  -H "Authorization: Bearer shx_your_api_key"
This response tells you:
  • which scopes are active
  • whether the key has full access
  • which resource groups are readable or writable
  • which payment methods are enabled for the shop
  • which gated Dev API features are enabled for the shop
Notably, enabledPaymentMethods tells you whether normal gateways like Stripe or PayPal are active, and features.white_label_crypto_checkout.enabled tells you whether your shop may request raw crypto payment data for a custom UI or bot flow. If you authenticated with OAuth2, the capabilities response also tells you which OAuth client issued the current access token.

Request Format

All requests should:
  • Use Content-Type: application/json
  • Send JSON-encoded request bodies
  • Include the Authorization header
curl https://api.shoppex.io/dev/v1/invoices \
  -H "Authorization: Bearer shx_your_api_key_or_shpat_access_token" \
  -H "Content-Type: application/json"

OAuth2 Flow

For third-party apps, Shoppex also supports an OAuth2 authorization-code flow:
1

Redirect to Authorize

Merchant is redirected to GET /dev/v1/oauth/authorize
2

Merchant Approval

Shoppex shows a hosted approval screen for the active merchant session
3

Receive Authorization Code

After approval, Shoppex redirects back with a short-lived shoa_... code
4

Exchange Code for Token

Your app exchanges the code at POST /dev/v1/oauth/token
5

Call API with Access Token

Your app calls normal /dev/v1/* endpoints with the returned shpat_... access token
In practice: the browser redirects to /dev/v1/oauth/authorize?..., the merchant approves on the Shoppex-hosted page, your backend exchanges the code via POST /dev/v1/oauth/token, then calls GET /dev/v1/orders with Authorization: Bearer shpat_.... Important:
  • /dev/v1/oauth/token returns standard OAuth2 JSON, not the normal Shoppex API envelope
  • normal Dev API resource endpoints still use the standard Shoppex response format

Payment Retries And Gateway Switches

Shoppex may create more than one internal payment attempt for the same invoice. A customer might start with PayPal, close the checkout, reopen the invoice, and finish with Stripe. This catches most people off guard: treat the Shoppex invoice or payment ID as the source of truth, not a single provider session or order ID.
  • use GET /orders for your operational order queue
  • use POST /orders when your backend wants to create a pending order from catalog line items
  • use POST /orders/:id/fulfill for a server-side fulfillment trigger on a pending order
  • use POST /orders/:id/refund for merchant-driven refunds without the dashboard
  • use GET /disputes for chargebacks and payment-risk review
  • use GET /invoices when you need the lower-level invoice resource directly
  • use POST /payment-links or POST /payment-links/:id/toggle for sales-link workflows
  • use GET /coupons/code/:code for server-side coupon validation by code
  • use POST /subscriptions/:id/pause or PATCH /subscriptions/:id/custom-fields for recurring billing workflows
  • use POST /customers/:id/wallet/credit or POST /customers/:id/wallet/debit for store-credit adjustments
  • use GET /customers/:id?include_affiliate=true when you need customer detail plus affiliate summary in one response
  • use GET /products/:id/variants/fields, POST /products/:id/variants/fields, or POST /products/:id/variants/fields/:fieldId/options for variant configuration tooling
  • use GET /products?include_variants=true when you need product reads with inline variant prices
  • use GET /analytics/reports or POST /analytics/reports/:id/generate for scheduled exports
  • use GET /affiliates/customers or POST /affiliates/applications/:id/approve for affiliate program automation
  • use GET /store/branding, POST /store/domains/additional, GET /store/domains/additional/:id/verification, or PUT /store/layout for storefront automation
  • use GET /themes/:id/control/inspect, POST /themes/:id/control/apply, POST /themes/:id/control/preview, GET /themes/:id/control/preview/starts/:startId, or POST /themes/:id/control/publish for theme automation
  • use GET /licenses, POST /licenses, PATCH /licenses/:id, or DELETE /licenses/:id for license support workflows
  • use POST /webhooks/logs/:id/retry or POST /webhooks/:id/rotate-secret for webhook ops workflows
  • use GET /security/audit-trail or GET /security/session-trail/:session_id for security and support workflows
Coupon note:
  • the public storefront flow already had POST /v1/storefront/coupons/check
  • GET /coupons/code/:code is the server-to-server Dev API equivalent
The reliable pattern: use Shoppex invoice/payment responses, listen to Shoppex webhooks, and make your fulfillment logic idempotent. Do not assume one invoice always maps to exactly one provider-side payment session.

Theme Automation Shortcut

If you came here for themes, the usual endpoint family is:
  • POST /themes/control/create
  • GET /themes/{id}/control/inspect
  • GET /themes/{id}/control/diff
  • POST /themes/{id}/control/apply
  • POST /themes/{id}/control/validate
  • POST /themes/{id}/control/preview
  • GET /themes/{id}/control/preview/starts/{startId}
  • POST /themes/{id}/control/publish
Best reading order:
  1. Build and Customize a Theme with AI
  2. Editing Themes
  3. this API reference for the exact endpoint details

Response Format

All responses return JSON with a consistent structure: Authenticated Dev API responses also include X-Request-Id. If you send X-Request-Id: sync-run-42, Shoppex echoes that same id back. If you don’t send one, Shoppex generates one for you — useful for correlating logs when debugging.
{
  "data": {
    "id": "abc123",
    "status": "COMPLETED"
  }
}

HTTP Status Codes

All error responses follow the standard error envelope format. See the Error Handling guide for detailed error codes.
CodeDescription
200Success
201Resource created
400Business rule or domain-specific request error
401Unauthorized (invalid or missing API key)
403Forbidden (missing scope or suspended shop)
404Resource not found
422Validation error for request body, params, or query
429Rate limit exceeded
500Internal server error

Request Tracing

Use X-Request-Id to correlate your logs with Shoppex responses.
X-Request-Id: sync-run-42
Shoppex returns the same header on success and error responses.

Rate Limiting

API requests are limited to protect the service. When you exceed the limit, you’ll receive a 429 Too Many Requests response. Authenticated Dev API requests return these headers:
  • X-RateLimit-Limit
  • X-RateLimit-Remaining
  • X-RateLimit-Reset
  • Retry-After when the request is blocked
When you hit the limit, the headers look like this:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 5
Retry-After: 5
Rate limits are plan-dependent. The values above are illustrative. Check the response headers from your actual requests for your current limits.
If rate limited, wait until X-RateLimit-Reset or Retry-After before retrying.

Idempotency

All current state-changing /dev/v1 endpoints support idempotent retries. This covers product, category, group, coupon, variant, customer, webhook, ticket, review, blacklist, license, escrow, invoice, and payment writes. Retrying POST /customers after a timeout won’t create the same customer twice, and retrying POST /webhooks/:id/test won’t spam duplicate test deliveries. Use one of these headers:
  • Idempotency-Key
  • X-Idempotency-Key
curl https://api.shoppex.io/dev/v1/payments \
  -X POST \
  -H "Authorization: Bearer shx_your_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payment-create-123" \
  -d '{"title":"Order #1001","email":"[email protected]","value":49.99,"currency":"USD"}'
Responses include an Idempotency-Status header:
  • created when the request created a new payment
  • cached when Shoppex replayed the stored response
  • processing when the same key is still in flight
  • bypassed when idempotency was intentionally skipped
Important behavior:
  • the replay key is scoped to your authenticated key, the route, and the idempotency key
  • Shoppex also checks the request body for the same method and path
  • the replay window is currently 24 hours
  • 5xx responses are not cached for replay
In other words: same key + same body = cached response, same key + different body = validation error, same key while the first request is still in flight = processing.

Pagination

The Dev API currently uses two pagination models: cursor-based pagination for feed-style entity lists (products, invoices, orders, customers, subscriptions) and page-based pagination for operational lists (webhook delivery logs, affiliate review queues). Most resource lists use cursor-based pagination with cursor and limit parameters.
For detailed pagination patterns, code examples, and best practices, see the Pagination guide.

Filtering

Core list endpoints now support a shared filtering and sorting contract:
# Filter by exact fields
GET /orders?filters=status:COMPLETED,customer_email:[email protected]

# Sort oldest first
GET /customers?sorts=created_at

# Sort newest first (default)
GET /invoices?sorts=-created_at
Supported list endpoints for this shared contract:
  • GET /customers
  • GET /orders
  • GET /invoices
filters uses field:value pairs separated by commas.
filters=status:COMPLETED,customer_email:[email protected]
sorts=created_at     # oldest first
sorts=-created_at    # newest first (default)
Legacy single-field query params like status or customerEmail still work where already documented, but new integrations should prefer filters and sorts.