> ## 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.

# In-person payments for connected accounts

> Run card-present payments on a connected account's terminals from your platform's point-of-sale backend.

A platform runs in-person payments for connected accounts through the same
terminal API a merchant uses for itself. Each request names the merchant with
`Ionic-Account`. That merchant owns its locations, terminals, [PaymentIntents](/concepts/key-concepts#how-the-objects-connect),
and the payments that result. Point-of-sale software on your platform can take
a sale at any connected account's counter with one set of platform keys.

The payment flow, statuses, and failure codes match
[Accept in-person terminal payments](/guides/in-person-payments).

## Before you begin

* A platform secret key from **Connect → API keys**, kept on your server.
* An active connection in the same mode. The platform key and the merchant's
  connection both grant each permission an operation needs:

| Operation | Permission |
| - | - |
| Create and update locations | `locations:write` |
| List and retrieve locations | `locations:read` |
| Request terminal hardware and configure test scenarios | `terminals:write` |
| List terminals and provisioning requests, check a terminal's connection, and read or refresh batches | `terminals:read` |
| Create PaymentIntents, process them on a terminal, request cancellation, and print receipts | `payments:write` |
| Retrieve PaymentIntents and terminal payments | `payments:read` |
| Refund a payment | `refunds:write` |

* A unique `Idempotency-Key` on each mutating `POST`. Reuse a key only to retry
  the same request.

`CONNECTED_ACCOUNT_ID` is the merchant's `mer_…` ID, selected by your
application's authorization logic.

## Find the merchant's terminals

Every test account, including a connected account's, includes two test
locations and three ready simulated terminals. List them for the merchant:

```bash theme={null}
curl https://api.ionicfi.com/v1/terminals \
  -H "Authorization: Bearer $IONIC_PLATFORM_SECRET_KEY" \
  -H "Ionic-Account: $CONNECTED_ACCOUNT_ID"
```

Each simulated terminal has a `test_profile` of `approved`, `declined`, or
`delayed`. Choose one and keep its `tmr_…` ID. See
[Test without physical hardware](/guides/in-person-payments#test-without-physical-hardware)
for each profile's behavior.

## Take a payment at the counter

<Steps>
  <Step title="Create the merchant's PaymentIntent">
    Create a USD PaymentIntent with automatic capture and no payment method.

    ```bash theme={null}
    curl https://api.ionicfi.com/v1/payment_intents \
      -H "Authorization: Bearer $IONIC_PLATFORM_SECRET_KEY" \
      -H "Ionic-Account: $CONNECTED_ACCOUNT_ID" \
      -H "Idempotency-Key: merchant-order-1042-intent" \
      -H "Content-Type: application/json" \
      -d '{
        "amount": 2500,
        "currency": "usd",
        "capture_method": "automatic"
      }'
    ```
  </Step>

  <Step title="Process it on the merchant's terminal">
    Select the terminal in the route and send the PaymentIntent ID. The
    terminal, the PaymentIntent, and the request belong to the same merchant
    and mode.

    ```bash theme={null}
    curl https://api.ionicfi.com/v1/terminals/$TERMINAL_ID/process_payment_intent \
      -H "Authorization: Bearer $IONIC_PLATFORM_SECRET_KEY" \
      -H "Ionic-Account: $CONNECTED_ACCOUNT_ID" \
      -H "Idempotency-Key: merchant-order-1042-terminal-attempt-1" \
      -H "Content-Type: application/json" \
      -d '{
        "payment_intent_id": "pi_01JEXAMPLEF9W6B3C2D7K4M8N"
      }'
    ```
  </Step>

  <Step title="Read the result">
    A `202` response means Ionic recorded the attempt. Retrieve the returned
    terminal payment for the same merchant until it reaches a final status.

    ```bash theme={null}
    curl https://api.ionicfi.com/v1/terminal_payments/$TERMINAL_PAYMENT_ID \
      -H "Authorization: Bearer $IONIC_PLATFORM_SECRET_KEY" \
      -H "Ionic-Account: $CONNECTED_ACCOUNT_ID"
    ```

    Then [handle each status and failure code](/guides/in-person-payments#handle-every-status).
  </Step>
</Steps>

An identifier that belongs to another merchant or mode returns `404`.
[Request cancellation](/guides/in-person-payments#request-cancellation) and
[Retrieve an unresolved attempt](/guides/in-person-payments#retrieve-an-unresolved-attempt)
work the same way with `Ionic-Account`.

## Equip a merchant's location

Physical terminals belong to a location in the merchant's account.

1. Create the location with `Ionic-Account` and `locations:write`. A location
   needs a `display_name`, `address`, `timezone`, and `merchant_category_code`.
   See [Create a terminal location](/api-reference/terminal-locations/create-a-terminal-location).
2. Request hardware for that location with `Ionic-Account` and
   `terminals:write`. The request takes the `location_id`, a `label`, and
   optional `metadata`. See
   [Request physical terminal hardware](/api-reference/terminal-provisioning/request-physical-terminal-hardware).
3. Retrieve the provisioning request until its `status` is `ready`. Its
   `terminal_id` then references the merchant's new terminal.

The terminal provisioning options are the same for every account. Read them
with a secret key from **Developers → API keys** in your platform's own Ionic
account, without `Ionic-Account`. See
[List terminal provisioning options](/api-reference/terminal-provisioning/list-terminal-provisioning-options).

## Refunds and receipts

Refund a merchant's in-person payment with `Ionic-Account` and
`refunds:write`. Include `terminal_id` to run a card-present refund on that
terminal. When the merchant has automatic refund receipts on, its receipt
prints there. Print a receipt on request with
[Print a refund receipt on a terminal](/api-reference/terminal-payments/print-a-refund-receipt-on-a-terminal),
which needs `payments:write`. See
[Refunds and captures for connected accounts](/guides/connect-refunds-captures)
and [Refund receipts](/concepts/terminal-object#refund-receipts).

## Batches and events

Read and refresh the merchant's terminal batches and settlement profiles with
`Ionic-Account` and `terminals:read`. A platform webhook endpoint receives each
merchant's events when that merchant's connection grants the matching read
permission:

| Events | Connection permission |
| - | - |
| `payment_intent.*`, `terminal_payment.*`, and `charge.settled` | `payments:read` |
| `terminal_batch.*` and `terminal_provisioning_request.*` | `terminals:read` |
| `refund.*` | `refunds:read` |

The event's `account` field names the merchant. See
[Webhooks for platforms](/guides/connect-webhooks).

## Keep terminal data with the correct merchant

| Value | Owner or scope |
| - | - |
| Platform secret key | The platform, in the intended mode. |
| Locations, terminals, and provisioning requests | The selected connected account. |
| PaymentIntent, terminal payment, Charge, and Refund | The same merchant and mode. |
| Batches and settlement profiles | The same merchant and mode. |

## Test before going live

Cover an approval, a decline, a delayed result, a retried request with the same
`Idempotency-Key`, a cancellation, a refund, and a batch refresh against a
connected test merchant's simulated terminals. Then run acceptance testing on an
Ionic-assigned physical test terminal before the merchant uses production
hardware. Live terminal payments require the merchant's account to accept live
payments. See [Test before going live](/guides/in-person-payments#test-before-going-live).

## What's next

<CardGroup cols={2}>
  <Card title="Refund and capture" icon="rotate-left" href="/guides/connect-refunds-captures">
    Refund, capture, or cancel a connected account's payment from your platform.
  </Card>

  <Card title="Read the Terminal object" icon="tablet-screen-button" href="/concepts/terminal-object">
    Check each terminal's setup, connection, and capability states.
  </Card>

  <Card title="Handle webhooks" icon="tower-broadcast" href="/guides/connect-webhooks">
    Receive every connected account's events on one endpoint and match each to its connected account.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.