> ## Documentation Index
> Fetch the complete documentation index at: https://docs.snappy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Place order

> Use this endpoint to create a new order for a specific product variant on behalf of a recipient via the Direct Fulfillment integration. Use this when you already know the recipient's shipping address and the exact variant to ship - V3 collapses gift creation and order placement into a single idempotent call.

###### Required fields:
- `billingMethodId` - the Billing Method that will pay for the order. Must belong to the specified Account. Use GET /v3/billing-methods to discover available methods.
- `variantId` - the specific product variant to order. Use GET /v3/products to browse variants.
- `recipient` - recipient contact information. Requires firstName, lastName, email, and phone (E.164 format).
- `shippingAddress` - physical shipping address. Requires address1, city, provinceCode (2-3 uppercase letters), postalCode, and countryCode (ISO 3166-1 alpha-2).
- `idempotencyKey` - a stable, caller-generated key (1-120 characters). Replaying the same request with the same key returns the original order without creating a duplicate.

###### Optional fields:
- `accountId` - the Account placing the order. May be supplied here in the body or via the Snappy-Account-Id header (header takes precedence when both are provided).
- `tags` - array of strings for grouping orders in reports (e.g. ["q4-campaign", "vip"]).
- `metadata` - key-value object for caller-supplied passthrough data. Up to 50 pairs; keys up to 40 chars; values up to 500 chars.
- `Snappy-Company-Id` header - optional company scoping.

###### Behavior Notes:
- The response is minimal: { id, status, trackingLink }. Use GET /v3/orders/{orderId} to retrieve the full Order with line items, fulfillments, and tracking detail.
- `status` is always active immediately after a successful placement.
- The Billing Method is debited on successful order creation. If it has insufficient funds at the time of the request, the order is not processed (422).
- Returns `422` for business-rule violations (insufficient funds, variant unavailable in the recipient's country, variant not found, etc.).
- Returns `404` if the referenced `accountId`, `billingMethodId`, or `variantId` does not exist or is not accessible to the calling Company.
- `address2` on the shipping address is optional but recommended (apartment, suite, floor, etc.) - incomplete addresses are a leading cause of fulfillment failures.

#### Permissions
- Requires: `gifts:create` or `orders:create`



## OpenAPI

````yaml post /v3/orders
openapi: 3.0.3
info:
  title: Snappy Public API v3
  version: 3.0.0
  contact:
    name: Snappy Support
    email: info@snappy.com
  description: >-
    Welcome to the Snappy API reference documentation!

    You can use this API to integrate with Snappy and spread smiles to your
    employees/clients/customers and much more.

    So let's get started!
servers:
  - url: https://api.snappy.com/public-api
    description: Base API URL
  - url: https://mtls-api.snappy.com/public-api
    description: >-
      ## mTLS URL

      You can also use mTLS to enhance your API security. To get your specific
      certificates please contact our support.

      Once you configure the certificated correctly, you need to also update
      endpoints to use the following secure api base URL:
security: []
tags:
  - name: Products
    description: >-
      Use these endpoints to retrieve products and tags for building catalog and
      browse experiences in your UI.
  - name: Collections
    description: >-
      Use these endpoints to retrieve products within curated collections for
      marketplace and browse experiences.
  - name: Variants
    description: >-
      Use these endpoints to retrieve variants, variant pricing, and country
      availability for orderable product SKUs.
  - name: Billing Methods
    description: >-
      A **Billing Method** is the funding source attached to an **Account** -
      for example, a Purchase Order (PO), Invoice, Prepay deposit, or Credit
      Card. Use these endpoints to retrieve billing method details such as
      remaining balance, status, and expiration.
  - name: Accounts
    description: >-
      An **Account** is a sub-entity within a **Company**, used to organize
      campaigns and gift sends. Use these endpoints to list, retrieve, and
      create accounts.
  - name: API Keys
    description: >-
      Use these endpoints to manage API keys for programmatic access. Key
      management requires company owner privileges.
  - name: Orders
    description: >-
      Use these endpoints to place, retrieve, cancel, and validate orders and
      shipping addresses.
paths:
  /v3/orders:
    post:
      tags:
        - Orders
      summary: Place an order - v3
      description: >-
        Use this endpoint to create a new order for a specific product variant
        on behalf of a recipient via the Direct Fulfillment integration. Use
        this when you already know the recipient's shipping address and the
        exact variant to ship - V3 collapses gift creation and order placement
        into a single idempotent call.


        ###### Required fields:

        - `billingMethodId` - the Billing Method that will pay for the order.
        Must belong to the specified Account. Use GET /v3/billing-methods to
        discover available methods.

        - `variantId` - the specific product variant to order. Use GET
        /v3/products to browse variants.

        - `recipient` - recipient contact information. Requires firstName,
        lastName, email, and phone (E.164 format).

        - `shippingAddress` - physical shipping address. Requires address1,
        city, provinceCode (2-3 uppercase letters), postalCode, and countryCode
        (ISO 3166-1 alpha-2).

        - `idempotencyKey` - a stable, caller-generated key (1-120 characters).
        Replaying the same request with the same key returns the original order
        without creating a duplicate.


        ###### Optional fields:

        - `accountId` - the Account placing the order. May be supplied here in
        the body or via the Snappy-Account-Id header (header takes precedence
        when both are provided).

        - `tags` - array of strings for grouping orders in reports (e.g.
        ["q4-campaign", "vip"]).

        - `metadata` - key-value object for caller-supplied passthrough data. Up
        to 50 pairs; keys up to 40 chars; values up to 500 chars.

        - `Snappy-Company-Id` header - optional company scoping.


        ###### Behavior Notes:

        - The response is minimal: { id, status, trackingLink }. Use GET
        /v3/orders/{orderId} to retrieve the full Order with line items,
        fulfillments, and tracking detail.

        - `status` is always active immediately after a successful placement.

        - The Billing Method is debited on successful order creation. If it has
        insufficient funds at the time of the request, the order is not
        processed (422).

        - Returns `422` for business-rule violations (insufficient funds,
        variant unavailable in the recipient's country, variant not found,
        etc.).

        - Returns `404` if the referenced `accountId`, `billingMethodId`, or
        `variantId` does not exist or is not accessible to the calling Company.

        - `address2` on the shipping address is optional but recommended
        (apartment, suite, floor, etc.) - incomplete addresses are a leading
        cause of fulfillment failures.


        #### Permissions

        - Requires: `gifts:create` or `orders:create`
      parameters:
        - schema:
            type: string
            description: Account identifier.
            example: acc123456
          required: true
          description: Account identifier.
          name: snappy-account-id
          in: header
        - schema:
            type: string
            description: Optional company identifier.
            example: cmp123456
          required: false
          description: Optional company identifier.
          name: snappy-company-id
          in: header
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlaceOrderV3Body'
      responses:
        '200':
          description: Order placed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaceOrderV3Response'
        '400':
          description: Bad Request - Invalid request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseV3'
        '403':
          description: Forbidden - Account or funding source not allowed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseV3'
        '404':
          description: Not Found - Variant, campaign, or related resource not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseV3'
        '422':
          description: >-
            Unprocessable Entity - Business rule violation (e.g. insufficient
            funds).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseV3'
      security:
        - ApiKeyAuthentication: []
components:
  schemas:
    PlaceOrderV3Body:
      type: object
      properties:
        billingMethodId:
          type: string
          pattern: ^[A-Za-z0-9]{8,}$
          description: >-
            The ID of the billing method that will pay for the order. Must
            belong to the specified account. Contact your Snappy account manager
            to retrieve your billing method IDs.
          example: '87654321'
        variantId:
          type: string
          minLength: 1
          description: >-
            The ID of the specific product variant to order. Use `GET
            /v3/products` to browse available products and retrieve variant IDs.
          example: variant_abc123
        recipient:
          $ref: '#/components/schemas/PlaceOrderV3Recipient'
        shippingAddress:
          $ref: '#/components/schemas/PlaceOrderV3ShippingAddress'
        idempotencyKey:
          type: string
          minLength: 1
          maxLength: 120
          description: >-
            A unique key used to prevent duplicate orders. If a request with the
            same key has already succeeded for this company, the original order
            is returned without creating a duplicate. Use a stable,
            caller-generated identifier such as your internal order ID.
          example: order-2026-05-13-abc
        tags:
          type: array
          items:
            type: string
          description: Optional tags for grouping and filtering orders in reports.
          example:
            - q4-campaign
            - vip
        metadata:
          allOf:
            - $ref: '#/components/schemas/Metadata'
            - description: >-
                Optional custom key-value pairs attached to the order. Use this
                to store additional information such as `externalRecipientId`
                for correlating with your internal systems. Maximum 50 pairs,
                keys up to 40 characters, values up to 500 characters.
              example:
                externalRecipientId: crm-user-987
                campaign: q4-vip
      required:
        - billingMethodId
        - variantId
        - recipient
        - shippingAddress
        - idempotencyKey
      additionalProperties: false
      description: >-
        Request body for placing an order via the Direct Fulfillment
        integration. The account is identified by the `Snappy-Account-Id`
        header.
      example:
        billingMethodId: '87654321'
        variantId: variant_abc123
        recipient:
          firstName: John
          lastName: Doe
          email: john.doe@example.com
          phone: '+12133734253'
        shippingAddress:
          address1: 123 Main St
          address2: Apt 4B
          city: New York
          provinceCode: NY
          postalCode: '10001'
          countryCode: US
        idempotencyKey: order-2026-05-13-abc
        metadata:
          externalRecipientId: crm-user-987
    PlaceOrderV3Response:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/PlaceOrderV3Result'
      required:
        - data
      additionalProperties: false
      description: Successful response returned after an order is placed.
      example:
        data:
          id: G7nR4bD9mK
          status: active
          trackingLink: >-
            https://gift.snappy.com/choose/G7nR4bD9mK?utm_source=l&utm_medium=i&utm_campaign=l2fX39ZvaM
    ErrorResponseV3:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message.
          example: Product not found.
        errorCode:
          type: string
          description: Structured error code.
          example: 404_PROD_001
        errors:
          type: array
          items:
            type: object
            properties:
              message:
                type: string
                example: Product with id 'q1w2e3r4t5' was not found
              path:
                type: string
                description: Dot-separated path to the field that caused the error.
                example: pathParameters.productId
              errorCode:
                type: string
                example: 404_PROD_001
            required:
              - message
              - path
          description: Optional field-level error details.
      required:
        - message
        - errorCode
      description: Standard v3 error envelope.
    PlaceOrderV3Recipient:
      type: object
      properties:
        firstName:
          type: string
          pattern: >-
            ^(?=.{1,50}$)[a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F][a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]*([\s\(\)\.\-_'\u2018\u2019]*[a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F][a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]*)*[
            \(\)\.\-_'\u2018\u2019]*$
          description: Recipient's first name.
          example: John
        lastName:
          type: string
          pattern: >-
            ^(?=.{1,50}$)[a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F][a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]*([\s\(\)\.\-_'\u2018\u2019]*[a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F][a-zA-Z0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\u0400-\u04FF\u0500-\u052F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\uAC00-\uD7AF\u0E00-\u0E7F\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]*)*[
            \(\)\.\-_'\u2018\u2019]*$
          description: Recipient's last name.
          example: Doe
        email:
          type: string
          pattern: >-
            ^(?=.{1,60}$)(?!.*[.]{2})(?!\.)[a-zA-Z0-9._%+\-\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F']+(?<!\.)@(?!-)[a-zA-Z0-9.-\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u01FF\u0100-\u017F\u0180-\u024F]+\.(?!(?:con|cim|ocm|cmo)$)[a-zA-Z]{2,}$/i
          description: Recipient's email address in RFC 5322 format.
          example: john.doe@example.com
        phone:
          type: string
          description: >-
            Recipient's phone number in E.164 format (required for order
            fulfillment).
          example: '+12133734253'
      required:
        - firstName
        - lastName
        - email
        - phone
      additionalProperties: false
      description: Order recipient's contact information.
      example:
        firstName: John
        lastName: Doe
        email: john.doe@example.com
        phone: '+12133734253'
    PlaceOrderV3ShippingAddress:
      type: object
      properties:
        address1:
          type: string
          minLength: 1
          maxLength: 35
          description: >-
            Street address, including house or building number. Maximum 35
            characters.
          example: 123 Main St
        address2:
          type: string
          maxLength: 35
          description: >-
            Apartment, suite, floor, or other secondary address details. Maximum
            35 characters.
          example: Apt 4B
        city:
          type: string
          minLength: 1
          description: City name.
          example: New York
        provinceCode:
          type: string
          pattern: ^[A-Z0-9]{1,3}$
          description: >-
            State or province code. Must be 1-3 uppercase alphanumeric
            characters (e.g., US state codes like NY, CA, or Australian
            territories like NSW).
          example: NY
        postalCode:
          type: string
          pattern: ^[a-zA-Z0-9 -]{3,10}$
          description: Postal code or ZIP code. Alphanumeric, 3-10 characters.
          example: '10001'
        countryCode:
          type: string
          pattern: ^[A-Z]{2}$
          description: Two-letter ISO 3166-1 alpha-2 country code. Must be uppercase.
          example: US
      required:
        - address1
        - city
        - provinceCode
        - postalCode
        - countryCode
      additionalProperties: false
      description: Physical shipping address for order delivery.
      example:
        address1: 123 Main St
        address2: Apt 4B
        city: New York
        provinceCode: NY
        postalCode: '10001'
        countryCode: US
    Metadata:
      type: object
      nullable: true
      additionalProperties:
        type: string
        maxLength: 500
        pattern: ^[a-zA-Z0-9\s\-_.]+$
      maxProperties: 50
      description: >-
        Custom key-value pairs attached at order creation. May include
        `externalRecipientId` for correlating with your internal systems.
        Returns `null` when no metadata was supplied.
      example:
        key1: value1
        key2: value2
    PlaceOrderV3Result:
      type: object
      properties:
        id:
          type: string
          description: >-
            The unique identifier of the placed order. Use this ID to track or
            cancel the order.
          example: G7nR4bD9mK
        status:
          type: string
          enum:
            - active
            - completed
            - cancelled
            - refunded
          description: >-
            The order's current status. `active` for newly placed orders. For
            idempotent replays, returns the actual order status (e.g.,
            `cancelled` if the order was previously cancelled).
          example: active
        trackingLink:
          type: string
          description: >-
            A link to the gift experience for this order. You can share this
            with the recipient to let them track delivery.
          example: >-
            https://gift.snappy.com/choose/G7nR4bD9mK?utm_source=l&utm_medium=i&utm_campaign=l2fX39ZvaM
      required:
        - id
        - status
        - trackingLink
      description: Details of the placed order.
  securitySchemes:
    ApiKeyAuthentication:
      type: apiKey
      in: header
      name: X-Api-Key
      description: |-
        ## Company Level Authentication

        Include your API key in the `X-Api-Key` header for every request:
        ```
        X-Api-Key: YOUR_API_KEY
        ```

````