Profiles API — Overview
Reusable bundles of restrictions, feature toggles and tag defaults that you assign to team members per event — the configuration layer behind the Qflow check-in app.
A profile is a named, reusable bundle of everything that governs how the check-in app behaves for a team member: which capabilities are locked (restrictions), which features are on and whether the member can change them on the device (settings), and the default filter / check-in / statistics tags. Build a profile once — "Door Scanner", "VIP Desk", "Roaming Supervisor" — then assign it to one, several, or every team member working an event.
Profiles are the configuration layer that sits on top of Team: Team decides who works an event, Profiles decides what they can do once they're there.
URL pattern
All endpoints on this page live under:
https://api.qflowhub.io/profiles/v1/<endpoint>
Every request needs both an OAuth bearer token AND an Ocp-Apim-Subscription-Key header — see Authentication.
What it does
Profiles
Create, read, update, delete and duplicate the reusable profile bundle — restrictions, settings and tag defaults in one object.
Restrictions & settings
The full catalogue of restriction codes and feature toggles a profile can carry, including the two that take a value (sign-out PIN, guest cap).
Assignment
Assign a profile to one, many, or all team members on an event — explicit fan-out — plus per-event tag overrides.
Resolved config
Preview the effective configuration a member's device receives after the profile and any overrides are merged.
Quick start — build a door profile and assign it
Create a profile that locks the device down to scanning and hides everything else:
curl -X POST 'https://api.qflowhub.io/profiles/v1' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{
"name": "Door Scanner",
"restrictions": ["restrict_settings", "restrict_stats", "restrict_signout 4821"],
"settings": { "ContinuousScan": { "value": true, "locked": true } }
}'
Save the returned id, then assign it to two door staff for an event:
curl -X POST 'https://api.qflowhub.io/profiles/v1/assign' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{
"profileId": "<profileId>",
"eventId": "<eventId>",
"teamMemberIds": ["<member1>", "<member2>"]
}'
Both devices pick up the profile on their next sync. The members must already be assigned to the event via the Team API first.
Read in this order
- Profiles — the profile object and its CRUD lifecycle.
- Restrictions & settings — the catalogue of what a profile can carry.
- Assignment — fan out a profile across an event's team.
- Resolved config — preview the merged result a device receives.
For full request/response schemas + try-it, see the auto-generated API Reference.
Profiles API — Profiles
The profile object and its lifecycle — create, read, update, delete and duplicate the reusable bundle of restrictions, settings and tags.
A profile is owned by your account and reused across events. It holds four things: a name, a set of restrictions, a map of settings (feature toggles), and three lists of default tags. Nothing in a profile references an event or a team member — that link is made separately when you assign it.
The profile object
{
"id": "8f2c…",
"name": "Door Scanner",
"restrictions": ["restrict_settings", "restrict_stats", "restrict_signout 4821"],
"settings": {
"ContinuousScan": { "value": true, "locked": true },
"OfflineMode": { "value": false, "locked": false }
},
"filterTags": [{ "name": "VIP", "type": "tickettype" }],
"checkinTags": [{ "name": "Checked-Door-A", "type": "tag" }],
"statsTags": [],
"created": "2026-06-16T09:00:00Z"
}
restrictions— an array of restriction codes; two may carry an inline value. See Restrictions & settings.settings— feature toggles keyed by name, each withvalue(on/off) andlocked(whether the member can change it on the device). The tag-lock flagsFilterTagsLocked,CheckinTagsLockedandStatsTagsLockedlive here too.filterTags/checkinTags/statsTags— name + type pairs, matched against the event's own tags when the profile is assigned.
id and created are server-assigned and ignored on input.
Lifecycle
List
GET /profiles/v1 — every profile on your account, newest first.
Get one
GET /profiles/v1/{id} — a single profile by id.
Create
POST /profiles/v1 — a new, unassigned profile.
Update
PUT /profiles/v1/{id} — replace the restrictions, settings and tags.
Delete
POST /profiles/v1/delete — delete the profile and clear it from every member.
Duplicate
POST /profiles/v1/duplicate — copy a profile as a starting point for a variant.
Update re-syncs every assigned device
PUT /profiles/v1/{id} is a full replace of the bundle — send the complete restrictions, settings and tag lists you want, not a delta. Every device the profile is currently assigned to is re-synced immediately, so the change lands without waiting for the next event.
Update is idempotent: sending the same body twice leaves the same end state.
Delete
Delete takes the id in the body so callers without HTTP DELETE support work:
curl -X POST 'https://api.qflowhub.io/profiles/v1/delete' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{ "id": "<profileId>" }'
It removes the profile and clears it from every team member it was assigned to; those devices re-sync and drop the profile. A repeat delete of an already-deleted profile returns 404.
Duplicate
Duplicate creates an unassigned copy with the same restrictions, settings and tags, named "<original> (copy)". Use it to branch a one-off variant for a single event without touching the shared profile:
curl -X POST 'https://api.qflowhub.io/profiles/v1/duplicate' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{ "id": "<profileId>" }'
Next
- Restrictions & settings — what you can put in
restrictionsandsettings. - Assignment — get the profile onto an event's team.
Profiles API — Restrictions & settings
The catalogue of restriction codes and feature toggles a profile can carry, including the two restrictions that take a value.
A profile's behaviour comes from two fields: restrictions (capabilities you lock down) and settings (feature toggles you preset). This page is the reference for both.
Restrictions
restrictions is an array of codes. Most are simple on/off locks — including the code in the array turns the lock on:
| Code | Locks |
|---|---|
restrict_settings |
Access to the in-app settings screen |
restrict_filtering |
Changing the guest-list filter |
restrict_switchevents |
Switching to a different event |
restrict_checkout |
Checking guests back out |
restrict_changeguestinfo |
Editing guest details |
restrict_overrideblock |
Checking in a blocked guest |
restrict_scanneronly |
The device to the scan window only |
restrict_stats |
Viewing the statistics screen |
Restrictions that take a value
Two restrictions accept an inline value — the code, a single space, then the value:
| Code | Value | Example |
|---|---|---|
restrict_signout |
A PIN required to sign out. Omit the value to lock sign-out entirely. | restrict_signout 4821 |
restrict_addguest |
The maximum number of guests the member may add. Omit the value to block adding guests entirely. | restrict_addguest 5 |
"restrictions": ["restrict_settings", "restrict_signout 4821", "restrict_addguest 5"]
restrict_signout 4821 lets a supervisor still sign the device out by entering 4821; bare restrict_signout blocks sign-out outright. Likewise restrict_addguest 5 caps additions at five, while bare restrict_addguest blocks them.
Codes are validated on create and update — an unrecognised code returns 400. Only the codes in the tables above are accepted.
Settings
settings is a map keyed by setting name. Each entry has two booleans:
"settings": {
"ContinuousScan": { "value": true, "locked": true },
"OfflineMode": { "value": false, "locked": false }
}
value— the on/off state the device adopts.locked— whentrue, the member can't change it on the device; whenfalse, it's a suggested default they can still override.
Setting names are fixed identifiers in PascalCase — ContinuousScan, CheckoutMode, PrintOnScan, RepeatScan (scanning); SearchLastName, ShowGuestNotes, StartGuestList (guest-list display); OfflineMode, DisableSounds, NfcScanMode (device options); and the tag-lock flags FilterTagsLocked, CheckinTagsLocked, StatsTagsLocked. Use the name exactly as listed; the API canonicalises casing on save, so an unknown name is the only way to get it wrong.
Older app versions are covered automatically
Restrictions set on a profile are delivered to current apps through the resolved profile, and to older app versions that can't read profiles through the underlying control-message channel — so the same lock-downs apply on every device regardless of version, including the sign-out PIN and guest cap. You don't call anything extra; assigning the profile is enough.
Next
- Assignment — push the profile to an event's team.
- Resolved config — see the effective restrictions a device ends up with.
Profiles API — Assignment
Assign a profile to one, many, or all team members on an event — explicit fan-out — plus per-event tag overrides.
Assignment is the link between a profile and the team. It's always per (team member, event): the same profile can drive a dozen members on one event and a different set on another. You fan out explicitly — you list the member ids you want, and each gets its own assignment.
A team member must already be assigned to the event via the Team API before a profile assignment takes effect on their device.
Assign
POST /profiles/v1/assign — assign one profile to a list of members on an event:
curl -X POST 'https://api.qflowhub.io/profiles/v1/assign' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{
"profileId": "<profileId>",
"eventId": "<eventId>",
"teamMemberIds": ["<member1>", "<member2>", "<member3>"]
}'
- One member — pass a single id.
- Several — pass the subset you want.
- All — pass every member's id. There's no "whole event" shortcut by design: fan-out is explicit so the assignment set is always exactly what you sent.
Each (member, event) gets its own assignment, replacing any profile previously assigned to that member on that event. Every affected device syncs immediately. Assign is idempotent — sending the same request again is a no-op, so a retry after a timeout never double-assigns.
Unassign
POST /profiles/v1/unassign — clear the assignment for a list of members on an event:
curl -X POST 'https://api.qflowhub.io/profiles/v1/unassign' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{
"eventId": "<eventId>",
"teamMemberIds": ["<member1>", "<member2>"]
}'
Each member's device re-syncs and drops the profile, clearing its restrictions. Idempotent per member — clearing a member who has no assignment is a successful no-op.
List assignments
Two read endpoints, depending on which way you're looking:
By event
GET /profiles/v1/event/{eventId}/assignments — every member on the event that has a profile, with any tag overrides.
By profile
GET /profiles/v1/{id}/assignments — every (member, event) a profile is currently assigned to.
Per-event tag overrides
A profile carries default tags, but a single assignment can override them for one event without touching the shared profile — handy when "Door Scanner" needs a different filter at one venue:
curl -X PUT 'https://api.qflowhub.io/profiles/v1/assignment/tags' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
-H 'Content-Type: application/json' \
-d '{
"eventId": "<eventId>",
"teamMemberId": "<member1>",
"filterTags": [{ "name": "Table 1-20", "type": "tag" }]
}'
Send a tag list to override it; omit a field (or send null) to clear that override and fall back to the profile's own tags. Only the tag lists can be overridden per assignment — restrictions and settings always come from the profile.
Next
- Resolved config — confirm exactly what a member ends up with.
Profiles API — Resolved config
Preview the effective configuration a member's device receives after the profile and any per-event overrides are merged.
The resolved endpoint answers a single question: what will this member's device actually get on this event? It returns the assigned profile merged with any per-event tag overrides — the exact payload the check-in app reads — so you can confirm a setup without picking up a device.
Get the resolved config
GET /profiles/v1/resolved/event/{eventId}/member/{teamMemberId}:
curl 'https://api.qflowhub.io/profiles/v1/resolved/event/<eventId>/member/<teamMemberId>' \
-H 'Authorization: Bearer <access_token>' \
-H 'Ocp-Apim-Subscription-Key: <subscription_key>'
{
"profileId": "8f2c…",
"profileName": "Door Scanner",
"settings": {
"ContinuousScan": { "value": true, "locked": true }
},
"restrictions": ["restrict_settings", "restrict_stats", "restrict_signout 4821"],
"filterTags": [{ "name": "Table 1-20", "type": "tag" }],
"checkinTags": [{ "name": "Checked-Door-A", "type": "tag" }],
"statsTags": []
}
What "resolved" means
- Settings and restrictions come straight from the assigned profile.
- Tags are the per-event override if one is set on the assignment, otherwise the profile's own defaults — so
filterTagsabove reflects the override from the Assignment example, not the profile default.
If the member has no assignment on the event, profileId and profileName are null and the lists come back empty — a clean signal that nothing is applied.
When to use it
- Verify a fan-out assignment landed the way you intended, on a specific member.
- Debug a member reporting the wrong lock-downs — compare resolved against the profile.
- Audit what a device is operating under without interrupting it.
This is the same merge the device performs, so it's the source of truth for "what's on that device right now".
Back to
- Overview — the whole surface at a glance.
- For full schemas + try-it, see the API Reference.
API Reference
Interactive reference for the Profiles surface — reusable bundles of restrictions, feature toggles and tag defaults that you assign to team members per event.