Stitchflow
Clover logo

Clover User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 9, 2026

Summary and recommendation

Clover exposes a REST API at https://api.clover.com/v3/merchants/{mId} for programmatic employee lifecycle management. Authentication uses OAuth 2.0 authorization code flow; tokens are merchant-scoped, do not expire by default unless revoked, and do not cross between sandbox (sandbox.dev.clover.com) and production environments.

The EMPLOYEES_R and EMPLOYEES_W scopes are required for read and write operations respectively; MERCHANT_R is needed for role metadata.

There is no SCIM 2.0 implementation on any plan - all provisioning must go through the proprietary REST API, which means any identity graph built on top of Clover requires custom mapping between Clover's employee id (UUID) and your IdP or HR system's user identifier.

API quick reference

Has user APIYes
Auth methodOAuth 2.0 (authorization code flow); access token passed as Bearer token in Authorization header or as token query parameter
Base URLOfficial docs
SCIM availableNo
SCIM plan requiredNot available on any plan

Authentication

Auth method: OAuth 2.0 (authorization code flow); access token passed as Bearer token in Authorization header or as token query parameter

Setup steps

  1. Register a developer account at https://sandbox.dev.clover.com and create an app in the Developer Dashboard.
  2. Configure your app's redirect URI and requested permissions (scopes) in the app settings.
  3. Direct the merchant to the Clover OAuth authorization URL: https://sandbox.dev.clover.com/oauth/authorize?client_id={APP_ID}&redirect_uri={REDIRECT_URI}
  4. After merchant approval, exchange the returned authorization code for an access token via POST to https://sandbox.dev.clover.com/oauth/token.
  5. Store the returned access token and use it as a Bearer token in subsequent API requests. Tokens are merchant-scoped and do not expire by default unless revoked.

Required scopes

Scope Description Required for
EMPLOYEES_R Read employee records for the merchant. GET /employees, GET /employees/{empId}
EMPLOYEES_W Create, update, and delete employee records. POST /employees, PUT /employees/{empId}, DELETE /employees/{empId}
MERCHANT_R Read merchant-level information including roles. GET /merchants/{mId} and related merchant metadata

User object / data model

Field Type Description On create On update Notes
id string Unique employee identifier (UUID). system-generated immutable Used as path parameter in employee-specific endpoints.
name string Full display name of the employee. required optional
nickname string Short name shown on receipts and POS UI. optional optional
email string Employee email address. optional optional Used for Clover account invitation if employee does not already have one.
pin string Numeric PIN used to clock in/out and authenticate at POS. optional optional Write-only; not returned in GET responses.
role string (enum) Predefined role: OWNER, ADMIN, MANAGER, EMPLOYEE. optional (defaults to EMPLOYEE) optional OWNER role cannot be assigned via API.
roles object (reference) Reference to a custom role object if custom roles are used. optional optional Custom roles must be created separately via /roles endpoint.
isOwner boolean Indicates if the employee is the merchant owner. system-set immutable
claimedTime integer (epoch ms) Timestamp when the employee claimed their Clover account. system-set immutable
deletedTime integer (epoch ms) Soft-delete timestamp; non-null means employee is deleted. system-set system-set
customId string Merchant-defined external identifier for the employee. optional optional
inviteSent boolean Whether a Clover account invitation email has been sent. system-set read-only

Core endpoints

List all employees

  • Method: GET
  • URL: https://api.clover.com/v3/merchants/{mId}/employees
  • Watch out for: Deleted employees are excluded by default. Use ?filter=deletedTime>0 to include them.

Request example

GET /v3/merchants/{mId}/employees?limit=100&offset=0
Authorization: Bearer {access_token}

Response example

{
  "elements": [
    {"id":"ABC123","name":"Jane Doe","role":"EMPLOYEE","email":"jane@example.com"}
  ],
  "href": "https://api.clover.com/v3/merchants/{mId}/employees"
}

Get single employee

  • Method: GET
  • URL: https://api.clover.com/v3/merchants/{mId}/employees/{empId}
  • Watch out for: Returns 404 if employee was hard-deleted or belongs to a different merchant.

Request example

GET /v3/merchants/{mId}/employees/{empId}
Authorization: Bearer {access_token}

Response example

{
  "id": "ABC123",
  "name": "Jane Doe",
  "role": "EMPLOYEE",
  "email": "jane@example.com",
  "isOwner": false
}

Create employee

  • Method: POST
  • URL: https://api.clover.com/v3/merchants/{mId}/employees
  • Watch out for: PIN is accepted on create but never returned in subsequent GET calls. Email triggers an invite only if the employee does not already have a Clover account.

Request example

POST /v3/merchants/{mId}/employees
Authorization: Bearer {access_token}
Content-Type: application/json

{"name":"John Smith","email":"john@example.com","role":"EMPLOYEE","pin":"1234"}

Response example

{
  "id": "XYZ789",
  "name": "John Smith",
  "role": "EMPLOYEE",
  "email": "john@example.com"
}

Update employee

  • Method: PUT
  • URL: https://api.clover.com/v3/merchants/{mId}/employees/{empId}
  • Watch out for: Clover uses PUT (full-replace semantics) not PATCH. Omitting optional fields may clear them depending on API version.

Request example

PUT /v3/merchants/{mId}/employees/{empId}
Authorization: Bearer {access_token}
Content-Type: application/json

{"name":"John A. Smith","role":"MANAGER"}

Response example

{
  "id": "XYZ789",
  "name": "John A. Smith",
  "role": "MANAGER"
}

Delete employee

  • Method: DELETE
  • URL: https://api.clover.com/v3/merchants/{mId}/employees/{empId}
  • Watch out for: Cannot delete the merchant owner (isOwner=true). Returns 400 if attempted.

Request example

DELETE /v3/merchants/{mId}/employees/{empId}
Authorization: Bearer {access_token}

Response example

HTTP 200 OK
(empty body)

List roles

  • Method: GET
  • URL: https://api.clover.com/v3/merchants/{mId}/roles
  • Watch out for: Custom roles are merchant-specific. The systemRole field maps to the base permission tier.

Request example

GET /v3/merchants/{mId}/roles
Authorization: Bearer {access_token}

Response example

{
  "elements": [
    {"id":"ROLE1","name":"Cashier","systemRole":"EMPLOYEE"}
  ]
}

Get current authenticated employee

  • Method: GET
  • URL: https://api.clover.com/v3/merchants/{mId}/employees/current
  • Watch out for: Returns the employee associated with the OAuth token, not necessarily an admin. Useful for identity verification.

Request example

GET /v3/merchants/{mId}/employees/current
Authorization: Bearer {access_token}

Response example

{
  "id": "ABC123",
  "name": "Jane Doe",
  "role": "ADMIN",
  "isOwner": false
}

Rate limits, pagination, and events

  • Rate limits: Clover does not publish explicit per-plan rate limit numbers in official documentation. Throttling is enforced server-side; excessive requests result in HTTP 429 responses.
  • Rate-limit headers: No
  • Retry-After header: No
  • Rate-limit notes: Official docs do not specify header names or numeric limits. Implement exponential backoff on HTTP 429.
  • Pagination method: offset
  • Default page size: 100
  • Max page size: 1000
  • Pagination pointer: offset and limit query parameters; e.g., ?limit=100&offset=0
Plan Limit Concurrent
All plans (sandbox) Not publicly documented; sandbox is more restrictive than production 0
All plans (production) Not publicly documented 0
  • Webhooks available: Yes
  • Webhook notes: Clover supports webhooks for merchant data change events. Apps register a webhook URL in the Developer Dashboard. Clover sends HTTP POST notifications when subscribed entities change.
  • Alternative event strategy: Poll GET /employees with a timestamp filter (modifiedTime) for environments where webhooks are not feasible.
  • Webhook events: EMPLOYEE_CREATE, EMPLOYEE_UPDATE, EMPLOYEE_DELETE

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: Not available on any plan
  • Endpoint: Not documented

Limitations:

  • Clover does not implement SCIM 2.0.
  • No IdP (Okta, Entra, Google Workspace, OneLogin) integration documented.
  • Employee provisioning must be done via the proprietary REST API.

Common scenarios

Three core automation scenarios are well-supported by the API. For provisioning, POST /v3/merchants/{mId}/employees with name, email, pin, and a roles:{id} reference fetched from GET /v3/merchants/{mId}/roles; omitting the roles object silently defaults the employee to the EMPLOYEE system role.

For roster sync, paginate GET /employees with limit=1000 and offset increments, then use the modifiedTime filter for incremental runs - deleted employees are excluded from default responses and must be queried separately with filter=deletedTime>0 to detect deprovisioned users.

For deprovisioning, confirm isOwner=false before calling DELETE /employees/{empId}; the API returns HTTP 400 if you attempt to delete the merchant owner, and deletion is immediate and irreversible with no archive state.

Provision a new employee with a custom role

  1. Obtain a merchant-scoped OAuth 2.0 access token via the authorization code flow.
  2. GET /v3/merchants/{mId}/roles to retrieve available custom role IDs.
  3. POST /v3/merchants/{mId}/employees with name, email, pin, and roles:{id} body to create the employee.
  4. Clover automatically sends an invitation email to the provided address if the employee has no existing Clover account.

Watch out for: If the roles object is omitted, the employee defaults to the EMPLOYEE system role. Custom role IDs must be fetched first; they are not predictable.

Sync employee roster to an external HR system

  1. GET /v3/merchants/{mId}/employees?limit=1000&offset=0 to retrieve all active employees.
  2. Paginate using offset increments until the elements array is empty.
  3. Map Clover employee id to the external system's user identifier.
  4. For incremental sync, filter by modifiedTime: GET /v3/merchants/{mId}/employees?filter=modifiedTime>{lastSyncEpochMs}

Watch out for: Deleted employees are excluded from default responses. Query with filter=deletedTime>0 separately to detect deprovisioned users.

Deprovision a departing employee

  1. GET /v3/merchants/{mId}/employees to find the employee's id by email or name.
  2. Confirm isOwner=false before proceeding (owner cannot be deleted via API).
  3. DELETE /v3/merchants/{mId}/employees/{empId} to remove the employee.
  4. Verify removal by confirming HTTP 200 response and re-querying the employee ID (expect 404).

Watch out for: Deletion is immediate and cannot be undone via the API. The employee loses POS access instantly but any in-progress sessions on hardware may not terminate until the device syncs.

Why building this yourself is a trap

Several non-obvious behaviors create integration risk. PUT semantics are used for updates - not PATCH - so omitting optional fields on an update call may silently clear them depending on API version.

PIN values are write-only: accepted on POST but never returned in any GET response, which complicates any sync logic that tries to validate existing PIN state. Rate limits are not documented numerically; the API returns HTTP 429 on throttle with no Retry-After header, so exponential backoff must be implemented defensively.

Webhook delivery for EMPLOYEE_CREATE, EMPLOYEE_UPDATE, and EMPLOYEE_DELETE events is not guaranteed - Clover's own documentation recommends reconciling via polling against modifiedTime if webhook events are missed. Finally, multi-merchant integrations must manage one OAuth token per merchant; there is no org-level token or tenant-scoped credential model.

Automate Clover workflows without one-off scripts

Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 9, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste