Overview

Integrating Shipping ModuleAnchorIcon

The PayPal shipping module displays shipping details to buyers during the PayPal checkout flow. Merchants can control how shipping addresses and options are handled through several configuration methods.

Using server-side shipping callbacks, merchants can dynamically update shipping details and order amounts as buyers make changes on the PayPal review page.

When buyers select or update their shipping address and option, PayPal sends a callback to the merchant’s server containing the updated shipping information (such as address, state, city, country code, and postal code). In response, the merchant can return updated shipping options and revised order totals to PayPal.

To include Shipping Module in your integration, set the server side shipping callback URL as shown below. For more information, see the Integration code samples section, below.

  1. javascript
// Add shippingCallbackUrl createPayment() request options
createPaymentRequestOptions.shippingCallbackUrl = "https://www.example.com/"

EligibilityAnchorIcon

  • Supports One-time payments only
  • Works with the Pay Now flow

Callback Request to MerchantAnchorIcon

When a shipping address or shipping option event occurs, PayPal sends a callback request to the configured shipping CallbackUrl. The callback includes information about the order, shipping address, shipping options, and the number of purchase units.

To include the Shipping Module in your integration, set the server-side shipping callback URL as:

  1. javascript
// Add shippingCallbackUrl createPayment() request options
createPaymentRequestOptions.shippingCallbackUrl = "https://www.example.com/"

Callback EventsAnchorIcon

The shipping module supports the following callback events:

  • onShippingAddressChange: This event occurs when the review page loads for the first time and when the buyer changes their shipping address. We recommend subscribing only to onShippingAddressChange, as this requires you to respond with all shipping options and amounts calculated on the initial callback, reducing delays and the number of requests.
  • onShippingOptionsChange: This event occurs when the buyer selects new shipping options. Subscribe to this if you want to be notified or need to recalculate amounts when a selected shipping option changes for the current address.
onShippingAddressChangeAnchorIcon
  1. javascript
Updates an order to add shipping address to purchase unit (or) replace the shipping address
//Request
curl -v -X PATCH 'https://api-m.sandbox.paypal.com/v2/checkout/orders/:order_id'
-H "Content-Type: application/json" 
-H "Authorization: Bearer ACCESS_TOKEN" 
-d '[
    {
        "op": "replace",
        "path": "/purchase_units/@reference_id=='PUHF'/shipping/address",
        "value": {
            "address_line_1": "2211 N First Street",
            "address_line_2": "Building 17",
            "admin_area_2": "San Jose",
            "admin_area_1": "CA",
            "postal_code": "95131",
            "country_code": "US"
        }
    }
]'

While the buyer is on the PayPal site, you can update their shopping cart to reflect the shipping address they selected on PayPal. This callback is triggered any time the user selects a new shipping option. You can use the callback to:

  • Validate that you support the shipping method.
  • Update shipping costs.
  • Change the line items in the cart.
  • Inform the buyer that you don't support their shipping method.
onShippingOptionsChangeAnchorIcon
  1. javascript
Updates an order to add shipping options to purchase unit.
//Request
curl -v -X PATCH 'https://api-m.sandbox.paypal.com/v2/checkout/orders/:order_id'
 -H 'Authorization: Bearer ACCESS_TOKEN
 -H 'Content-Type: application/json'
 -d '[
    {
        "op": "add",
        "path": "/purchase_units/@reference_id=='PUHF'/shipping/options",
        "value": [
            {
                "id": "STORE0002012345202",
                "label": "Ground Shipping",
                "type": "SHIPPING",
                "amount": {
                    "currency_code": "USD",
                    "value": "10.00"
                },
                "selected": true
            }
        ]
    }
]'

Triggered anytime the user selects a new shipping option:

  • Validate that you support the shipping address.
  • Update shipping costs.
  • Change the line items in the cart.
  • Inform the buyer that you don't support their shipping address.

Enabling server-side callbacksAnchorIcon

The createPayment({ shippingCallbackUrl: "https://example.com/callback" }) object is used to enable and configure server-side callbacks during the flow. The shippingCallbackUrl field specifies the endpoint on your servers where the callback request is sent. The callback_events array specifies which callback events you support. The flow supports the following events:

  1. javascript
callbackEvents: ["SHIPPING_ADDRESS"];

Or if you want to support both events:

  1. javascript
callbackEvents: ["SHIPPING_ADDRESS", "SHIPPING_OPTIONS"];

Callback Request FieldsAnchorIcon

FieldDescriptionData Type
orderIdUnique identifier for the shipping order. For example, 5O190127TN364715Tstring
shipping_addressShipping address informationobject
shipping_address.country_codeIdentifies the shipping address country. For example, USstring
shipping_address.admin_area_1Identifies the shipping address state or region. For example, CAstring
shipping_address.admin_area_2Identifies the shipping address city or municipality. For example, San Josestring
shipping_address.postal_codeIdentifies the postal code. For example, 95131string
shipping_optionShipping option information (not included in initial callback)object
shipping_option.selectedDetermines which option is selected by default. Possible values are true or falseboolean
shipping_option.idShipping option identifier. For example, SHIP_123string
shipping_option.typeIndicates the type of shipping option. For example, SHIPPINGstring
shipping_option.amountShipping option amount informationobject
shipping_option.amount.currency_codeIndicates the type of currency. For example, USDstring
shipping_option.amount.valueString denoting the purchase price and shipping option price, formatted as decimalstring
shipping_option.descriptionDropdown menu option selected by the buyer. For example, Standard Shippingstring
purchase_unitsDefines the purchase unitsarray
purchase_units[].reference_idIdentifier associated with the purchase units. For example, PUHFstring

Merchant Response to CallbackAnchorIcon

Your server must respond to the callback with updated shipping options and order amounts. The response structure is similar to an order object.

Merchant Success ResponseAnchorIcon

When the callback request is acceptable, respond with an HTTP 200 OK status and include shipping options and amount updates:

  1. javascript
{
  "merchant_id": "2V7XXXX2CXX15924N",
  "purchase_units": [
    {
      "reference_id": "PUHF",
      "amount": {
        "currency_code": "USD",
        "value": "230.00",
        "breakdown": {
          "item_total": {
            "value": "180.00",
            "currency_code": "USD"
          },
          "tax_total": {
            "value": "20.00",
            "currency_code": "USD"
          },
          "shipping": {
            "value": "30.00",
            "currency_code": "USD"
          }
        }
      },
      "shipping": {
        "options": [
          {
            "selected": true,
            "id": "SHIP_123",
            "amount": {
              "value": "30.00",
              "currency_code": "USD"
            },
            "type": "SHIPPING",
            "label": "Express Shipping"
          },
          {
            "selected": false,
            "id": "SHIP_456", 
            "amount": {
              "value": "15.00",
              "currency_code": "USD"
            },
            "type": "SHIPPING",
            "label": "Standard Shipping"
          }
        ]
      }
    }
  ]
}

Merchant Success Response FieldsAnchorIcon

FieldDescriptionData Type
merchant_idIdentifies the merchant. For example, 2V7XXXX2CXX15924Nstring
purchase_unitsPurchase unit informationarray
purchase_units[].reference_idUniquely identifies the purchase transaction. For example, PUHFstring
purchase_units[].amountPurchase unit amount in the orderobject
purchase_units[].amount.currency_codeCode indicating the amount currency type. For example, USDstring
purchase_units[].amount.valueString denoting the purchase unit amount in the order, formatted as decimalstring
purchase_units[].amount.breakdownAmount breakdownobject
purchase_units[].amount.breakdown.item_totalAmount item breakdownobject
purchase_units[].amount.breakdown.item_total.valueAmount item value. For example, 180.00string
purchase_units[].amount.breakdown.tax_totalAmount tax breakdownobject
purchase_units[].amount.breakdown.tax_total.valueString denoting the tax amount, formatted as decimalstring
purchase_units[].amount.breakdown.shippingAmount shipping breakdownobject
purchase_units[].amount.breakdown.shipping.valueString denoting the shipping amount, formatted as decimalstring
purchase_units[].shipping.optionsShipping option informationarray
purchase_units[].shipping.options[].selectedDetermines which options are selected by default. Possible values are true or falseboolean
purchase_units[].shipping.options[].idShipping option identifier. For example, SHIP_123string
purchase_units[].shipping.options[].amountAmount for the selected shipping optionobject
purchase_units[].shipping.options[].amount.valueString denoting the amount for the selected shipping option, formatted as decimalstring
purchase_units[].shipping.options[].typeAn enum that indicates the type of delivery for the selected option. For example, SHIPPINGstring
purchase_units[].shipping.options[].labelDropdown menu option selected by the buyer. Indicates the type of shipping methodstring

Merchant Decline ResponseAnchorIcon

Your merchant server can issue an HTTP 422 Unprocessable Entity error to decline a callback event. In the response, provide a reason why the callback is being declined. The following error reasons are supported:

Callback Event TypeErrorDescription
Shipping addressSHIPPING_ADDRESS_INVALIDYour order can't be shipped to this address.
Shipping addressSHIPPING_COUNTRY_UNSUPPORTEDYour order can't be shipped to this country.
Shipping addressSHIPPING_STATE_UNSUPPORTEDYour order can't be shipped to this state.
Shipping addressSHIPPING_ZIP_UNSUPPORTEDYour order can't be shipped to this zip.
Shipping optionSHIPPING_OPTION_NOT_AVAILABLEThe shipping method you selected is unavailable. To continue, choose another way to get your order.
Shipping optionPICKUP_NOT_AVAILABLEPart of your order isn't available at this store.
Sample decline callback response:AnchorIcon
  1. javascript
"name": "UNPROCESSABLE_ENTITY", "details": [ { "issue": "SHIPPING_COUNTRY_UNSUPPORTED", "description": "The shipping country is not supported" } ], "message": "The requested action could not be performed, semantically incorrect, or failed business validation.", "debug_id": "9e450c2dac87c", "links": [ { "href": "https://developer.paypal.com/docs/api/orders/v2/#error-SHIPPING_COUNTRY_UNSUPPORTED", "rel": "information_link", "method": "GET" } ]

Integration notesAnchorIcon

  • If you are subscribed to shipping_options, ensure the callback response includes the updated total cost so that the checkout page can be updated.
  • Merchants with client-side shopping carts should include item details when they create the order for server-side shipping callbacks.
  • The cart identifier will be embedded in the callback URL if merchants cannot associate their shopping cart with the order.

Domain registrationAnchorIcon

In order to use server-side shipping callbacks with PayPal, you'll need to register any domains you plan to use as the shippingCallbackUrl. You can do this through the Braintree control panel using the instructions below. You will have to do this in both your sandbox and production environments.

Rules for domain namesAnchorIcon

A domain name:

  • Must not start with a scheme (e.g. "https://").

  • Must be between 4 and 255 characters.

  • Cannot contain spaces or wildcards (*).

  • Can consist of a top-level domain, a second-level domain, and 0 or more subdomains etc. a.b.example.com where example is the top-level domain, com is the second-level domain, and a and b are subdomains.

  • The top-level domain must consist of 2 to 63 letters.

  • Each subdomain and the second-level domain must consist of 1 to 63 alphanumeric characters and or hyphens.

  • Each subdomain and the second-level domain can not start or end with a hyphen.

  • The top-level domain, second-level domain, and the subdomains must be separated by a dot(.).

  • Can end with a trailing dot.

Sandbox environmentAnchorIcon

Register your sandbox domain name in the Braintree Control Panel:

  1. Log into your sandbox Control Panel

  2. Click on the gear icon in the top right corner

  3. Click Account Settings from the drop-down menu

  4. Scroll to the Payment Methods section

  5. Next to PayPal, click the Options link

  6. Client the View Domain Names button

  7. Enter the domain of your return page in the Specify Your Domain Names section.

  8. Click Add Domain Names button

Production environmentAnchorIcon

Register your production domain name in the Braintree Control Panel:

  1. Log into your production Control Panel

  2. Click on the gear icon in the top right corner

  3. Click Account Settings from the drop-down menu

  4. Scroll to the Payment Methods section

  5. Next to PayPal, click the Options link

  6. Client the View Domain Names button

  7. Enter the domain of your return page in the Specify Your Domain Names section.

  8. Click Add Domain Names button

Best practicesAnchorIcon

  • Use SHIPPING_ADDRESS callbacks only when possible to reduce the number of callback requests and improve performance.
  • Validate shipping addresses in your callback handler and return appropriate error responses for unsupported locations.
  • Calculate accurate shipping costs based on the provided address and return all available shipping options in your response.
  • Handle callback timeouts gracefully and ensure your callback endpoint responds quickly to avoid payment flow interruptions.