Why migrate
V3 is a ground-up refresh that standardizes conventions across every endpoint and unlocks surfaces that V2 never exposed.Before you begin
Your existing API key already works
The sameX-Api-Key authenticates both V2 and V3. The version lives in the URL path - there is nothing new to provision to start calling V3.
products:read already reaches both /v2/products and /v3/products. See Authentication & Security for the full scope table.
Generating an API key (recap)
If you’re starting fresh or want a dedicated key for your V3 rollout:1
Open Company Settings
Log in at login.snappy.com and go to Sharing & Access under Company Settings.
2
Generate a key
Under API Access, click Generate Key, name it, and set an expiration (up to one year).
3
Assign scopes
Grant the minimum scopes your integration needs (e.g.
products:read, orders:create, orders:read:masked). The same scopes apply to V2 and V3.4
Configure PII access
Toggle Expose Sensitive Information to decide whether reads resolve to
:read:masked or :read:unmasked.5
Copy the secret immediately
The secret is shown once. Store it securely - if you lose it, rotate the key.
Two ways to manage API keys. Create and manage keys in the Snappy dashboard on the Sharing & Access page, or manage them programmatically with an existing
X-Api-Key via the key-management endpoints (/v2/authentication/apiKeys or /v3/authentication/api-keys). See API Keys (V3).New optional scoping header (V3)
V3 endpoints accept an optional header that narrows a request to a sub-entity. Omit it to run against the full org reachable by the key.A few endpoints - currently the V3 Collections list and by-ID endpoints - require
Snappy-Account-Id. Each reference page notes when it applies.What changes at a glance
Most of the migration work is mechanical: swap the version in the path and adopt V3’s JSON:API query conventions. This table is your cheat sheet.Pagination: offset → page/cursor
links object - use links.next verbatim to fetch the next page rather than building URLs yourself:
Filtering & sorting: bespoke → JSON:API
filter[...] expressions are ANDed. Unknown filter keys return 400.
Hydration: expand[] → include
Deep dive - Orders
This is the biggest behavioral change in V3. In V2, an Order is a sub-entity of a Gift: even Direct Fulfillment goes through a two-step gift-and-claim flow, and you retrieve order state by reading the parent Gift. In V3, Orders are first-class - created, retrieved, listed, and cancelled directly.Placing an order
V2 - two steps (create gift, then claim):In V3 the recipient’s contact details and the shipping address are separate objects (
recipient + shippingAddress), whereas V2’s claim payload merged them. The idempotencyKey (1–120 chars) is required in V3 and replaces the V2 recipient key for double-billing protection.Retrieving, listing, and cancelling
Order field mapping
Deep dive - Marketplace (Products, Variants & Collections)
V2 modeled the catalog as a single Product object with an embeddedvariants array. V3 splits Products (display-level) and Variants (orderable units) into separate resources with their own endpoints, and adds the marketplace vs swag catalog split.
Listing products
V2 - budget is required,types is an array, offset pagination:
Getting variants
In V2, bothGET /v2/products/{id} and GET /v2/variants/{id} returned the full Product object with a variants array. In V3 the entities are cleanly separated:
Key catalog differences
Everything else: endpoint mapping
The remaining domains keep identical functionality in V3 - the same operations and data, relocated to/v3/... and re-skinned in V3 conventions (camelCase, filter[...], page[...], include). Migrating these is the mechanical swap described in What changes at a glance: change the path, update pagination/filter params, and adjust field casing.
Scopes are unchanged across versions - e.g.
campaigns:create, recipients:read:masked, accounts:read work for both /v2 and /v3. You do not need to regenerate keys to call the V3 equivalents.Error handling
The error object stays a flat shape in V3, with the same split between validation (400) and everything else:
errorCode: V3 uses the structured format {STATUS}_{DOMAIN}_{SEQUENCE} (e.g. 404_PROD_001, 403_PBLC_001), while V2 uses symbolic codes (e.g. NOT_FOUND). Switch on errorCode, never on message. See Request & Response Standards and Error Handling.
Migration checklist
1
Confirm your key reaches V3
Repeat one existing V2 read against the
/v3/... path with the same X-Api-Key. If it returns data, you’re ready - no new credentials needed.2
Adopt V3 query conventions
Update your client’s pagination (
page[...]), filtering (filter[...]), sorting (sort=), and hydration (include=) helpers. Follow links.next verbatim.3
Migrate catalog reads first
Move Products/Variants/Collections to V3 - lowest risk, biggest performance win. Split your product-and-variants reads into the separate V3 endpoints and start caching the now-static IDs.
4
Move order placement to V3 Orders
Replace the gift-create → claim flow with a single
POST /v3/orders. Generate a stable idempotencyKey per order and split recipient vs shippingAddress. Read order state from GET /v3/orders/{orderId} instead of the parent Gift.5
Update error handling
Switch your error branching to the structured
errorCode format.6
Migrate remaining domains
Apply the mechanical path/convention swap to Campaigns, Gifts, Recipients, Accounts, and address endpoints. Adopt Billing Methods to pre-check funds before high-value orders.
7
Run both versions in parallel, then cut over
Because the same key serves both, you can ship V3 per domain behind a flag, verify, and retire the V2 calls when you’re confident.