Flow · 9 steps

Set up a station and unlock it with a PIN

A station is a device kept signed in to one job — pick & pack, receiving, a stocktake, the register — at one site, unlocked by the people who work it with their own station PIN. The session that follows is theirs, narrowed to the station's view. Enrolling, renaming and revoking a station are a signed-in manager's, from their own sign-in session; the device then speaks for itself with the credential its enrolment handed it. A person in a personal view (reporting, the ops board) opens it the same way, from their sign-in.

Services involved

A filled dot is a read; a ring is a call that changes something.

  • Auth: https://auth.getmanifold.io

Every call carries Authorization: Bearer $MANIFOLD_TOKEN unless its step says otherwise (getting a token). Run a flow in your sandbox, not your live organization: see Before you start.

1 Set your station PIN

The owner chooses the PIN they will unlock stations with in this organization: six digits or more for an owner or admin, hashed at rest and never shown again.

PUT /api/auth/station-pins/org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d Auth

Sent as the person's own sign-in session.

Request · application/json
{
  "pin": "482913"
}
Response
{
  "organizationId": "org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "userId": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c",
  "setAt": "2026-08-17T09:00:00.000Z"
}

From your answer, later steps send userId (here usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c) as {userId}.

Records auth.station-pin-set.

2 Enrol the packing bench

A device at the main warehouse becomes the pick & pack station "Bench 2". The answer carries the device's credential once; the device keeps it.

POST /api/auth/stations/org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d Auth

Sent as the person's own sign-in session.

Request · application/json
{
  "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "view": "pick-pack",
  "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
  "name": "Bench 2"
}
Response
{
  "station": {
    "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
    "view": "pick-pack",
    "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
    "name": "Bench 2",
    "enrolledAt": "2026-08-17T09:00:00.000Z",
    "enrolledBy": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c"
  },
  "credential": "stc_Qm9vdGgtMi1pbi10aGUtd2FyZWhvdXNl"
}

From your answer, later steps send station.stationId (here stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d) as {stationId} and credential (here stc_Qm9vdGgtMi1pbi10aGUtd2FyZWhvdXNl) as {credential}.

Records auth.station-enrolled.

3 Enrol it again

Idempotent on stationId: the same enrolment by the same person answers the station it made, and appends nothing.

POST /api/auth/stations/org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d Auth

Sent as the person's own sign-in session.

Request · application/json
{
  "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "view": "pick-pack",
  "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
  "name": "Bench 2"
}

What the answer holds: the operation's example.

Records nothing.

4 List the stations

Settings › Stations: every station the manager may manage, newest first.

GET /api/auth/stations/org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d Auth

Sent as the person's own sign-in session.

Response
{
  "stations": [
    {
      "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
      "view": "pick-pack",
      "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
      "name": "Bench 2",
      "enrolledAt": "2026-08-17T09:00:00.000Z",
      "enrolledBy": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c"
    }
  ]
}

5 Rename it

What the device and Settings › Stations call it.

PATCH /api/auth/stations/org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d/stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d Auth

Sent as the person's own sign-in session.

Request · application/json
{
  "name": "Packing bench 2"
}
Response
{
  "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "view": "pick-pack",
  "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
  "name": "Packing bench 2",
  "enrolledAt": "2026-08-17T09:00:00.000Z",
  "enrolledBy": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c"
}

Records auth.station-renamed.

6 Show the lock screen

The device, under its own credential, reads who may unlock it: the organization's active members with a station PIN whose roles open its view.

POST /api/auth/station/roster Auth

Request · application/json
{
  "credential": "stc_Qm9vdGgtMi1pbi10aGUtd2FyZWhvdXNl"
}
Response
{
  "station": {
    "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
    "view": "pick-pack",
    "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
    "name": "Packing bench 2",
    "enrolledAt": "2026-08-17T09:00:00.000Z",
    "enrolledBy": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c"
  },
  "people": [
    {
      "userId": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c",
      "name": "Avery Lin"
    }
  ]
}

Records nothing.

7 Unlock it with the PIN

The owner taps their name and types their PIN. The answer is a short-lived token that is theirs, in the pick & pack view at this station's site.

POST /api/auth/station/unlock Auth

Request · application/json
{
  "method": "pin",
  "credential": "stc_Qm9vdGgtMi1pbi10aGUtd2FyZWhvdXNl",
  "userId": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c",
  "pin": "482913"
}
Response
{
  "token": "eyJhbGciOiJFZERTQSJ9.eyJ2aWV3IjoicGljay1wYWNrIn0.c3RhdGlvbi1zZXNzaW9u",
  "expiresAt": "2026-08-17T09:15:00.000Z",
  "tenantId": "org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "userId": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c",
  "view": "pick-pack",
  "station": {
    "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
    "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d"
  }
}

Records auth.station-unlocked.

8 Open the reporting view

A personal view needs no device: the signed-in person exchanges their session for a token in it. Appends nothing — the sign-in was journalled when it happened.

POST /api/auth/views/reporting/session Auth

Sent as the person's own sign-in session.

Response
{
  "token": "eyJhbGciOiJFZERTQSJ9.eyJ2aWV3IjoicmVwb3J0aW5nIn0.dmlldy1zZXNzaW9u",
  "expiresAt": "2026-08-17T09:15:00.000Z",
  "tenantId": "org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "userId": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c",
  "view": "reporting"
}

Records nothing.

9 Revoke it

The bench is retired: its credential unlocks nothing from now on. Final — the device is enrolled again as a new station.

POST /api/auth/stations/org_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d/stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d/revoke Auth

Sent as the person's own sign-in session.

Response
{
  "stationId": "stn_01a1586e-f9f6-7a8b-9c7d-6e5f4a3b2c1d",
  "view": "pick-pack",
  "locationId": "loc_01a15852-46d1-7a3b-9c0d-1e2f3a4b5c6d",
  "name": "Packing bench 2",
  "enrolledAt": "2026-08-17T09:00:00.000Z",
  "enrolledBy": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c",
  "revokedAt": "2026-08-17T09:00:00.000Z",
  "revokedBy": "usr_01a15869-1d2e-7f3a-8b4c-5d6e7f8a9b0c"
}

Records auth.station-revoked.

What a recorded fact is: Facts and the journal. Why a repeated step changes nothing: Idempotency and retries.