> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gr4vy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PayPal Pay Later

> Configure PayPal Pay Later as a payment method in Gr4vy.

export const connector = {
  displayName: "Pay Later",
  method: "paypalpaylater",
  features: "create_transaction delayed_capture partial_capture partial_refunds redirect_requires_popup refunds requires_webhook_setup settlement_reporting transaction_sync verify_credentials void",
  supportedCountries: "AD AE AG AI AL AM AO AR AT AU AW AZ BA BB BE BF BG BH BI BJ BM BN BO BR BS BT BW BY BZ CA CD CG CH CI CK CL CM CN CO CR CV CY CZ DE DJ DK DM DO DZ EC EE EG ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GI GL GM GN GP GR GT GW GY HK HN HR HU ID IE IL IN IS IT JM JO JP KE KG KH KI KM KN KR KW KY KZ LA LC LI LK LS LT LU LV MA MC MD ME MG MH MK ML MN MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PL PM PN PT PW PY QA RE RO RS RU RW SA SB SC SE SG SH SI SJ SK SL SM SN SO SR ST SV SZ TC TD TG TH TJ TM TN TO TT TV TW TZ UA UG US UY VA VC VE VG VN VU WF WS YE YT ZA ZM ZW",
  supportedCurrencies: "AUD BRL CAD CHF CNY CZK DKK EUR GBP HKD HUF ILS INR JPY MXN MYR NOK NZD PHP PLN RUB SEK SGD THB TWD USD"
};

export const ConnectorRegions = ({data, kind, name: nameOverride}) => {
  const [query, setQuery] = useState("");
  const [open, setOpen] = useState(false);
  const isCountries = kind === "countries";
  const raw = data && (isCountries ? data.supportedCountries : data.supportedCurrencies);
  const codes = typeof raw === "string" ? raw.split(/\s+/).filter(Boolean) : Array.isArray(raw) ? raw : [];
  const DISPLAY_NAME_OVERRIDES = {
    authorizenet: "Authorize.net",
    cardpointe: "Fiserv CardPointe",
    dlocal: "dLocal",
    shift4i4go: "Shift4 i4go",
    tokenex: "TokenEx"
  };
  const rawName = data && data.displayName || "";
  const name = nameOverride || DISPLAY_NAME_OVERRIDES[rawName.toLowerCase()] || rawName || "This connector";
  const verb = isCountries ? "supports transactions from buyers in" : "supports processing payments in";
  const noun = isCountries ? "countries" : "currencies";
  if (codes.length === 0) return null;
  let displayNames = null;
  try {
    displayNames = new Intl.DisplayNames(["en"], {
      type: isCountries ? "region" : "currency"
    });
  } catch (e) {
    displayNames = null;
  }
  const resolve = code => {
    if (!displayNames) return null;
    try {
      const resolved = displayNames.of(code);
      return resolved && resolved !== code ? resolved : null;
    } catch (e) {
      return null;
    }
  };
  const MAJOR_CURRENCIES = ["USD", "EUR", "GBP", "CAD", "AUD", "JPY", "CHF", "CNY", "SGD", "HKD", "NZD", "SEK", "NOK", "DKK", "MXN", "BRL", "INR"];
  const items = codes.map(code => ({
    code,
    label: resolve(code)
  }));
  if (isCountries) {
    items.sort((a, b) => (a.label || a.code).localeCompare(b.label || b.code));
  } else {
    const rank = code => {
      const i = MAJOR_CURRENCIES.indexOf(code);
      return i === -1 ? MAJOR_CURRENCIES.length : i;
    };
    items.sort((a, b) => rank(a.code) - rank(b.code) || a.code.localeCompare(b.code));
  }
  if (codes.length <= 3) {
    const parts = items.map(it => isCountries || !it.label ? it.label || it.code : `${it.label} (${it.code})`);
    const joined = parts.length === 1 ? parts[0] : parts.length === 2 ? `${parts[0]} and ${parts[1]}` : `${parts.slice(0, -1).join(", ")}, and ${parts[parts.length - 1]}`;
    return <p>
        {name} {verb} {joined}.
      </p>;
  }
  const chipStyle = {
    display: "inline-flex",
    alignItems: "baseline",
    gap: "0.4rem",
    padding: "0.15rem 0.55rem",
    borderRadius: "0.375rem",
    border: "1px solid rgba(128, 128, 128, 0.25)",
    fontSize: "0.875rem",
    lineHeight: 1.5
  };
  const codeStyle = {
    fontFamily: "var(--font-mono, ui-monospace, monospace)",
    fontWeight: 600,
    fontSize: "0.8125rem"
  };
  const controlStyle = {
    color: "inherit",
    background: "transparent",
    border: "1px solid rgba(128, 128, 128, 0.3)",
    borderRadius: "0.5rem",
    fontSize: "0.875rem"
  };
  const renderChip = it => <span key={it.code} style={chipStyle} title={isCountries ? it.code : it.label || it.code}>
      {isCountries ? it.label || it.code : <span style={codeStyle}>{it.code}</span>}
      {!isCountries && it.label ? <span style={{
    opacity: 0.7
  }}>{it.label}</span> : null}
    </span>;
  const PREVIEW = 5;
  const collapsible = items.length > PREVIEW;
  const q = query.trim().toLowerCase();
  const filtered = q ? items.filter(it => it.code.toLowerCase().includes(q) || it.label && it.label.toLowerCase().includes(q)) : items;
  const expanded = open || q !== "";
  const visible = !collapsible ? items : expanded ? filtered : items.slice(0, PREVIEW);
  const toggle = () => {
    const next = !open;
    setOpen(next);
    if (!next) setQuery("");
  };
  return <div>
      <p>
        {name} {verb} the following {codes.length} {noun}:
      </p>

      {collapsible ? <input type="text" value={query} onChange={e => setQuery(e.target.value)} placeholder={`Filter ${noun}…`} aria-label={`Filter ${noun}`} style={{
    ...controlStyle,
    display: "block",
    width: "100%",
    maxWidth: "22rem",
    padding: "0.4rem 0.7rem",
    margin: "0 0 0.75rem"
  }} /> : null}

      <div style={{
    display: "flex",
    flexWrap: "wrap",
    gap: "0.4rem"
  }}>
        {visible.map(renderChip)}
      </div>

      {q && filtered.length === 0 ? <p style={{
    opacity: 0.7,
    marginTop: "0.6rem"
  }}>
          No {noun} match “{query.trim()}”.
        </p> : null}
      {q && filtered.length > 0 ? <p style={{
    opacity: 0.6,
    fontSize: "0.8125rem",
    marginTop: "0.6rem"
  }}>
          Showing {filtered.length} of {items.length}.
        </p> : null}

      {collapsible && !q ? <button type="button" aria-expanded={open} onClick={toggle} style={{
    ...controlStyle,
    display: "inline-flex",
    alignItems: "center",
    gap: "0.4rem",
    padding: "0.35rem 0.75rem",
    marginTop: "0.75rem",
    cursor: "pointer"
  }}>
          <span aria-hidden="true" style={{
    display: "inline-block",
    transform: open ? "rotate(90deg)" : "none",
    transition: "transform 0.15s ease"
  }}>
            ›
          </span>
          {open ? "Show fewer" : `and ${items.length - PREVIEW} more`}
        </button> : null}
    </div>;
};

export const ConnectorCapabilities = ({data}) => {
  const CAPABILITIES = [{
    keys: ["three_d_secure_hosted"],
    label: "3-D Secure (hosted)",
    description: "Gr4vy-hosted 3DS authentication flow.",
    cardOnly: true
  }, {
    keys: ["three_d_secure_pass_through"],
    label: "3-D Secure (pass-through)",
    description: "Pass through 3DS data authenticated by a third party.",
    cardOnly: true
  }, {
    keys: ["partial_authorization"],
    label: "Partial authorization",
    description: "Support partial approval responses."
  }, {
    keys: ["zero_auth"],
    label: "Zero auth",
    description: "Verify a card without charging it."
  }, {
    keys: ["void"],
    label: "Void",
    description: "Cancel an authorized transaction before capture."
  }, {
    keys: ["direct_capture"],
    label: "Direct capture",
    description: "Capture a payment immediately at authorization.",
    hideWhenUnsupported: true
  }, {
    keys: ["delayed_capture"],
    label: "Delayed capture",
    description: "Authorize a payment and capture it at a later time."
  }, {
    keys: ["partial_capture"],
    label: "Partial capture",
    description: "Capture a portion of the authorized amount."
  }, {
    keys: ["over_capture"],
    label: "Over capture",
    description: "Capture more than the originally authorized amount."
  }, {
    keys: ["refunds"],
    label: "Refunds",
    description: "Refund a captured payment."
  }, {
    keys: ["partial_refunds"],
    label: "Partial refunds",
    description: "Refund a portion of the captured amount."
  }, {
    keys: ["settlement_reporting"],
    label: "Settlement reporting",
    description: "Automatic settlement and reconciliation reporting."
  }, {
    keys: ["create_session"],
    label: "Create session",
    description: "Create a connector session for client-side flows."
  }, {
    keys: ["network_tokens_default", "network_tokens_toggle"],
    label: "Network tokens",
    description: "Network-level tokenization for improved approval rates.",
    cardOnly: true
  }, {
    keys: ["digital_wallets"],
    label: "Digital wallets",
    description: "Apple Pay, Google Pay, and other wallet integrations."
  }, {
    keys: ["payment_method_tokenization", "payment_method_tokenization_toggle"],
    label: "Payment method tokenization",
    description: "Store payment methods outside of transactions."
  }, {
    keys: ["transaction_sync"],
    label: "Transaction sync",
    description: "Synchronize transaction state from the connector."
  }, {
    keys: ["create_token"],
    label: "Tokenization",
    description: "Create a token from card details collected via Secure Fields.",
    hideWhenUnsupported: true
  }, {
    keys: ["delete_token"],
    label: "Delete token",
    description: "Delete a stored token.",
    hideWhenUnsupported: true
  }, {
    keys: ["verify_credentials"],
    label: "Verify credentials",
    description: "Validate the configured credentials against the connector.",
    hideWhenUnsupported: true
  }];
  const raw = data && data.features;
  const enabled = typeof raw === "string" ? new Set(raw.split(/\s+/).filter(Boolean)) : Array.isArray(raw) ? new Set(raw) : new Set(Object.keys(raw || ({})).filter(key => raw[key]));
  const isOn = entry => entry.keys.some(key => enabled.has(key));
  const isNonCard = data && data.method && data.method !== "card";
  const renderGroup = (title, entries, supported) => {
    if (entries.length === 0) return null;
    const mark = supported ? "✓" : "✕";
    const markColor = supported ? "#16a34a" : "#9ca3af";
    return <div style={{
      marginTop: "1rem"
    }}>
        <div style={{
      fontSize: "0.75rem",
      fontWeight: 600,
      letterSpacing: "0.05em",
      textTransform: "uppercase",
      opacity: 0.6,
      marginBottom: "0.25rem"
    }}>
          {title}
        </div>
        {}
        <div role="list">
          {entries.map(entry => <div role="listitem" key={entry.label} style={{
      display: "flex",
      gap: "0.5rem",
      alignItems: "baseline",
      padding: "0.3rem 0",
      opacity: supported ? 1 : 0.7
    }}>
              <span aria-hidden="true" style={{
      color: markColor,
      fontWeight: 700,
      flexShrink: 0
    }}>
                {mark}
              </span>
              <span>
                <strong>{entry.label}</strong>
                {entry.description ? <span style={{
      opacity: 0.85
    }}> — {entry.description}</span> : null}
              </span>
            </div>)}
        </div>
      </div>;
  };
  const visible = isNonCard ? CAPABILITIES.filter(entry => !entry.cardOnly) : CAPABILITIES;
  const supported = visible.filter(isOn);
  const unsupported = visible.filter(entry => !isOn(entry) && !entry.hideWhenUnsupported);
  return <div>
      {renderGroup("Supported", supported, true)}
      {renderGroup("Not supported", unsupported, false)}
    </div>;
};

PayPal Pay Later provides installment and deferred payment options for eligible buyers. This buy now, pay later (BNPL) solution allows customers to split purchases into interest-free payments or defer payment, subject to credit approval and eligibility criteria determined by PayPal.

<Info>Pay Later availability automatically depends on buyer eligibility, which is determined by PayPal based on factors like purchase amount, buyer history, and location.</Info>

## Setup

Follow the [PayPal setup instructions](./paypal) before configuring PayPal Pay Later.

After setting up your PayPal account, Pay Later options are automatically presented to eligible buyers during checkout. No additional configuration is required beyond enabling the payment method in your Gr4vy connection.

## Capabilities

<ConnectorCapabilities data={connector} />

## Integration

For PayPal Pay Later, the default integration is through a redirect to PayPal's hosted checkout page where eligible buyers are presented with Pay Later options.

Start by creating a new transaction with the following required fields.

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
    transactionCreate: new TransactionCreate()
    {
      Amount = 1299,
      Currency = "USD",
      Country = "US",
      PaymentMethod =
        TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
          new RedirectPaymentMethodCreate()
          {
            Method = "paypalpaylater",
            Country = "US",
            Currency = "USD",
            RedirectUrl = "https://example.com/callback",
          }
        ),
    }
  );
  ```

  ```go Go theme={"system"}
  amount := int64(1299)
  currency := "USD"
  country := "US"
  method := components.RedirectPaymentMethodCreateMethodPaypalpaylater
  redirectUrl := "https://example.com/callback"

  redirectPaymentMethodCreate := components.RedirectPaymentMethodCreate{
    Method: method,
    Country: country,
    Currency: currency,
    RedirectURL: redirectUrl,
  }
  paymentMethod := components.CreateTransactionCreatePaymentMethodRedirectPaymentMethodCreate(redirectPaymentMethodCreate)

  transactionCreate := components.TransactionCreate{
    Amount:        amount,
    Currency:      currency,
    Country:       &country,
    PaymentMethod: &paymentMethod,
  }

  transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
  ```

  ```java Java theme={"system"}
  CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
    .transactionCreate(TransactionCreate.builder()
      .amount(1299L)
      .currency("USD")
      .country("US")
      .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
        .method(RedirectPaymentMethodCreateMethod.PAYPALPAYLATER)
        .country("US")
        .currency("USD")
        .redirectUrl("https://example.com/callback")
        .build()))
      .build())
    .call();

  Transaction transaction = transactionResponse.transaction().orElse(null);
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(
    amount: 1299,
    currency: 'USD',
    country: 'US',
    paymentMethod: new RedirectPaymentMethodCreate(
      method: 'paypalpaylater',
      country: 'US',
      currency: 'USD',
      redirectUrl: 'https://example.com/callback'
    )
  );
  $response = self::$sdk->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction: models.Transaction = client.transactions.create(
    amount=1299,
    currency="USD",
    country="US",
    payment_method={
      "method": "paypalpaylater",
      "country": "US",
      "currency": "USD",
      "redirect_url": "https://example.com/callback",
    }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
    amount: 1299,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "paypalpaylater",
      country: "US",
      currency: "USD",
      redirectUrl: "https://example.com/callback"
    }
  })
  ```
</CodeGroup>

After the transaction is created, the API response includes `payment_method.approval_url` and the `buyer_approval_pending` status.

```json theme={"system"}
{
  "type": "transaction",
  "id": "ea1efdd0-20f9-44d9-9b0b-0a3d71e9b625",
  "payment_method": {
    "type": "payment-method",
    "approval_url": "https://www.paypal.com/checkoutnow?token=..."
  },
  "method": "paypalpaylater"
}
```

Redirect the buyer to the `approval_url` where PayPal determines eligibility and presents available Pay Later options. After the buyer reviews terms and approves the payment, they are redirected to the `redirect_url` you provided when creating the transaction. Do not rely solely on the redirect - either poll the transaction or (recommended) rely on webhooks to detect the final status (for example `capture_succeeded` or failure states).

## Supported countries

<ConnectorRegions data={connector} kind="countries" />

## Testing

PayPal provides a sandbox environment for testing Pay Later transactions. After setting up your sandbox PayPal developer account, you can create test buyer accounts in the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard/accounts).

Pay Later options in the sandbox simulate the eligibility and approval flow. Note that specific Pay Later products (like Pay in 4 or Pay in 30 days) may vary by test account configuration.

For detailed testing instructions and Pay Later-specific sandbox guidelines, see the [PayPal Pay Later documentation](https://developer.paypal.com/docs/checkout/pay-later/integrate/).

## Additional configuration

### Ingest billing and shipping details

By default, billing, and shipping details received from PayPal are not imported. To enable this feature, head over to **Connections** → **Configured** and select your PayPal connector. Next, go to **Credentials** and toggle **Import billing details** and/or **Import shipping details**.

When **Import billing details** is enabled, any of the user's name, email address, and billing address are automatically imported into your transaction, merging it with any data already present on the transaction. Linked buyers are not updated, but only the snapshot of the buyer on the transaction.

When **Import shipping details** is enabled, the user's shipping address is automatically **requested** and imported into your transaction, merging it with any data already present on the transaction. Linked buyers are not updated, but only the snapshot of the buyer on the transaction.

<Note>The ingestion of billing and shipping details is not available for tokenized payments.</Note>

### Server-side shipping callbacks

When **Import shipping details** is enabled, you can configure PayPal to call your server whenever the buyer changes their shipping address or selects a different shipping option during checkout. This lets you return updated shipping costs and available options in real time.

To enable this, pass `order_update_callback_config` in `connection_options["paypal-paypalpaylater"]` when creating a transaction:

| Field             | Description                                                                                                                                                                            |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `callback_url`    | The URL PayPal calls when the buyer updates their shipping details.                                                                                                                    |
| `callback_events` | Array of events to subscribe to. `"SHIPPING_ADDRESS"` fires when the buyer changes their shipping address; `"SHIPPING_OPTIONS"` fires when they change their selected shipping option. |

<CodeGroup>
  ```csharp C# theme={"system"}
  var transaction = await client.Transactions.CreateAsync(
    transactionCreate: new TransactionCreate()
    {
      Amount = 1299,
      Currency = "USD",
      Country = "US",
      PaymentMethod =
        TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
          new RedirectPaymentMethodCreate()
          {
            Method = "paypalpaylater",
            Country = "US",
            Currency = "USD",
            RedirectUrl = "https://example.com/callback",
          }
        ),
      ConnectionOptions = new Dictionary<string, object>()
      {
        ["paypal-paypalpaylater"] = new Dictionary<string, object>()
        {
          ["order_update_callback_config"] = new Dictionary<string, object>()
          {
            ["callback_url"] = "https://example.com/shipping-callback",
            ["callback_events"] = new List<string> { "SHIPPING_ADDRESS", "SHIPPING_OPTIONS" },
          }
        }
      }
    }
  );
  ```

  ```go Go theme={"system"}
  amount := int64(1299)
  currency := "USD"
  country := "US"
  method := components.RedirectPaymentMethodCreateMethodPaypalpaylater
  redirectUrl := "https://example.com/callback"

  redirectPaymentMethodCreate := components.RedirectPaymentMethodCreate{
    Method: method,
    Country: country,
    Currency: currency,
    RedirectURL: redirectUrl,
  }
  paymentMethod := components.CreateTransactionCreatePaymentMethodRedirectPaymentMethodCreate(redirectPaymentMethodCreate)

  transactionCreate := components.TransactionCreate{
    Amount:        amount,
    Currency:      currency,
    Country:       &country,
    PaymentMethod: &paymentMethod,
    ConnectionOptions: map[string]interface{}{
      "paypal-paypalpaylater": map[string]interface{}{
        "order_update_callback_config": map[string]interface{}{
          "callback_url":    "https://example.com/shipping-callback",
          "callback_events": []string{"SHIPPING_ADDRESS", "SHIPPING_OPTIONS"},
        },
      },
    },
  }

  transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
  ```

  ```java Java theme={"system"}
  CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
    .transactionCreate(TransactionCreate.builder()
      .amount(1299L)
      .currency("USD")
      .country("US")
      .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
        .method(RedirectPaymentMethodCreateMethod.PAYPALPAYLATER)
        .country("US")
        .currency("USD")
        .redirectUrl("https://example.com/callback")
        .build()))
      .connectionOptions(Map.of(
        "paypal-paypalpaylater", Map.of(
          "order_update_callback_config", Map.of(
            "callback_url", "https://example.com/shipping-callback",
            "callback_events", List.of("SHIPPING_ADDRESS", "SHIPPING_OPTIONS")
          )
        )
      ))
      .build())
    .call();

  Transaction transaction = transactionResponse.transaction().orElse(null);
  ```

  ```php PHP theme={"system"}
  $transactionCreate = new TransactionCreate(
    amount: 1299,
    currency: 'USD',
    country: 'US',
    paymentMethod: new RedirectPaymentMethodCreate(
      method: 'paypalpaylater',
      country: 'US',
      currency: 'USD',
      redirectUrl: 'https://example.com/callback'
    ),
    connectionOptions: [
      'paypal-paypalpaylater' => [
        'order_update_callback_config' => [
          'callback_url' => 'https://example.com/shipping-callback',
          'callback_events' => ['SHIPPING_ADDRESS', 'SHIPPING_OPTIONS'],
        ]
      ]
    ]
  );
  $response = self::$sdk->transactions->create($transactionCreate);
  $transaction = $response->transaction;
  ```

  ```python Python theme={"system"}
  transaction: models.Transaction = client.transactions.create(
    amount=1299,
    currency="USD",
    country="US",
    payment_method={
      "method": "paypalpaylater",
      "country": "US",
      "currency": "USD",
      "redirect_url": "https://example.com/callback",
    },
    connection_options={
      "paypal-paypalpaylater": {
        "order_update_callback_config": {
          "callback_url": "https://example.com/shipping-callback",
          "callback_events": ["SHIPPING_ADDRESS", "SHIPPING_OPTIONS"],
        }
      }
    }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
    amount: 1299,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "paypalpaylater",
      country: "US",
      currency: "USD",
      redirectUrl: "https://example.com/callback"
    },
    connectionOptions: {
      "paypal-paypalpaylater": {
        order_update_callback_config: {
          callback_url: "https://example.com/shipping-callback",
          callback_events: ["SHIPPING_ADDRESS", "SHIPPING_OPTIONS"],
        }
      }
    }
  })
  ```
</CodeGroup>

### Checkout experience

You can customize the PayPal Checkout page by passing any of the following fields in `connection_options["paypal-paypalpaylater"]` when creating a transaction.

| Field                 | Description                                                                                                                                                                                                                                                                                                                                                                           |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `user_action`         | Controls the label on the PayPal Checkout button. `"PAY_NOW"` (default) shows an immediate pay button; `"CONTINUE"` shows a continue button for deferred-payment flows.                                                                                                                                                                                                               |
| `shipping_preference` | Controls how the shipping address is sourced during checkout. `"NO_SHIPPING"` hides the shipping address fields; `"GET_FROM_FILE"` lets the buyer provide or change their address during checkout; `"SET_PROVIDED_ADDRESS"` pre-fills the address you supplied and prevents the buyer from changing it. When omitted, Gr4vy determines this value automatically (see the note below). |
| `brand_name`          | The merchant brand name displayed on the PayPal Checkout page. Maximum 127 characters.                                                                                                                                                                                                                                                                                                |
| `landing_page`        | The page shown to the buyer when they arrive at PayPal. `"LOGIN"` opens the PayPal login page; `"GUEST_CHECKOUT"` opens the guest checkout page; `"NO_PREFERENCE"` lets PayPal decide.                                                                                                                                                                                                |
| `locale`              | A BCP 47 locale tag used to localize the PayPal Checkout page, for example `"en-US"` or `"fr-FR"`.                                                                                                                                                                                                                                                                                    |

<Note>
  `"GUEST_CHECKOUT"` for `landing_page` only takes effect if **PayPal account optional** is enabled in your PayPal merchant account settings. If the setting is not enabled, PayPal falls back to showing the login page regardless.
</Note>

<Note>
  `locale` is a hint to PayPal and may not always be honored. PayPal also determines locale from the buyer's browser cookies and the configuration of its own SDK, so the effective locale can differ from the value you provide.
</Note>

<CodeGroup>
  ```csharp C# theme={"system"}
  ConnectionOptions = new Dictionary<string, object>()
  {
    ["paypal-paypalpaylater"] = new Dictionary<string, object>()
    {
      ["user_action"] = "PAY_NOW",
      ["shipping_preference"] = "GET_FROM_FILE",
      ["brand_name"] = "Acme Store",
      ["landing_page"] = "LOGIN",
      ["locale"] = "en-US",
    }
  }
  ```

  ```go Go theme={"system"}
  ConnectionOptions: map[string]interface{}{
    "paypal-paypalpaylater": map[string]interface{}{
      "user_action":         "PAY_NOW",
      "shipping_preference": "GET_FROM_FILE",
      "brand_name":          "Acme Store",
      "landing_page":        "LOGIN",
      "locale":              "en-US",
    },
  },
  ```

  ```java Java theme={"system"}
  .connectionOptions(Map.of(
    "paypal-paypalpaylater", Map.of(
      "user_action", "PAY_NOW",
      "shipping_preference", "GET_FROM_FILE",
      "brand_name", "Acme Store",
      "landing_page", "LOGIN",
      "locale", "en-US"
    )
  ))
  ```

  ```php PHP theme={"system"}
  connectionOptions: [
    'paypal-paypalpaylater' => [
      'user_action' => 'PAY_NOW',
      'shipping_preference' => 'GET_FROM_FILE',
      'brand_name' => 'Acme Store',
      'landing_page' => 'LOGIN',
      'locale' => 'en-US',
    ]
  ]
  ```

  ```python Python theme={"system"}
  transaction = client.transactions.create(
    amount=1299,
    currency="USD",
    country="US",
    payment_method={
      "method": "paypalpaylater",
      "country": "US",
      "currency": "USD",
      "redirect_url": "https://example.com/callback",
    },
    connection_options={
      "paypal-paypalpaylater": {
        "user_action": "PAY_NOW",
        "shipping_preference": "GET_FROM_FILE",
        "brand_name": "Acme Store",
        "landing_page": "LOGIN",
        "locale": "en-US",
      }
    }
  )
  ```

  ```ts TypeScript theme={"system"}
  const transaction = await gr4vy.transactions.create({
    amount: 1299,
    currency: "USD",
    country: "US",
    paymentMethod: {
      method: "paypalpaylater",
      country: "US",
      currency: "USD",
      redirectUrl: "https://example.com/callback",
    },
    connectionOptions: {
      "paypal-paypalpaylater": {
        user_action: "PAY_NOW",
        shipping_preference: "GET_FROM_FILE",
        brand_name: "Acme Store",
        landing_page: "LOGIN",
        locale: "en-US",
      },
    },
  });
  ```
</CodeGroup>

<Note>
  `shipping_preference` is automatically determined by Gr4vy when not set. It is set to `GET_FROM_FILE` when `order_update_callback_config` is set and shipping ingestion is enabled, `SET_PROVIDED_ADDRESS` when a shipping address is supplied on the transaction, and `NO_SHIPPING` otherwise. Setting `shipping_preference` explicitly overrides this automatic behavior.
</Note>

### Payment receiving preferences

By default, PayPal only settles payments automatically if the payment is in the primary currency of the PayPal merchant account. If you need to accept payments in additional currencies, you need to open a PayPal account balance in each of the currencies you intend to accept. Alternatively, you can configure your PayPal merchant account to automatically convert payments into the primary currency.

If you receive a payment in a currency that your PayPal merchant account is not configured to accept, the payment enters a pending state and you need to log in to the PayPal merchant dashboard to trigger settlement, either by opening the required currency balance, or converting the payment into the primary currency of your PayPal account.

<Warning>Payments left in a pending state are eventually reversed by PayPal.</Warning>

### FraudNet

FraudNet is a PayPal-developed JavaScript library that collects browser-based data to help reduce fraud. Upon checkout, the FraudNet library sends data elements to PayPal Risk Services for fraud and risk assessment.

When creating transactions, the PayPal FraudNet library must be included on the checkout page for all transactions. When using Embed, the PayPal FraudNet library is included automatically. If you are using the API directly, you need to use the [device fingerprinting library](../../guides/features/anti-fraud/fingerprint) which includes the PayPal FraudNet library.

## Supported currencies

<ConnectorRegions data={connector} kind="currencies" />
