An Order represents the physical fulfillment event - the point at which a gift becomes a shipment. The Order is the primary integration object for Direct Fulfillment: you create it via a single call to POST /v3/orders with the recipient and variant details, then track its progress through the lifecycle.
Orders are also generated automatically by Snappy when a recipient claims their gift in the Triggered Gifting model - those orders are retrievable, listable, and cancellable through the same V3 Orders API.
The V3 Orders API exposes Orders as first-class resources with their own lifecycle, line items, fulfillments, and tracking - independent of the Gift entity. You no longer need to retrieve orders through their parent Gift.
The Order Object
| Field | Type | Description |
|---|
id | string | Unique identifier of the Order (e.g. G7nR4bD9mK) |
status | enum | Order lifecycle status. One of: active, completed, cancelled, refunded |
fulfillmentStatus | enum | Aggregated fulfillment status across all line items. One of: unfulfilled, fulfilled, cancelled |
idempotencyKey | string | Caller-supplied idempotency key from order creation |
tags | string array | Caller-supplied tags for grouping and filtering orders in reports |
lineItems | array | Products included in this Order. See Line items below. |
fulfillments | array | Fulfillment records - shipments with carrier, tracking info, and delivery status. See Fulfillments below. |
recipient | object | Recipient contact details. See Recipient below. |
shippingAddress | object | Physical shipping address. See Shipping address below. |
metadata | object | Caller-supplied key-value pairs. null when no metadata was supplied. |
cancellationDetails | object | Populated only when status is cancelled. See Cancellation details below. |
Order status
| Status | Description |
|---|
active | Being processed or in fulfillment |
completed | Fulfilled and finalized |
cancelled | Cancelled before fulfillment |
refunded | Returned and refunded after delivery |
Fulfillment status
Aggregated across all line items.
| Status | Description |
|---|
unfulfilled | No fulfillments exist yet |
fulfilled | Every line item is covered by a fulfillment record |
cancelled | Order fulfillment was cancelled |
Line items
| Field | Type | Description |
|---|
variantId | string | Variant ID of the ordered product |
title | string | Product title captured at the time of order |
quantity | integer | Number of units of this variant ordered |
Fulfillments
A Fulfillment represents a shipment containing one or more line items. An Order can have multiple Fulfillments (e.g. split shipments), and a Fulfillment can cover multiple line items (e.g. consolidated shipping). This is a many-to-many relationship between line items and fulfillments.
| Field | Type | Description |
|---|
id | string | Unique identifier of the fulfillment record |
status | enum | Carrier delivery status. See Delivery statuses below. |
trackingCompany | string | Carrier name (e.g. UPS, USPS, FedEx) |
trackingInfo.number | string | Carrier tracking number |
trackingInfo.url | string | Carrier tracking page URL |
fulfillmentLineItems | array | Line items included in this fulfillment |
Delivery statuses
| Status | Description |
|---|
confirmed | Order received by the vendor |
processing | Being prepared for shipment |
in_transit | Shipped and in transit |
out_for_delivery | Out for delivery |
delivered | Delivered to the recipient |
Use Webhooks to track delivery status changes in real time rather than polling. See Webhook Event Types.
Recipient
| Field | Type | Description |
|---|
firstName | string | Recipient first name |
lastName | string | Recipient last name |
email | string | Recipient email address |
phone | string | E.164 phone number |
Shipping address
| Field | Type | Description |
|---|
address1 | string | Street address (max 35 chars) |
address2 | string | Apartment, suite, floor (max 35 chars) |
city | string | City name |
provinceCode | string | State or province code (2-3 uppercase letters) |
postalCode | string | Postal/ZIP code (alphanumeric, 3-10 chars) |
countryCode | string | ISO 3166-1 alpha-2 country code (uppercase) |
Cancellation details
| Field | Type | Description |
|---|
cancelledAt | string (ISO 8601) | Timestamp when the Order was cancelled |
cancellationReason | enum | Reason for cancellation. Currently only: customer_requested |
Key Concepts & Business Rules
Idempotency on order placement
Every POST /v3/orders request must include an idempotencyKey (1-120 characters). If a request with the same key has already succeeded for this Company, the original order is returned - no duplicate is created. Use stable, caller-generated keys (e.g. your internal order ID).
See Duplicate Detection for the full idempotency reference.
Variants are required - not Products
When placing an order, you must always specify the variantId, not the productId. Every Product has at least one Variant, even if it has no variations. See Products & Variants Overview.
Two separate fields with different purposes:
tags - array of strings for grouping and filtering orders in reports (e.g. ["q4-campaign", "vip"]).
metadata - key-value object for arbitrary passthrough data (e.g. {"externalRecipientId": "crm-user-987"}). Up to 50 pairs, keys up to 40 chars, values up to 500 chars.
Use tags for categorization; use metadata for data you want to round-trip.
Status vs fulfillment status
The Order has two distinct status fields that capture different concerns:
status tracks the commercial lifecycle: active → completed, or active → cancelled / refunded
fulfillmentStatus tracks the physical lifecycle aggregated across line items: unfulfilled → fulfilled (or cancelled)
Per-shipment carrier progress lives inside fulfillments[].status.
Cancellation rules
Orders can only be cancelled before they are picked up by the fulfillment partner. Once an Order is in transit, cancellation returns 422. The cancellationReason enum currently only supports customer_requested; additional reasons may be added in future releases.
Address validation reduces fulfillment failures
Invalid or incomplete shipping addresses are a common cause of fulfillment failures. We recommend validating the recipient’s address via POST /orders/addresses/validate before calling POST /v3/orders, especially when addresses are entered by end users in your platform UI.
Billing is triggered at order creation
The Billing Method (referenced via billingMethodId) is debited when an Order is successfully placed. If the Billing Method has insufficient funds at the time of the request, the order will not be processed. See Billing Methods Overview to check remaining balance before placing high-value orders.
The V3 list endpoint uses page-number pagination (page[number] and page[size], max 300, default 100). Responses include a top-level links object with first, next, and prev URLs.
See Request & Response Standards for the full V3 pagination contract.
Account scoping
Pass the optional Snappy-Account-Id header to scope queries to a specific Account. For POST /v3/orders, accountId may alternatively be supplied in the request body - the header takes precedence when both are provided. The optional Snappy-Company-Id header further scopes to a specific Company.
Permissions
The V3 Orders endpoints require different scopes depending on the operation:
| Endpoint | Required scope |
|---|
POST /v3/orders | orders:create |
GET /v3/orders | orders:read:masked or orders:read:unmasked |
GET /v3/orders/{orderId} | orders:read:masked or orders:read:unmasked |
POST /v3/orders/{orderId}/cancel | orders:cancel |
PII fields (recipient name, tracking info) are masked under orders:read:masked and returned in full under orders:read:unmasked.
How to Work with Orders
Place an order (Direct Fulfillment)
Creates a new Order for a single variant on behalf of a recipient. Returns a minimal create result with the Order ID, initial status (active), and a tracking link. Required: billingMethodId, variantId, recipient, shippingAddress, idempotencyKey. Optional: accountId, tags, metadata.
List orders
Returns a paginated list of Orders matching the supplied filters. Filter by status (active, cancelled), idempotencyKey (comma-separated array), or createdAt range. Sort by createdAt (newest first by default).
Get an order by ID
Retrieves a single Order with full detail - line items, recipient, shipping address, fulfillments, and tracking info.
Cancel an order
POST /v3/orders/{orderId}/cancel
Cancels an Order that has not yet been fulfilled. Returns the Order in its post-cancellation state with status: "cancelled" and a populated cancellationDetails object. Returns 422 if the Order has already been picked up by the fulfillment partner.