Skip to main content
To extend your API beyond basic product sales, you can enable specialized shopping experiences. This guide shows you how to:
  • Handle gift cards with recipient information and delivery scheduling.
  • Use geographic coordinates for location-aware services, such as local-inventory checking and delivery-radius validation.
  • Support multi-item carts with create, update, and per-item error handling.
Note: You can view the complete protocol reference for the Cart API and the Complete Checkout API.

Gift cards

Create a cart containing a gift card with recipient details and scheduled delivery.
POST /api/paypal/v1/merchant-cart
Content-Type: application/json
Authorization: Bearer <paypal-jwt-token>

{
  "items": [
    {
      "variant_id": "GIFTCARD-100",
      "quantity": 1,
      "gift_options": {
        "is_gift": true,
        "recipient": {
          "name": "Mary Johnson",
          "email": "mary@example.com"
        },
        "delivery_date": "2024-12-25T09:00:00Z",
        "sender_name": "John Smith",
        "gift_message": "Merry Christmas! Enjoy your shopping."
      }
    }
  ],
  "payment_method": {
    "type": "paypal"
  }
}

Geographic coordinates

Some merchants offer location-based services that require precise geographic positioning beyond standard postal addresses. The Cart API supports optional latitude/longitude coordinates to enable features like local inventory checking, distance-based pricing, delivery radius validation, and enhanced shipping calculations. This geographic data operates independently from shipping addresses, allowing you to provide location-aware commerce experiences while maintaining clean separation between postal and coordinate data.

Latitude and longitude support strategy

Geographic coordinates are optional. This feature is for merchants who can provide enhanced location services. Geographic coordinates are provided in a separate geo_coordinates field, distinct from the shipping_address object. This clean separation allows:
  • Postal addresses to remain focused on standard shipping data
  • Geographic coordinates to provide precise location enhancement
  • Independent handling of address and coordinate data
  • Graceful degradation when coordinates aren’t supported
Here’s how to structure address and coordinate data separately:
{
  "shipping_address": {
    "address_line_1": "123 Main Street",
    "admin_area_2": "San Jose",
    "admin_area_1": "CA",
    "postal_code": "95131",
    "country_code": "US"
  },
  "geo_coordinates": {
    "latitude": "37.3349",
    "longitude": "-122.0090",
    "subdivision": "CA",
    "country_code": "US"
  }
}

Geographic fields

The geo_coordinates object contains precise location data that enhances address information for location-aware services.
FieldDescriptionExample
latitude and longitudePrecise WGS84 coordinates in decimal degreeslatitude: "37.3349", longitude: "-122.0090"
subdivisionAdministrative division (state, province, region) using ISO 3166-2 formatsubdivision: "CA" (California)
country_codeISO 3166-1 alpha-2 country code for the coordinate locationcountry_code: "US"

Multi-item carts

The Cart API supports carts with multiple items. You can create a cart with several products in a single request, update the cart by replacing the full items list, and receive per-item error reporting when issues occur.

Create a cart with multiple items

Include multiple items in the items array, each with its own variant_id, quantity, and pricing.
{
  "items": [
    {
      "variant_id": "SHIRT-BLUE-M",
      "quantity": 2,
      "name": "Blue T-Shirt",
      "description": "Cotton crew neck, Size M",
      "price": { "currency_code": "USD", "value": "29.99" }
    },
    {
      "variant_id": "JEANS-SLIM-32",
      "quantity": 1,
      "name": "Slim Fit Jeans",
      "description": "Classic slim fit, Size 32",
      "price": { "currency_code": "USD", "value": "79.99" }
    },
    {
      "variant_id": "SNEAKERS-WHITE-10",
      "quantity": 1,
      "name": "White Sneakers",
      "description": "Classic white, Size 10",
      "price": { "currency_code": "USD", "value": "89.99" }
    }
  ],
  "totals": {
    "subtotal": { "currency_code": "USD", "value": "229.96" },
    "shipping": { "currency_code": "USD", "value": "9.99" },
    "tax": { "currency_code": "USD", "value": "20.70" },
    "total": { "currency_code": "USD", "value": "260.65" }
  }
}

Update cart items

To update a cart, send the complete items list in the request. The merchant compares this list to the existing cart and applies the differences. A single update can add new items, remove existing items, and change quantities.
{
  "items": [
    {
      "variant_id": "SHIRT-BLUE-M",
      "quantity": 3,
      "name": "Blue T-Shirt",
      "description": "Cotton crew neck, Size M",
      "price": { "currency_code": "USD", "value": "29.99" }
    },
    {
      "variant_id": "SNEAKERS-WHITE-10",
      "quantity": 1,
      "name": "White Sneakers",
      "description": "Classic white, Size 10",
      "price": { "currency_code": "USD", "value": "89.99" }
    },
    {
      "variant_id": "HAT-BLACK-OS",
      "quantity": 1,
      "name": "Black Cap",
      "description": "One Size",
      "price": { "currency_code": "USD", "value": "24.99" }
    }
  ]
}
In this example, compared to the original cart: SHIRT-BLUE-M quantity increased from 2 to 3, JEANS-SLIM-32 was removed, and HAT-BLACK-OS was added.

Error handling for multiple items

Return a separate validation issue for each item that fails, and include the variant_id so the AI agent can identify the affected item. Errors can be reported in two ways:
  • 200/201 with INCOMPLETE status — the cart was created or updated, but some items have issues. Report them in the validation_issues array.
  • 422 Unprocessable Entity — the cart could not be created or the update could not be applied. Report per-item errors in details[].business_context.
The following example shows an INCOMPLETE response where 2 out of 3 items have inventory issues:
{
  "id": "CART-MULTI-001",
  "status": "INCOMPLETE",
  "validation_status": "INVALID",
  "items": [
    {
      "variant_id": "SHIRT-BLUE-M",
      "quantity": 2,
      "name": "Blue T-Shirt",
      "price": { "currency_code": "USD", "value": "29.99" }
    },
    {
      "variant_id": "JEANS-SLIM-32",
      "quantity": 2,
      "name": "Slim Fit Jeans",
      "price": { "currency_code": "USD", "value": "79.99" }
    },
    {
      "variant_id": "SNEAKERS-WHITE-10",
      "quantity": 1,
      "name": "White Sneakers",
      "price": { "currency_code": "USD", "value": "89.99" }
    }
  ],
  "validation_issues": [
    {
      "code": "INVENTORY_ISSUE",
      "type": "BUSINESS_RULE",
      "message": "Product is currently out of stock",
      "user_message": "Blue T-Shirt (Size M) is out of stock. Would you like a different color?",
      "variant_id": "SHIRT-BLUE-M",
      "context": {
        "specific_issue": "ITEM_OUT_OF_STOCK",
        "available_quantity": 0,
        "requested_quantity": 2
      },
      "resolution_options": [
        { "action": "REMOVE_ITEM", "label": "Remove from cart" },
        { "action": "SUGGEST_ALTERNATIVE", "label": "View other colors" }
      ]
    },
    {
      "code": "INVENTORY_ISSUE",
      "type": "INVALID_DATA",
      "message": "Requested quantity exceeds available stock",
      "user_message": "Only 1 unit of Slim Fit Jeans is available. You requested 2.",
      "variant_id": "JEANS-SLIM-32",
      "context": {
        "specific_issue": "INSUFFICIENT_INVENTORY",
        "available_quantity": 1,
        "requested_quantity": 2
      },
      "resolution_options": [
        { "action": "MODIFY_CART", "label": "Update to available quantity" }
      ]
    }
  ],
  "totals": {
    "subtotal": { "currency_code": "USD", "value": "89.99" },
    "shipping": { "currency_code": "USD", "value": "9.99" },
    "total": { "currency_code": "USD", "value": "99.98" }
  }
}