PayPal Commerce Platform gateway guide

Quick Start

New to integrating PayPal Commerce Platform with Spreedly? Here's your setup guide:

  1. Retrieve your PayPal Commerce Platform credentials
    1. Log in to the PayPal Dashboard.
    2. Navigate to My Apps & Credentials.
    3. Select the application you want to enable with Spreedly.
    4. Copy the Client ID and Secret.
      1. You will use the Client ID as login and the Secret as password when creating the gateway.
  2. Get familiar with the Spreedly API
    1. Review Spreedly API basics
    2. Understand the core concepts: Gateways, Payment Methods, and Transactions
  3. Add PayPal Commerce Platform gateway to Spreedly in sandbox mode
ℹ️

OAuth 2.0 authentication: PayPal Commerce Platform requests authenticate to PayPal using OAuth 2.0 access tokens instead of Basic auth. Spreedly generates the access token from the existing REST Client ID and Secret credentials via PayPal’s /v1/oauth2/token endpoint, so merchants do not need to create new credentials or complete additional setup.

The OAuth 2.0 access token is used for PayPal Commerce Platform API requests, including PayPal Wallet and Venmo wallet payment methods. This behaviour is supported by PayPal for both wallets. Reference: PayPal REST authentication documentation.

ℹ️

Review this documentation to understand more about how to test transactions.

Additional notes

The Spreedly integration to the PayPal Commerce Platform supports two primary transaction paths:

Spreedly offsite payment flow, where a customer uses a payment method stored at PayPal

Direct credit card transactions using a payment method stored in Spreedly's vault

In both cases, work with your PayPal account manager to verify your account is configured correctly. This may include enabling support for raw card payment data.

If you want a customer's billing address returned in gateway responses, PayPal must enable that feature. Without it, certain gateway-specific response fields cannot be populated.

📘

Google Pay support is limited to CRYPTOGRAM_3DS. PAN_ONLY is not supported, and PayPal Commerce Platform does not support Global 3DS for this flow.

Adding a PayPal Commerce Platform Gateway

Required credentials

login: PayPal Client ID

password: PayPal Secret

Request

curl https://core.spreedly.com/v1/gateways.xml \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/xml' \
-d '<gateway>
  <gateway_type>paypal_commerce_platform</gateway_type>
  <login>client id</login>
  <password>secret</password>
</gateway>'

Response

<gateway>
  <token>YovvB1bIN56lvJedMbTBiqGgXYZ</token>
  <gateway_type>paypal_commerce_platform</gateway_type>
  <name>PayPal Commerce Platform</name>
  <login>client id</login>
  <characteristics>
    <supports_purchase type="boolean">true</supports_purchase>
    <supports_authorize type="boolean">true</supports_authorize>
    <supports_capture type="boolean">true</supports_capture>
    <supports_partial_capture type="boolean">true</supports_partial_capture>
    <supports_credit type="boolean">true</supports_credit>
    <supports_partial_credit type="boolean">true</supports_partial_credit>
    <supports_general_credit type="boolean">true</supports_general_credit>
    <supports_void type="boolean">true</supports_void>
    <supports_verify type="boolean">true</supports_verify>
    <supports_store type="boolean">true</supports_store>
    <supports_remove type="boolean">true</supports_remove>
    <supports_offsite_purchase type="boolean">true</supports_offsite_purchase>
    <supports_offsite_authorize type="boolean">true</supports_offsite_authorize>
    <supports_inquire_by_gateway_transaction_id type="boolean">true</supports_inquire_by_gateway_transaction_id>
    <supports_inquire_by_order_id type="boolean">true</supports_inquire_by_order_id>
    <supports_stored_credentials type="boolean">true</supports_stored_credentials>
    <supports_transaction_retry type="boolean">true</supports_transaction_retry>
  </characteristics>
  <payment_methods>
    <payment_method>credit_card</payment_method>
    <payment_method>google_pay</payment_method>
    <payment_method>paypal</payment_method>
    <payment_method>third_party_token</payment_method>
  </payment_methods>
  <state>retained</state>
</gateway>

Add your Client ID to login and your Secret to password. Use your sandbox credentials when creating a test gateway.

Purchase

Request

curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "payment_method_token",
    "amount": 100,
    "currency_code": "USD"
  }
}'

Authorize

Request

curl https://core.spreedly.com/v1/gateways/[gateway_token]/authorize.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "payment_method_token",
    "amount": 500,
    "currency_code": "USD"
  }
}'

Capture

Request

curl https://core.spreedly.com/v1/transactions/[authorization_token]/capture.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "amount": 500,
    "currency_code": "USD"
  }
}'

Void

Request

curl https://core.spreedly.com/v1/transactions/[authorization_token]/void.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{}'

Credit (Refund)

Request

curl https://core.spreedly.com/v1/transactions/[purchase_or_capture_token]/credit.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "amount": 100,
    "currency_code": "USD"
  }
}'

Google Pay

PayPal Commerce Platform supports Google Pay for Purchase and Authorize when the payment method uses CRYPTOGRAM_3DS. PAN_ONLY is not supported. Because this gateway does not support Global 3DS, PAN-only Google Pay cannot be used here. Stored credentials are not supported with Google Pay payment methods.

Request

curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "google_pay_cryptogram_payment_method_token",
    "amount": 100,
    "currency_code": "USD",
    "billing_address": {
      "address1": "123 Main Street",
      "city": "San Jose",
      "state": "CA",
      "zip": "95131",
      "country": "US"
    }
  }
}'

Apple Pay

PayPal Commerce Platform supports Apple Pay for Purchase and Authorize. Stored credentials are supported with Apple Pay payment methods.

Request

curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "apple_pay_payment_method_token",
    "amount": 100,
    "currency_code": "USD",
    "billing_address": {
      "address1": "123 Main Street",
      "city": "San Jose",
      "state": "CA",
      "zip": "95131",
      "country": "US"
    }
  }
}'

Network Token

PayPal Commerce Platform supports network tokens for Purchase and Authorize when the payment method has a provisioned network token and the request includes attempt_network_token. Store is not supported with network token payment methods.

Request

curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "payment_method_token",
    "amount": 100,
    "currency_code": "USD",
    "attempt_network_token": true
  }
}'

Store / Remove

Third-party vaulting

The PayPal Commerce Platform gateway supports storing a payment method directly with PayPal using PayPal's Vault API. Once stored, you can reuse the resulting PayPal vault token for future transactions without resending the original card number.

Storing a payment method

To create a PayPal vault token, call store on a retained payment method through the PPCP gateway:

curl https://core.spreedly.com/v1/gateways/{gateway_token}/store.json \
  -u 'your_environment_key:your_access_secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "transaction": {
      "payment_method_token": "{payment_method_token}"
    }
  }'

A successful store request returns a new Spreedly payment method with payment_method_type of third_party_token, associated with the PPCP gateway. Use transaction.payment_method.token from the store response as the payment method token for later purchase, authorize, and redact calls. This token represents the card stored in PayPal's vault.

Using a stored third-party token

Reference the third_party_token payment method (transaction.payment_method.token from store) in place of the original payment method on any supported transaction

curl https://core.spreedly.com/v1/gateways/{gateway_token}/purchase.json \
  -u 'your_environment_key:your_access_secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "transaction": {
      "amount": 1000,
      "currency_code": "USD",
      "payment_method_token": "{third_party_token}"
    }
  }'

Spreedly sends the PayPal vault token to PayPal's Orders v2 API as payment_source.card.vault_id.

Removing a stored payment method

To delete the corresponding PayPal vault token, redact the third_party_token payment method and include remove_from_gateway

curl https://core.spreedly.com/v1/payment_methods/{third_party_token}/redact.json \
  -u 'your_environment_key:your_access_secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "transaction": {
      "remove_from_gateway": "{gateway_token}"
    }
  }'

Inquire / Sync

PayPal Commerce Platform is only partly async. Sync/Inquire is mainly useful for unvaulted PayPal and Venmo offsite transactions, and for General Credit payouts that are still pending or processing.

Card, Google Pay, Apple Pay, capture, refund, and void usually complete on the first Spreedly response, so they should not be expected to support Sync/Inquire. Void has no pending state.

Webhooks

PayPal Orders v2 does not use per-order IPN or notify_url. PPCP completion is handled through redirect plus API calls. Spreedly does not currently process PPCP REST webhooks.

What Sync/Inquire supports

  • Supported: offsite PayPal or Venmo purchase/authorize when Spreedly has the PayPal order ID.
  • Supported: General Credit payouts when Spreedly has the payout batch ID.
  • Not supported: card, Google Pay, Apple Pay purchase/authorize, Capture, and Void.

Pending and error behaviour

If the buyer approval or payout is still pending, Inquire returns pending: true and the transaction moves from pending to processing.

If PayPal returns RESOURCE_NOT_FOUND, or if Sync/Inquire is used for an unsupported transaction, the transaction can currently fail instead of staying unchanged.

Use Sync/Inquire only for supported offsite PayPal/Venmo flows and General Credit payouts. For most other PPCP transactions, the first Spreedly response is the final result.

Partial Capture

Use gateway-specific field final_capture to control whether more captures are expected.

Set false when additional captures will follow

Use true, or omit the field, on the final capture

Authorizations expire, and a single capture cannot exceed 115% of the original authorized amount.

Request: partial capture

curl https://core.spreedly.com/v1/transactions/[authorization_token]/capture.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "amount": 300,
    "currency_code": "USD",
    "gateway_specific_fields": {
      "paypal_commerce_platform": {
        "final_capture": false
      }
    }
  }
}'

Request: final capture

curl https://core.spreedly.com/v1/transactions/[authorization_token]/capture.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "amount": 200,
    "currency_code": "USD",
    "gateway_specific_fields": {
      "paypal_commerce_platform": {
        "final_capture": true
      }
    }
  }
}'

Example flow: authorize 5.00 USD, capture 3.00 USD with final_capture: false, then capture 2.00 USD with final_capture: true.

Idempotent Requests

Pass gateway-specific field paypal_request_id, ideally as a UUID. Spreedly forwards this value as the PayPal-Request-Id header.

Supported operations include Purchase, Authorize, Capture, Credit, and Void.

curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "payment_method_token",
    "amount": 2800,
    "currency_code": "USD",
    "gateway_specific_fields": {
      "paypal_commerce_platform": {
        "paypal_request_id": "a1b2c3d4-e5f6-7890-abcd-ef123456xyz0"
      }
    }
  }
}'
  • Using the same key with the same payload should return the same gateway_transaction_id
  • If the payload changes, use a new idempotency key

Payouts via General Credit

General Credit can be used for PayPal payouts.

Required gateway-specific fields

  • recipient_type: EMAIL, PHONE, or PAYPAL_ID
  • recipient_wallet: PAYPAL, VENMO, or RECIPIENT_SELECTED
  • reference_id
  • email_subject
  • email_message

If a PayPal payout remains pending, Spreedly may keep the General Credit transaction pending until an inquire call resolves the final status.

Stored Credentials

For recurring or merchant-initiated usage patterns, include stored credential fields on Purchase or Authorize requests.

  • stored_credential_initiator
  • stored_credential_reason_type
curl https://core.spreedly.com/v1/gateways/[gateway_token]/purchase.json \
-u 'EnvironmentKey:AccessSecret' \
-H 'Content-Type: application/json' \
-d '{
  "transaction": {
    "payment_method_token": "payment_method_token",
    "amount": 100,
    "currency_code": "USD",
    "stored_credential_initiator": "cardholder",
    "stored_credential_reason_type": "recurring"
  }
}'

Gateway Specific Fields

Field NameTypeRequiredUse CaseExample
paypal_request_idStringNoIdempotency keyUUID value
final_captureBooleanNoMarks whether a partial capture is finalfalse
verification_methodStringNoControls verification behaviorSCA_WHEN_REQUIRED
recipient_typeStringYes for payoutsIdentifies the payout recipient typeEMAIL
recipient_walletStringYes for payoutsIdentifies the payout wallet destinationPAYPAL
reference_idStringNoMerchant reference for payoutsgeneral_credit_2020_100007
email_subjectStringYes for payoutsSubject line for payout notificationYou have a payout!
email_messageStringYes for payoutsMessage body for payout notificationThanks for using our service!

Existing nested fields may also apply, including purchase_units, application_context, airline_data, payee, order_only, and uuid.

Gateway Specific Response Fields

Offsite responses can include buyer and address information when enabled on the PayPal account. Possible fields include payer, first_name, last_name, billing and shipping address values, email, merchant_id, national_number, and issue for errors.

Additional resources

📘

If you need support with this gateway, please contact Support at [email protected].

📘

PayPal Commerce Platform documentation: PayPal developer documentation

API Endpoint: https://api.paypal.com (Production)
Test Endpoint: https://api-m.sandbox.paypal.com (Test)


Did this page help you?