> For the complete documentation index, see [llms.txt](https://docs.commercelayer.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.commercelayer.io/core-api-reference/2026-05/payment_setting_paypals.md).

# Payment setting paypals

The payment setting paypal object and the allowed CRUD operations on the related resource endpoint

PayPal payment settings are the PayPal-specific subtype of [payment settings](/core-api-reference/2026-05/payment_settings.md). They hold the credentials and configuration required to process payments through [PayPal](https://www.paypal.com)'s REST API.

## Credentials

Setting up a PayPal payment setting requires the following credential attributes:

<table><thead><tr><th width="220">Attribute</th><th>Description</th><th width="100" data-type="checkbox">Required</th></tr></thead><tbody><tr><td><strong><code>client_id</code></strong></td><td>Your PayPal REST API client ID.</td><td>true</td></tr><tr><td><strong><code>client_secret</code></strong></td><td>Your PayPal REST API client secret.</td><td>true</td></tr><tr><td><strong><code>webhook_id</code></strong></td><td>The ID of the PayPal webhook configured to point at <code>webhook_endpoint_url</code> — used to verify incoming <a href="#webhook-events">webhook</a> signatures.</td><td>true</td></tr></tbody></table>

## Capabilities

PayPal payment settings support the following Commerce Layer features:

<table><thead><tr><th width="220">Feature</th><th width="100" data-type="checkbox">Supported</th><th>Notes</th></tr></thead><tbody><tr><td>Payment sessions</td><td>true</td><td></td></tr><tr><td>Payment wallets</td><td>true</td><td></td></tr><tr><td>Payment links</td><td>false</td><td></td></tr><tr><td>3DS / SCA</td><td>false</td><td>PayPal's own <a href="#approval-flow">approval step</a> provides equivalent strong customer authentication, but through a different mechanism — see below.</td></tr></tbody></table>

## Approval flow

{% hint style="info" %}
Unlike gateways that redirect the customer during authorization, PayPal requires the shopper's approval **before** an authorization can be attempted.
{% endhint %}

When a payment session is created with a PayPal payment setting, Commerce Layer creates a PayPal order and stores the raw response — including its HATEOAS `links` array — in the session's `response_data` attribute. Redirect the shopper to the link with the `rel` attribute set to `approve` to complete PayPal's approval step.

{% hint style="warning" %}
Because approval happens at session creation rather than during authorization, a PayPal payment authorization never transitions to `requires_action` — `next_action_type` and `next_action_data` stay `null` throughout its lifecycle. Attempting to authorize before the shopper has approved the order is rejected by PayPal.
{% endhint %}

Once the shopper returns from the approval step, create a [payment authorization](/core-api-reference/2026-05/payment_authorizations.md) as usual to complete the payment — or, if `auto_capture` is enabled, to authorize and capture it in one step.

## Wallet vaulting

PayPal vaulting uses a two-step token exchange. Your client-side integration (the PayPal JS SDK) collects the shopper's consent and produces a **setup token** — Commerce Layer never creates this token itself. Submit its ID back when creating the payment wallet, via the `_payment_details` trigger attribute:

<pre class="language-json"><code class="lang-json">{
  "data": {
    "type": "payment_wallets",
    "attributes": {
<strong>      "_payment_details": { "setup_token_id": "..." }
</strong>    },
    "relationships": {
      "customer": { "data": { "type": "customers", "id": "..." } },
      "payment_setting": {
        "data": { "type": "payment_setting_paypals", "id": "..." }
      }
    }
  }
}
</code></pre>

Commerce Layer exchanges the setup token for a permanent payment token via PayPal's Vault API and stores it as the wallet's `payment_token`. Unless you supply your own `customer_token`, Commerce Layer sends the customer's own identifier alongside the setup token in that same request and stores it as the wallet's customer token — it's a separate input, not part of the token exchange itself.

{% hint style="info" %}
You can find more information about how this compares to the other payment providers [here](/core-api-reference/2026-05/payment_wallets.md#token-references).
{% endhint %}

### Vaulting during a payment

When a [payment session](/core-api-reference/2026-05/payment_sessions.md#vaulting-during-a-charge) has vaulting enabled, Commerce Layer asks PayPal to store the shopper's account once the payment succeeds, and creates the wallet from the vault token PayPal returns — no setup token is needed. PayPal can store the account right away, in which case the wallet is created with the authorization, or complete the payment first and store the account shortly after: the wallet is then created when the `VAULT.PAYMENT-TOKEN.CREATED` [webhook event](#webhook-events) arrives.

{% hint style="warning" %}
PayPal only vaults the account when reference transactions are enabled on your PayPal merchant account — otherwise the session is paid all the same, but no wallet is created.
{% endhint %}

### Duplicate wallets

PayPal keeps one vault token per PayPal account and customer, and returns the same one when that account is vaulted again for the same PayPal customer. Commerce Layer stores the PayPal customer ID on each wallet and reuses it for every later vaulting of that customer, directly or during a payment, while your own customer ID travels separately as the merchant reference. When a payment session with vaulting enabled vaults an account the customer already holds in an active wallet, the session is linked to that wallet instead of creating a new one.

{% hint style="warning" %}
Creating a wallet directly for an account that's already stored in one of the customer's active wallets is rejected, with a `422 Unprocessable Entity` error pointing to the existing wallet.
{% endhint %}

## Webhook events

Commerce Layer listens to the following PayPal webhook events, sent to the `webhook_endpoint_url` attribute exposed on this resource — configure it, along with the events below, as a webhook in the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard/webhooks), and copy the generated ID into the `webhook_id` credential attribute:

<table><thead><tr><th width="330">Event</th><th>Action</th></tr></thead><tbody><tr><td><strong><code>PAYMENT.AUTHORIZATION.CREATED</code></strong></td><td>Creates or updates a payment authorization — <code>succeeded</code> or <code>failed</code>.</td></tr><tr><td><strong><code>PAYMENT.AUTHORIZATION.VOIDED</code></strong></td><td>Creates or updates a payment void — <code>succeeded</code>.</td></tr><tr><td><strong><code>PAYMENT.CAPTURE.COMPLETED</code></strong></td><td>Creates or updates a payment capture — <code>succeeded</code>.</td></tr><tr><td><strong><code>PAYMENT.CAPTURE.DENIED</code></strong></td><td>Creates or updates a payment capture — <code>failed</code>.</td></tr><tr><td><strong><code>PAYMENT.CAPTURE.REFUNDED</code></strong></td><td>Creates or updates a payment refund — <code>succeeded</code>.</td></tr><tr><td><strong><code>VAULT.PAYMENT-TOKEN.CREATED</code></strong></td><td>Creates a <code>succeeded</code> payment wallet linked to the payment session that asked for vaulting, if it doesn't have one yet.</td></tr></tbody></table>

Events are matched to a payment session using the originating order ID — the same value Commerce Layer stores as the session's `token` — which PayPal sets in the event resource's `supplementary_data.related_ids.order_id` field for payment events, and in its `metadata.order_id` field for `VAULT.PAYMENT-TOKEN.CREATED`. If the referenced transaction does not already exist, it is created automatically.

{% hint style="info" %}
Unlike Adyen, Braintree, and Checkout.com, PayPal has no local signature check based on a shared secret. Commerce Layer verifies every incoming event with a server-to-server call to [PayPal's own verification endpoint](https://developer.paypal.com/api/rest/webhooks/rest/#link-verifyeventsignature) before processing it.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.commercelayer.io/core-api-reference/2026-05/payment_setting_paypals.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
