Users Data
Field reference, snapshot semantics, and examples for sending user lists to Harmony
A users push tells Harmony who has access to an application. It answers questions like "who holds a paid seat", "who still has an account after leaving", and "which roles are granted where".
This page covers the users endpoint in full. For setup, see Bring Your Own App.
The most important rule: a push is a snapshot
Every users push is a complete replacement of the application's user list — not a list of changes.
Harmony compares each push against what it already knows and makes reality match your push. Users present in your push are created or updated. Users absent from your push are removed from Harmony.
Push 1: alice, bob, carol → Harmony shows: alice, bob, carol
Push 2: alice, carol → Harmony shows: alice, carol (bob removed)
Push 3: alice, bob, carol → Harmony shows: alice, bob, carol (bob restored)This is what makes offboarding work — when someone loses access in the application, they disappear from your next push and Harmony reflects that automatically, with no delete call required.
Always send every current user, every time. Sending only the users who changed since your last push will remove everyone else. If your script filters, paginates, or short-circuits on an error, make sure the final result is still the complete list.
Endpoint
POST https://external.harmony.io/custom-push/v1/users
Authorization: Bearer <access key>
Content-Type: application/jsonRequest body
external_app_id
string
Yes
The App ID you registered in Harmony. 1–200 characters, A–Z a–z 0–9 . _ -. Must be identical in every push for this application.
users
array
Yes
Between 1 and 100 user objects. See below.
snapshot_token
string
No
Only used when a single user list spans more than one request. See Sending more than 100 users.
schema_version
string
No
Defaults to "1.0". Reserved for future versions of this API.
User fields
Each object in the users array describes one account in the application.
external_id
string
Yes
1–255 chars
The application's own identifier for this account. Use whatever the application calls its user ID — a UUID, a numeric ID, a username. It identifies the row across pushes, so it must be stable for a given person.
email
string
Yes
Valid email, max 254 chars
The user's email address. Harmony uses this to match the account to an employee record, which is what links this application to the rest of your data. Accounts without a usable email address cannot be matched and are not retained.
name
string
No
255 chars
Display name, shown in Harmony's user lists. If omitted, Harmony shows the email address instead.
status
string
No
See values below
The account's state in the application. Defaults to active.
role
string
No
255 chars
The role this user holds, in the application's own vocabulary — Billing Admin, Editor, read-only. Do not translate it into Harmony terms; access reviews are more useful when they show what the application actually says.
license_tier
string
No
paid, free, unknown
Whether this account consumes a billable seat. Omit if you genuinely do not know — do not guess.
plan_name
string
No
255 chars
The plan or SKU name attached to this user, for example Enterprise or Business Plus.
metadata
object
No
1 KB serialized
Any additional key/value data you want to carry along. Free-form JSON.
status values
active
The account is in normal use. This is the default.
inactive
The account exists but is deactivated or dormant.
pending
The account is invited or provisioned but not yet accepted.
suspended
The account is temporarily blocked by an administrator.
expired
The account's access has lapsed.
Reporting a user as inactive is not the same as omitting them. An inactive user still appears in Harmony, still counts toward the application's user list, and still shows up in access reviews — which is usually what you want, since a dormant account is still an account. Omitting a user removes them entirely.
license_tier values
paid
The account consumes a billable seat.
free
The account is on a free or included tier.
unknown
The tier is not determinable from the application's data.
Reporting license_tier is what makes license optimization possible — Harmony can only tell you about wasted spend if it knows which seats cost money.
Response
202 Accepted:
batch_id
A unique identifier for this request. Useful when contacting support about a specific push.
snapshot_id
The identifier of the user list this push opened or contributed to. You only need it when sending more than 100 users.
accepted_rows
How many user rows were accepted.
For error responses, see the API reference.
Examples
A minimal push
Only the two required fields per user:
A fully populated push
Every field in use:
A complete sync script
Sending more than 100 users
A single request carries at most 100 users. For larger applications, split the list across several requests that Harmony joins into one user list.
First request — send the first 100 users and omit
snapshot_token. Harmony opens a new user list and returns itssnapshot_id.Every following request — send the next 100 users and set
snapshot_tokento thesnapshot_idyou received from the first request.When the last request succeeds, the list is complete and replaces the previous one.
Rules for multi-batch pushes:
snapshot_tokenmust be a value Harmony gave you. You cannot invent one.Complete the full sequence within an hour. A user list left half-sent for longer is rejected when you try to continue it, which leaves it permanently incomplete.
Send each user exactly once across the whole sequence. Sending the same user twice under one list inflates seat counts until the next clean push.
If any request in the sequence fails, do not resume. Start over: send the complete user list again from the beginning, without a snapshot_token. This opens a fresh list that replaces the incomplete one.
Resuming after a failure — or abandoning a half-sent list — leaves Harmony holding a partial user list that it treats as complete, which removes every user that never made it.
Recommended push frequency
Push whenever the application's user list changes, or on a fixed schedule if you cannot detect changes. Daily is a good default. Pushing more often is safe — each push simply replaces the previous list.
There is no penalty for pushing an unchanged list.
See also
Usage data — reporting what users actually did
API reference — errors, retries, and limits
Last updated
Was this helpful?
