# Enroll a device

Pair a phone or Kustom terminal with your account through an enrollment code from POST /ipp/v1/enrollments, then list, name and deregister your devices.

A phone or terminal can't take payments until it's enrolled on your account. Your backend
creates a single-use enrollment code, a clerk types it into the Kustom POS app, and the app
pairs itself. Creating the code is the only part you build.

```mermaid
sequenceDiagram
    actor Clerk as Store clerk
    participant POS as Kustom POS app
    participant Kustom
    participant Server as Your server

    critical Create an enrollment
        %% href: #1-create-an-enrollment
        Server->>+Kustom: POST /ipp/v1/enrollments
        Note over Server,Kustom: authenticated with your API credentials
        Kustom-->>-Server: enrollment_code and expires_at
    end

    critical Hand the code to the clerk
        %% href: #2-hand-the-code-to-the-clerk
        Server->>Clerk: the enrollment code
        Note over Server,Clerk: by any route you choose, or your MDM pushes it to the device
        Clerk->>POS: types the code
    end

    critical The app registers the device
        POS->>+Kustom: register the device
        Note over POS,Kustom: no API credentials: the code is the credential
        Kustom-->>-POS: device record and bearer token
    end

    critical Manage the device
        %% href: #3-manage-the-device-afterwards
        Server->>+Kustom: GET /ipp/v1/devices
        Kustom-->>-Server: device_id and your enrollment metadata
    end
```

## Before you start

- In-person payments is [enabled on your account](/in-person/#getting-set-up).
- The Kustom POS app is installed on the device.
- If your account has more than one location, you know which one the device belongs to. You
  can [list your locations](/api/in-person-payments/list-locations/) to find the
  `location_id`.

Enrolling many managed devices at once? [Enroll a managed fleet](/in-person/enroll-a-managed-fleet/)
pushes the codes through your MDM instead.

## Step by step

### 1. Create an enrollment

[`POST /ipp/v1/enrollments`](/api/in-person-payments/create-enrollment/). The response
carries an `enrollment_code` and an `expires_at`.

The `ttl` you send decides what kind of code you get:

| `ttl` | Code |
|---|---|
| `TWO_HOURS` | A short 8-character code, made for a clerk to type |
| `TWENTY_FOUR_HOURS`, `FORTY_EIGHT_HOURS`, `SEVENTY_TWO_HOURS`, `THIRTY_DAYS` | A UUID, made for pushing to a device rather than typing |

**On an account with more than one location, `location_id` is required**, and it binds the
device to that location for good. Sessions don't carry a location — they inherit the
device's.

Any metadata you attach is carried onto the device record when pairing completes. Tag each
enrollment with its store or lane, and you can filter devices by it later.

### 2. Hand the code to the clerk

How it reaches them is yours to choose. The clerk types it into the Kustom POS app, which
registers the device against your account and receives its own bearer token. Nothing more
is needed from your backend.

### 3. Manage the device afterwards

The enrolled device has a stable `device_id`, which is what you send when you
[create a session](/in-person/take-a-payment/). From here you can
[list](/api/in-person-payments/list-devices/), [update](/api/in-person-payments/update-device/)
and [deregister](/api/in-person-payments/deregister-device/) devices.

**Name each device when you update it.** Nothing in the API says whether a device is a
phone or a Kustom terminal, so a `name` such as "Terminal, till 2" is how you tell them
apart in the device list.

**Deregistering revokes the device's bearer token immediately.** The clerk has to enroll
it again before it can take another payment.

## Check that it works

The device appears in [`GET /ipp/v1/devices`](/api/in-person-payments/list-devices/),
carrying the metadata you set on its enrollment. The enrollment itself has moved to
`CONSUMED`:

| Status | Meaning |
|---|---|
| `PENDING` | Created, and no clerk has entered it yet |
| `CONSUMED` | A device registered with it |
| `EXPIRED` | Not used before `expires_at`. Create a new enrollment |
| `CANCELLED` | Deleted with [`DELETE /ipp/v1/enrollments/{enrollment_id}`](/api/in-person-payments/delete-enrollments/) |

`CANCELLED` and `EXPIRED` enrollments are left out of
[list results](/api/in-person-payments/list-enrollments/).

## Troubleshooting

**The `/ipp/v1` endpoints return `404` or `403`.** In-person payments isn't enabled on the
account. That's a conversation with your Kustom representative, not a code fix.

**The clerk's code is rejected.** It expired or was already used — codes are single-use.
Create a new enrollment.

**The device needs to move to another location.** A device stays bound to the location it
enrolled into. Deregister it and enroll it again with the new `location_id`.

## Related

- [Take a payment](/in-person/take-a-payment/) — send a cart to the device you just enrolled
- [Test without hardware](/in-person/test-without-hardware/) — a simulated device for Playground
- [Enroll a managed fleet](/in-person/enroll-a-managed-fleet/) — the same enrollment, pushed through your MDM
