Using the Staff API

API OAuth Staff Management Staff CRUD Android iOS

Purpose of this guide

This guide covers how to create, retrieve, update, and delete the staff (employees) under a business account using ReceiptRoller's Staff API. It is the entry point for working with staff data — for shift management apps, per-POS-operator sales apps, HR system integrations, and more.

Prerequisites

  • You have obtained an access token via the OAuth 2.0 authorization code flow
  • Your app's scopes include store.staff.read (read) / store.staff.write (create, update, delete)
  • You know the business account ID (UUID) (Listing business accounts, stores, and POS terminals)
  • Base URL: https://receiptroller.io

Endpoints

MethodPathPurposeRequired scope
GET/api/v1/staffList / search staffstore.staff.read
GET/api/v1/staff/{staffId}Detail of one personstore.staff.read
POST/api/v1/staffCreatestore.staff.write
PUT/api/v1/staff/{staffId}Updatestore.staff.write
DELETE/api/v1/staff/{staffId}Delete (soft delete)store.staff.write

1. Retrieve the staff list

GET /api/v1/staff?organizationId={organizationId}
Authorization: Bearer {access_token}

Query parameters (all optional, AND-combined)

  • storeId — only staff assigned to that store (staff assigned to all stores are also included)
  • position — filter by role/title (exact match)
  • employmentType — FullTime / PartTime / Contract / Other
  • status — Active / Inactive / Pending
  • search — partial search by name (including kana), employee number, or reference ID
  • includeDeleted — whether to include deleted records (default false)

Response example

{
  "organizationId": "a04507de-043a-4b47-b0a3-6204562f6e20",
  "staff": [
    {
      "id": "stf-001",
      "organizationId": "a04507de-...",
      "employeeNumber": "E-0001",
      "referenceId": "TM_xyz",
      "userId": "",
      "name": {
        "first": "Taro",
        "last": "Tanaka",
        "firstKana": "タロウ",
        "lastKana": "タナカ",
        "display": "Taro Tanaka"
      },
      "role": {
        "position": "Store manager",
        "employmentType": "FullTime",
        "isOwner": false
      },
      "status": "Active",
      "contact": { "phone": "090-1234-5678", "email": "tanaka@example.com" },
      "hr": { "hireDate": "2024-04-01T00:00:00Z", "dateOfBirth": "1990-05-15T00:00:00Z", "address": "Shibuya-ku, Tokyo..." },
      "pay": {
        "hourlyRate": 1800,
        "isOvertimeExempt": true,
        "tipEligible": true,
        "jobs": [
          {
            "jobTitle": "Store manager",
            "payType": "HOURLY",
            "hourlyRate": 1800,
            "annualRate": 0,
            "weeklyHours": 40,
            "locationIds": ["store-A"]
          },
          {
            "jobTitle": "Cashier",
            "payType": "HOURLY",
            "hourlyRate": 1200,
            "annualRate": 0,
            "weeklyHours": 10,
            "locationIds": ["store-B"]
          }
        ]
      },
      "assignments": {
        "storeIds": ["store-A", "store-B"],
        "allLocations": false
      },
      "emergency": { "name": "Hanako Tanaka", "phone": "090-...", "relation": "Spouse" },
      "integrations": { "squareTeamMemberId": "TM_xyz", "smaregiStaffId": "" },
      "profileImageUrl": "https://...",
      "notes": "",
      "createdAt": "2024-04-01T09:00:00Z",
      "updatedAt": "2026-06-02T10:30:00Z"
    }
  ],
  "totalCount": 1
}

2. Retrieve the detail of one person

GET /api/v1/staff/{staffId}?organizationId={organizationId}
Authorization: Bearer {access_token}

Returns 404 if the staff member does not belong to the specified business account.

3. Create

POST /api/v1/staff?organizationId={organizationId}
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "displayName": "Hanako Sato",
  "firstName": "Hanako",
  "lastName": "Sato",
  "firstNameKana": "ハナコ",
  "lastNameKana": "サトウ",
  "employeeNumber": "E-0002",
  "position": "Cashier",
  "employmentType": "PartTime",
  "status": "Active",
  "phone": "080-9876-5432",
  "email": "sato@example.com",
  "hourlyRate": 1200,
  "hireDate": "2026-06-01",
  "isOvertimeExempt": false,
  "tipEligible": true,
  "assignedStoreIds": "store-001,store-002",
  "isAssignedToAllLocations": false,
  "jobAssignmentsJson": "[{\"jobTitle\":\"Cashier\",\"payType\":\"HOURLY\",\"hourlyRate\":1200,\"weeklyHours\":20,\"locationIds\":[\"store-001\"]}]"
}

Points

  • Either displayName, or firstName + lastName, is required
  • Even if you include organizationId in the request body, it is ignored. The business account resolved from the token/query is always used
  • If there are multiple jobs, pass an array in jobAssignmentsJson. For a single job, just position + hourlyRate is fine

4. Update

PUT /api/v1/staff/{staffId}?organizationId={organizationId}
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "displayName": "Hanako Sato",
  "phone": "080-9876-5432",
  "hourlyRate": 1300,
  "status": "Active"
}

Overwrites with the fields you send (a full replacement, not a partial update). For fields whose values you want to keep, resend the existing values along with the change.

5. Delete (soft delete)

DELETE /api/v1/staff/{staffId}?organizationId={organizationId}
Authorization: Bearer {access_token}

Points

  • The response is 204 No Content
  • Because it is a soft delete, resolving the staff ID from past shift logs or POS transactions still works
  • Deleted staff are not included in list or search results

Correspondence with Square Team Member

This API's fields are compatible with the Square Team Members API. On a business account where the Square integration is enabled, integrations.squareTeamMemberId is set automatically, and changes on Square are also reflected into ReceiptRoller (planned for implementation in Phase 3, t-e9a2f482).

Fields originating from Square

  • referenceId ⇔ Square reference_id
  • role.isOwner ⇔ Square is_owner
  • status ⇔ Square status (ACTIVE → "Active" / INACTIVE → "Inactive")
  • assignments.allLocations ⇔ Square assignment_type: ALL
  • pay.jobs ⇔ Square wage_setting.job_assignments
  • pay.isOvertimeExempt ⇔ Square is_overtime_exempt
  • pay.tipEligible ⇔ Square tip_eligible

Fields unique to ReceiptRoller (not present in / not synced from Square)

  • Name kana (firstNameKana, lastNameKana)
  • Hire date, date of birth, address
  • Emergency contact (emergency.*)
  • Employment type (FullTime / PartTime / Contract / Other)
  • Profile photo
  • Notes, employee number, Smaregi integration ID

Typical flow (mobile app)

  1. Obtain an access token via OAuth → scopes include store.staff.read and store.staff.write
  2. Select a business account with GET /api/v1/me/organizations
  3. Show GET /api/v1/staff?storeId=... paginated on the staff list screen
  4. Add a new staff member with POST /api/v1/staff
  5. On the edit screen, GET /api/v1/staff/{id}PUT /api/v1/staff/{id}
  6. For offboarding, DELETE /api/v1/staff/{id} (or PUT with status: "Inactive")

Error responses

StatusMeaningWhat to do
401 UnauthorizedAccess token invalid / expiredRe-obtain with the refresh token
403 ForbiddenMissing the required scope / not a member of the business accountCheck the scope and the selected business account
400 Bad RequestMissing required field (displayName or firstName/lastName)Review the request body
404 Not FoundThe staff ID does not exist in that business accountRe-fetch from the list

Related information

Published: 2026-06-03 Updated: 2026-07-05
このトピックについて
開発者API
機能の詳細を見る
Tags
API (22) OAuth (15) Android (10) iOS (9) Webhook (6) Troubleshooting (5) api (5) App registration (4) POS Integration (4) Reference (4)
Related articles