Skip to main content

Authentication & scopes

Three auth surfaces

Each surface has a distinct auth model — appropriate to its threat surface and use case.

SurfaceAuth methodGranularity
Admin API (/api/v1/...)Bearer token (copt_...)Per-token scopes
Public endpoints (/api/public/...)None (CORS allow-list) or API key (pk_...)Per-shop
Webhooks (inbound)HMAC SHA-256 signaturePer-source secret
Webhooks (outbound)HMAC SHA-256 signature you signPer-endpoint secret

Admin API — bearer tokens

Token format

copt_live_aB3xY9zKqMnPwR2vT4uH7jL5sQ8eFc1g
  • copt_ prefix identifies as Sumeru Systems API token
  • live_ (or test_) environment marker
  • 32-character random body (base62)

Tokens are stored as SHA-256 hashes; the raw token is shown once at creation and never displayed again.

Creating tokens

Admin UI: Settings → API tokens → Create. Pick scopes (see catalog below). Token shown once.

Programmatic creation (for managing many shops): use the /api/v1/api-keys endpoint with a master token (Enterprise).

Sending the token

GET /api/v1/customers/cus_abc123 HTTP/1.1
Host: api.sumeru.systems
Authorization: Bearer copt_live_aB3xY9zKqMnPwR2vT4uH7jL5sQ8eFc1g

Authorization header is required on every admin API call.

Token security

  • Tokens are stored hashed (SHA-256); raw never persisted
  • All token comparisons use crypto.timingSafeEqual
  • Tokens can be rotated anytime (old token revoked immediately)
  • Tokens are scope-gated; minimum-privilege principle
  • Admin UI shows last-used timestamp + IP per token

Scopes catalog

ScopeWhat it grants
customers:readRead Customer 360 profiles
customers:writeUpdate profiles, tag, enroll in journeys
orders:readRead order history
orders:writeCreate / cancel / refund orders
attribution:readRead attribution data
campaigns:readRead campaigns
campaigns:writeCreate / launch / pause campaigns
journeys:readRead journeys + enrollments
journeys:writeCreate / edit / pause journeys
products:readRead product catalog
products:writeUpdate products, prices, inventory
analytics:readRead dashboards + DIE recommendations
webhooks:readList webhook subscriptions
webhooks:writeCreate / update webhook subscriptions
audit:readRead audit log
*All scopes (admin only — discouraged)

Tokens declare their scopes at creation; the API enforces on every call. Calling an endpoint outside scope returns 403 with code scope_required.

Public endpoints — CORS or API key

Public endpoints are storefront-facing (called from your shop's JavaScript). They use:

CORS allow-list (default)

Each shop has a configured allow-list of domains (yourshop.com, www.yourshop.com). Requests from those origins succeed without an API key.

fetch('https://api.sumeru.systems/api/public/reviews', {
headers: { 'X-Shop-Domain': 'yourshop.com' }
})

API key (for headless / custom platforms)

For storefronts not on standard Shopify domains (Hydrogen, custom Next.js, etc.):

pk_live_xY7aB3cKz9...

Sent as X-Public-Key header. Public keys are scoped to public endpoints only — cannot access admin API.

Webhooks — HMAC signatures

Inbound (Sumeru receiving)

When Shopify / WhatsApp / marketplace fires a webhook to Sumeru, the body is HMAC-signed by the source. We verify:

  • Shopify: HMAC-SHA256 with shop secret, X-Shopify-Hmac-Sha256 header
  • WhatsApp (Meta): HMAC-SHA256 with app secret, X-Hub-Signature-256 header
  • Marketplaces: per-marketplace contract (per webhooks)

Signature mismatches reject with 401.

Outbound (Sumeru notifying you)

When Sumeru sends events to your endpoint (Zapier, custom integration), we HMAC-sign the body. You verify:

const crypto = require('crypto');

function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

Header: X-Sumeru-Signature: sha256=<hex>

Your endpoint secret is shown once at webhook subscription creation. Rotate via the admin or API.

Shopify scopes (the underlying)

Sumeru as a Shopify app declares these scopes; you'll see them at install:

  • read_customers, write_customers
  • read_orders, write_orders
  • read_products, write_products
  • read_marketing_events, write_marketing_events
  • read_orders (extended retention) — for predictive LTV
  • read_themes — pixel install verification
  • read_locales — for translation routing
  • read_inventory, write_inventory

These are Shopify-side scopes the merchant approves at install. The Sumeru admin token scopes (above) gate Sumeru API access on top of whatever Shopify-side access the app has.

Token rotation

POST /api/v1/api-keys/<id>/rotate HTTP/1.1
Authorization: Bearer copt_live_...

Returns the new token in the response. The old token is revoked immediately. Plan for ~5 seconds of overlap if your client is mid-flight when rotation fires.

Brute-force / rate-limit protection

  • Failed auth attempts rate-limited at 10/min per IP
  • 100 failed attempts in 24h: IP blocked for 1h
  • 1000 failed attempts in 24h: alert to admin

Successful auth resets counters per IP.

See also