# Test in-person payments without hardware

Run the whole in-person flow in Playground with a simulated device and a simulated card tap from /ipp/v1/dev, then work through the checklist before going live.

Playground has two dev-only endpoints under `/ipp/v1/dev/*` that stand in for the device and
the card. You get the same sessions, callbacks and orders as production, with no app and no
hardware.

## Before you start

- Playground API credentials, with in-person payments enabled on the account.
- A [callback handler](/in-person/take-a-payment/#2-handle-the-callbacks) reachable from
  Kustom.

**The dev endpoints exist only on `api.playground.kustom.co`.** In production they return
`404`.

## Step by step

### 1. Create a simulated device

[`POST /ipp/v1/dev/devices`](/api/in-person-payments/create-simulated-device/). It's
registered instantly, needs no app and carries `simulated: true` in its metadata. Use its
`device_id` exactly as you would a real one.

### 2. Create a session

[Create a session](/in-person/take-a-payment/#1-create-a-session) against the simulated
device, with the same call you'll use in production.

### 3. Simulate a card tap

[`POST /ipp/v1/dev/sessions/{sessionId}/simulate-tap`](/api/in-person-payments/simulate-card-tap/),
choosing an `outcome`. Leave it out and you get `SUCCESS`, which finalizes the session. Any
other value declines the tap and arrives as `ipp.payment.failed` — every outcome is listed
in [Session states and callbacks](/in-person/sessions-and-callbacks/#card-tap-outcomes).

## Check that it works

Before going live, confirm all of these against Playground:

- The device is enrolled and appears in the device list.
- A session is created and reaches the device.
- `ipp.session.finalized` arrives and your handler processes it.
- The `order_id` from that callback is linked to your own order record.
- A `DECLINED_GENERIC` outcome is handled without breaking the sale.
- Cancellation from your backend works.
- Your callback endpoint returns `2xx` reliably, under load.

## Troubleshooting

**The dev endpoints return `404`.** You're calling production. They exist in Playground
only.

## Related

- [Enroll a device](/in-person/enroll-a-device/) — pair a real phone or terminal once the flow works
