Skip to main content

PayPal REST API requests

PayPal REST APIs authenticate with OAuth 2.0 access tokens, and return HTTP response codes with JSON-encoded responses.

Base URLs

All PayPal REST API requests target one of two base URLs:

  • Sandbox for testing: https://api-m.sandbox.paypal.com
  • Live for production: https://api-m.paypal.com

Important HTTP headers

The following is a list of all PayPal-specific HTTP request headers.

PayPal-Auth-Assertion

Optional. For platforms and marketplaces only.

For platforms, marketplaces, and service providers that process payments for multiple merchants. For example, Square, eBay, Shopify, or payment processors. Individual merchants running their own websites do not need this header.

Purpose

Generating and storing separate access tokens for each merchant becomes complex and costly. Use the PayPal-Auth-Assertion JSON Web Token (JWT) header to identify which merchant each API call is for. You only need one set of platform credentials for all merchants.

This header requires explicit consent from each merchant you represent.

Build the JWT assertion

PayPal recommends using the unsigned JWT. The information passed with the JWT is not sensitive data.

Build the JWT with 3 parts:

  • Header: For an unsigned JWT, set algorithm to "alg": "none".
  • Payload: Include the following fields:
    • iss: The platform's client_id (issuer).
    • payer_id: The specific merchant's PayPal payer ID.
  • Signature: Use an empty string "" for unsigned JWTs. If you prefer a signed JWT for security reasons, you can sign it with your secret from your API credentials.

Base64 encode each part separately, then concatenate with periods:

[encoded_header].[encoded_payload].[encoded_signature]

Example HTTP header:

PayPal-Auth-Assertion: eyJhbGciOiJub25lIn0.eyJpc3MiOiJZT1VSX1BMQVRGT1JNX0NMSUVOVF9JRCIsInBheWVyX2lkIjoiTUVSQ0hBTlRfUEFZRVJfSUQifQ.

Include the resulting JWT string in the PayPal-Auth-Assertion header when making API calls on behalf of that merchant.

{
"iss": "your_platform_client_id",
"payer_id": "merchant_payer_id_here"
}

PayPal-Partner-Attribution-ID

Required. For platforms and marketplaces only.

This header does two things:

  • Identifies your platform as a PayPal partner
  • Enables revenue attribution tracking

The header value is your unique Build Notation (BN) code. PayPal uses the BN code to track all transactions associated with your platform.

Take the following steps to find your BN code:

  1. From your developer dashboard, select Apps & Credentials.
  2. Select the app you're using.
  3. Under App Settings, scroll to Reports.
  4. Your BN code appears on the last line of the Reports section.

PayPal-Mock-Response

Optional.

Simulate an error. Pass an error code to test through the mock_application_codes header parameter. For example, "mock_application_codes": "DUPLICATE_INVOICE_ID". For more information, see:

PayPal-Request-Id

Optional but recommended for all POST and PUT calls.

The PayPal-Request-Id contains a unique user-generated ID that prevents duplicate transactions. PayPal recommends to include it in any API call that creates or modifies data.

The PayPal-Request-Id is how PayPal enforces idempotency in REST API calls. Idempotency means you can retry the call multiple times without duplicating actions. For example, if a user presses a Buy Now button multiple times, they aren't charged for each button press.

Network timeouts, HTTP 500 errors, and other failures can leave you uncertain whether your API call succeeded. With this header, you can retry failed calls knowing that PayPal won't process the same action for as long as the server stores the ID.

PayPal stores your unique ID for up to 45 days. If you retry a call with the same PayPal-Request-Id, PayPal recognizes it as a duplicate and returns the result of the original call.

Common authentication errors

When using PayPal HTTP headers, you might encounter these issues:

  • 401 Unauthorized: Check that your platform credentials are valid and that you have permission to act on behalf of the merchant.
  • 400 Bad Request: Verify the JWT format is correct and all required fields are present.
  • 403 Forbidden: Ensure the merchant has granted your platform appropriate permissions.

For detailed error troubleshooting, check the response body. Find an error code, message, and debug ID to reference when contacting PayPal support.

Query PayPal REST APIs

When making a REST API request to PayPal, append query parameters to the endpoint URL using the following format:

https://api-m.sandbox.paypal.com/{resource}?parameter1=value1&parameter2=value2
  • Separate each query parameter with an ampersand &.
  • Introduce the first query parameter with a question mark ?.
  • URL-encode parameter names and values if they contain special characters.

Example: list invoices

This example returns details for four invoices, starting from the third invoice, and includes the total invoice count.

curl -v -X GET https://api-m.sandbox.paypal.com/v1/invoicing/invoices?page=3&page_size=4&total_count_required=true\
-H "Content-Type: application/json" \
-H "Authorization: Bearer ACCESS-TOKEN"
  • page=3 requests the third page of results.
  • page_size=4 limits the response to 4 items per page.
  • total_count_required=true asks PayPal to include the total count of items in the response.

Query parameters

Note: Not all pagination parameters are available for all APIs.

ParameterTypeDescription
countintegerThe number of items to list in the response.
end_timeintegerThe end date and time for the range to show in the response, in Internet date and time format. For example, end_time=2025-03-07T11:00:00Z.
pageintegerThe page number indicating which set of items will be returned in the response. For example, the combination of page=1 and page_size=20 returns the first 20 items. The combination of page=2 and page_size=20 returns items 21 through 40.
page_sizeintegerThe number of items to return in the response.
total_count_requiredbooleanIndicates whether to show the total count in the response.
sort_bystringSorts the payments in the response by a specified value, such as the create time or update time.
sort_orderstringSorts the items in the response in ascending or descending order.
start_idstringThe ID of the starting resource in the response. When results are paged, you can use the next_id value as the start_id to continue with the next set of results.
start_indexintegerThe start_index parameter lets you specify the position in the list where results should begin. For example, setting start_index=2 skips the first item and shows results from the second item onward.
start_timestringThe start date and time for the range to show in the response, in Internet date and time format. For example, start_time=2025-03-06T11:00:00Z.

Example request: create invoice

PayPal's REST APIs support standard HTTP methods - GET, POST, PUT, PATCH, DELETE.

Important: Include a PayPal-Request-Id header in all POST and PUT requests to prevent duplicate actions.

The following request creates an invoice:

  • From sender David Larusso, including address, email address, and phone number.
  • To recipient Stephanie Meyers, including address, email address, and phone number.
  • For one $50 yoga mat including sales tax.
  • For one $10 t-shirt including sales tax.
  • With $20 minimum partial payments enabled.
  • With an optional tip.
  • With $10 packing charges and $10 shipping charges, including sales tax.
  • With a 5% invoice discount.
curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/invoicing/invoices' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ACCESS-TOKEN' \
-d '{
"detail": {
"invoice_number": "123",
"reference": "deal-ref",
"invoice_date": "2028-11-22",
"currency_code": "USD",
"note": "Thank you for your business.",
"term": "No refunds after 30 days.",
"memo": "This is a long contract",
"payment_term": {
"term_type": "NET_10",
"due_date": "2028-11-22"
}
},
"invoicer": {
"name": {
"given_name": "David",
"surname": "Larusso"
},
"address": {
"address_line_1": "1234 First Street",
"address_line_2": "337673 Hillside Court",
"admin_area_2": "Anytown",
"admin_area_1": "CA",
"postal_code": "98765",
"country_code": "US"
},
"email_address": "[email protected]",
"phones": [
{
"country_code": "001",
"national_number": "4085551234",
"phone_type": "MOBILE"
}
],
"website": "www.test.com",
"tax_id": "ABcNkWSfb5ICTt73nD3QON1fnnpgNKBy-Jb5SeuGj185MNNw6g",
"logo_url": "https://example.com/logo.PNG",
"additional_notes": "2-4"
},
"primary_recipients": [
{
"billing_info": {
"name": {
"given_name": "Stephanie",
"surname": "Meyers"
},
"address": {
"address_line_1": "1234 Main Street",
"admin_area_2": "Anytown",
"admin_area_1": "CA",
"postal_code": "98765",
"country_code": "US"
},
"email_address": "[email protected]",
"phones": [
{
"country_code": "001",
"national_number": "4884551234",
"phone_type": "HOME"
}
]
},
"shipping_info": {
"name": {
"given_name": "Earl",
"surname": "Gray"
},
"address": {
"address_line_1": "1234 Main Street",
"admin_area_2": "Anytown",
"admin_area_1": "CA",
"postal_code": "98765",
"country_code": "US"
}
}
}
],
"items": [
{
"name": "Yoga mat",
"description": "Elastic mat to practice yoga.",
"quantity": "1",
"unit_amount": {
"currency_code": "USD",
"value": "50.00"
},
"tax": {
"name": "Sales Tax",
"percent": "7.25"
},
"discount": {
"percent": "5"
},
"unit_of_measure": "QUANTITY"
},
{
"name": "Yoga t-shirt",
"quantity": "1",
"unit_amount": {
"currency_code": "USD",
"value": "10.00"
},
"tax": {
"name": "Sales Tax",
"percent": "7.25"
},
"unit_of_measure": "QUANTITY"
}
]
}'