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

# Accept payments for connected merchants

> Mount Ionic's payment form on your platform's page to accept payments for a connected merchant.

Use Ionic Blocks to embed a payment form on your platform's page. Add an empty
HTML element where you want the form to appear, then use Ionic.js to mount a
Payment Block inside it. Customers enter their card details in that Block.

Your platform uses its own API keys and selects the connected merchant with
the SDK's `account` option. The PaymentIntent belongs to that merchant, who
receives the payment. Use the same merchant ID when creating the intent on
your server and mounting the Block in the browser.

[How Connect works](/guides/connect-overview) explains platform and merchant
roles. The [Blocks guide](/guides/payment-fields) covers the shared payment
features and options.

## Before you begin

* Platform test keys from **Connect → API keys**, with the secret key on your server.
* An active connection granting `payments:write` and `payments:read`, with those
  permissions also on the platform key.
* Your page's origin registered for the same mode in **Connect → Payment domains**.
* `@ionicfi/sdk` 0.4.1 or later and `@ionicfi/js` 0.2.1 or later.

## Select the connected merchant

`GET /v1/connected_accounts` lists the platform's connections. Each `data[].id`
is a connected merchant ID. This platform-level request takes no
`Ionic-Account` header.

A merchant-scoped request uses `Ionic-Account`, or the server SDK's `account`
request option. The selected merchant, amount, and access to the resulting
intent must come from your application's authorization decisions.

## Create the PaymentIntent on your server

Use your platform's secret key and the selected merchant's ID. The
PaymentIntent specifies the payment amount; its `client_secret` lets the
browser display a Block for that payment.

```ts theme={null}
import { Ionic } from "@ionicfi/sdk";

const ionic = new Ionic({ token: process.env.IONIC_PLATFORM_SECRET_KEY });
const paymentIntent = await ionic.paymentIntents.create(
  {
    "Idempotency-Key": requestKey,
    amount: 12500,
    currency: "usd",
    capture_method: "automatic",
  },
  { account: "mer_BBBBBBBBBBBBBB" },
);
```

`requestKey` represents the application-assigned key for this operation.
Repeating the operation uses the same key and body. The key's scope includes the
receiving merchant and mode. See [Idempotency](/api-reference/idempotency).

The create response contains `client_secret`; secret-key retrieval does not
return its value. The browser needs authorized access to that secret, the
platform publishable key, and the matching connected merchant ID.

## Mount the Payment Block on your page

Add an empty HTML element where you want the payment form to appear:

```html theme={null}
<div id="payment"></div>
```

Run this code in the browser after the element exists. Replace the placeholder
values with your platform's publishable key, the connected merchant ID used on
your server, and the `client_secret` returned when that merchant's PaymentIntent
was created.

```ts theme={null}
import { loadIonic } from "@ionicfi/js";

const ionic = await loadIonic("pk_v1_test_...", { account: "mer_BBBBBBBBBBBBBB" });
const blocks = ionic.blocks({ clientSecret: "pi_..._secret_..." });
const payment = blocks.create("payment");
await payment.mount("#payment");
```

`blocks.create("payment")` creates the Payment Block.
`payment.mount("#payment")` displays it inside the `<div id="payment">` on
your page. `#payment` is the CSS selector for that element. The Block shows
Ionic's card fields, or the intent's status when card entry is no longer available.

Ionic automatically loads the secure card fields in an iframe hosted at
`embed.ionicfi.com`. If your site uses a Content Security Policy, follow the
[CSP configuration](/guides/payment-fields#content-security-policy).

Mounting displays the Block. Submitting the payment is a separate call to
`confirmPayment`.

## Confirm the payment and read its status

`ionic.confirmPayment({ blocks })` submits the card details from the mounted
Block for its PaymentIntent when your customer chooses to pay.
`ionic.retrievePaymentIntent(clientSecret)` reads that payment's current status.
Both calls use the connected merchant selected in `loadIonic`. The
[confirmation methods](/guides/payment-fields#confirmation-and-status) and
[retry limits](/guides/payment-fields#reloads-and-retries) are the same as for a
direct merchant.

The merchant is fixed for the client's lifetime. `blocks.destroy()` removes
the UI without canceling a submitted payment. A different merchant requires a
new client and an intent belonging to that merchant.

## Keep payment data with the correct merchant

| Value                               | Owner or scope                                                            |
| ----------------------------------- | ------------------------------------------------------------------------- |
| Secret and publishable keys         | The platform, in the intended mode.                                       |
| PaymentIntent and its client secret | The selected connected merchant.                                          |
| `customer` and saved payment method | The same connected merchant as the intent.                                |
| `reference`                         | Application-supplied correlation text; Ionic does not enforce uniqueness. |

Different merchants may use the same reference. A reference does not identify
a merchant or authorize access to a client secret. Any application lookup or
reuse must preserve the intended merchant and mode as well as the intent's
identity. A platform API key's access to both merchants does not authorize a
customer to access both merchants' payments.

## Platform payment events

A platform webhook endpoint belongs to the platform, so endpoint creation uses
platform keys without `Ionic-Account`. The Program needs `connect_webhooks`, the
key needs webhook-management permissions, and the merchant's connection needs
`payments:read` for payment events. See
[Platform webhooks](/webhooks/endpoints#platform-webhooks-for-connected-accounts).

`event.account` identifies the connected merchant. A verified signature proves
the delivery's authenticity, not its association with an application's purchase.
The merchant, mode, intent ID, amount, and currency must match the intended
payment. `reference` alone cannot establish that association.

Events may be duplicated or arrive out of order. Your application decides how
to record payment outcomes and apply fulfillment policy using the
[event and delivery contracts](/guides/payment-fields#payment-events).

## Save a card during the payment

A PaymentIntent with the same merchant's `customer` and
`setup_future_usage: "off_session"` enables optional saving. The customer’s
consent determines whether saving is requested. See
[Save the card being entered](/guides/payment-fields#save-the-card-being-entered).

For saving without payment, see [Save cards for connected merchants](/guides/connect-save-cards).
For live-mode setup, see [Going live](/guides/going-live#launching-a-connect-integration).
