Envie
Reference

Authentication & conventions

Calling the REST API without the SDK: the three auth modes as raw headers, plus the conventions every endpoint shares.

Everything the SDK does over HTTP you can do from any language — this page is the auth matrix and the house rules.

Base URL: https://api.getenvie.com · everything under /v1.

The three auth modes, as requests

Liquid storefronts — the app proxy (no key)

Theme code calls the shop's own domain under /apps/envie/*; Shopify signs the request and forwards it to Envie. Never call api.getenvie.com from a Liquid theme — only the proxy carries the signature.

# From theme JS this is just a same-origin fetch:
curl "https://your-store.myshopify.com/apps/envie/wishlist"

Headless browsers — public key

Two headers, browser-safe, anonymous scope only:

curl "https://api.getenvie.com/v1/storefront/wishlist?aid=1e5f4b6a-0000-4000-8000-000000000000" \
  -H "X-Envie-Shop: your-store.myshopify.com" \
  -H "X-Envie-Public-Key: env_pk_your_store_xxxxxxxx"

aid is the shopper's anonymous id — a UUID your code mints once and keeps in the browser. Your storefront's origin must be declared under Envie → Developers (CORS is enforced against that list). A public key can never act as a logged-in customer.

Servers — private key

One header, full shop scope, server-side only:

curl "https://api.getenvie.com/v1/shop" \
  -H "Authorization: Bearer env_sk_your_key"

Keys are created in Envie → Developers, shown once, revocable in one click. If one ever reaches a browser or a repo, rotate it.

Which endpoints take which mode

SurfacePathsModes
Storefront/v1/storefront/*proxy · public · private
Privateeverything else (/v1/shop, /v1/lists, …)private only

The generated reference marks the accepted modes per endpoint, and its playground sends real requests from your browser.

Conventions (all endpoints)

  • Ids are strings. Shopify's 64-bit ids overflow JSON numbers, so they travel as decimal strings: "productId": "8123456789012". Envie's own ids carry a type prefix (lst_…, itm_…) — a wrong-prefix id is a 400, not a mysterious 404.
  • Times are ISO-8601 UTC. 2026-08-05T14:32:11.000Z.
  • Pagination is cursor-based. ?cursor=&limit= (limit ≤ 100); responses carry pageInfo.nextCursor, null when done. No page numbers, no offsets.
  • Idempotency. Send an Idempotency-Key header (any unique string) on any POST; a retry with the same key within 24 h returns the original result instead of repeating the work.
  • Errors are problem documents. RFC 9457 application/problem+json, with a stable type URL that resolves to an explanation. Branch on type, never on message text.
  • Rate limits. 60/min storefront, 600/min private; budget on X-RateLimit-Remaining-* headers, 429 carries Retry-After. Details in limits.
  • Stability. Additive-only within /v1: fields are never removed or repurposed, deprecations are announced at least 90 days ahead (changelog + Deprecation header), breaking changes only ever in a /v2.

A complete round trip

# Save an item (public mode), idempotently:
curl -X POST "https://api.getenvie.com/v1/storefront/wishlist/toggle" \
  -H "X-Envie-Shop: your-store.myshopify.com" \
  -H "X-Envie-Public-Key: env_pk_your_store_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5f3c1a2b-save-hoodie" \
  -d '{
    "productId": "8123456789012",
    "handle": "soft-hoodie",
    "anonymousId": "1e5f4b6a-0000-4000-8000-000000000000"
  }'
# → { "added": true, "count": 1, "itemId": "itm_…" }

The machine-readable version of this page is the spec itself: /openapi.json.

On this page