Skip to main content
This guide explains why you’d move an existing integration from V2 to V3, and how to do it endpoint by endpoint. V3 is the recommended standard for all new work.

Why migrate

V3 is a ground-up refresh that standardizes conventions across every endpoint and unlocks surfaces that V2 never exposed.
You don’t have to migrate everything at once. A common path is: keep V2 gifting running, adopt V3 Marketplace for catalog reads first (biggest performance win, lowest risk), then move order placement to V3 Orders.

Before you begin

Your existing API key already works

The same X-Api-Key authenticates both V2 and V3. The version lives in the URL path - there is nothing new to provision to start calling V3.
Scopes are shared too: a key with 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

V3 responses include a top-level links object - use links.next verbatim to fetch the next page rather than building URLs yourself:
High-volume product list endpoints (GET /v3/products, GET /v3/collections/{id}/products, GET /v3/products/{id}/variants) use cursor pagination instead: page[cursor] + page[size]. links.prev is always null (no backward navigation). Never parse or construct cursors manually - follow links.next.

Filtering & sorting: bespoke → JSON:API

Multiple 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):
V3 - one idempotent call:
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

Order-level webhooks fire alongside gift-level webhooks for V3 orders, so you can track delivery state without polling. See Webhook Event Types.

Deep dive - Marketplace (Products, Variants & Collections)

V2 modeled the catalog as a single Product object with an embedded variants 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:
V3 - JSON:API filters, cursor pagination:

Getting variants

In V2, both GET /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

Maintaining a local mirror of the catalog? V3 adds an asynchronous, NDJSON-based Export API - pair it with stock-availability-updates webhooks for incremental refresh instead of repeatedly paging the list endpoints.

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:
The main change is 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.
Need a hand planning your migration? Reach out to your Snappy contact.
Last modified on July 22, 2026