Team API

Team API — Overview

Add and manage the team members who operate your events — door staff, back-of-house, and assigning them per-event access.

The Team API is the admin layer — granting and revoking event access for staff. Typical integrators don't touch this often: once team is set up, day-to-day operations run via Guests and Comms. But when you onboard new venue staff, transition a member off, or want to see how many guests someone checked in, this is the surface.

URL pattern

All endpoints on this page live under:

https://api.qflowhub.io/checkin/v1/api/<endpoint>

Two route conventions live side by side on this controller — important to keep straight:

  • /api/teammember/* (singular) — CRUD on a single team member (POST to create, PUT to update, DELETE to delete) plus assign / unassign event linkage.
  • /api/teammembers/* (plural) — listing / lookup of one or more team members across events or your enterprise.

Plus one stat-rollup endpoint under a different prefix: /api/team/event/{eventId} for per-team-member check-in counts on a specific event.

Every request needs both an OAuth bearer token AND an Ocp-Apim-Subscription-Key header — see Authentication.

What it does

Quick start — onboard one team member end-to-end

Create the team member:

curl -X POST 'https://api.qflowhub.io/checkin/v1/api/teammember' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "userName":  "kelly.door",
    "email":     "kelly@example.com",
    "firstName": "Kelly",
    "lastName":  "Door"
  }'

Save the returned id, then assign them to an event:

curl -X POST 'https://api.qflowhub.io/checkin/v1/api/teammember/<teamMemberId>/assign/<eventId>' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

They can now log into the Qflow check-in app and scan guests at that event.

Read in this order

  1. Team members — the single-record shape and CRUD.
  2. Listing & lookup — discovery across events / enterprise.
  3. Event assignments — link them to specific events.
  4. Check-in stats — per-member activity rollups.

For full request/response schemas + try-it, see the auto-generated API Reference.

Team API

Team members

Create, update, and delete team-member records. The CRUD layer for the staff who'll log into the check-in app at the door.

The shape of a team member

Every team member has a userName, an email, and an id. Names (firstName / lastName) and password are optional.

Usernames are lowercased and trimmed. On enterprise accounts they're also namespaced — stored as <enterprise>/<userName> server-side (standalone accounts keep the bare username). Emails are lowercased and trimmed too.

Creating a team member

POST /api/teammember. Required: userName and email. Server returns the persisted record (id, email, userName, firstName, lastName).

curl -X POST 'https://api.qflowhub.io/checkin/v1/api/teammember' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "userName":  "kelly.door",
    "email":     "kelly@example.com",
    "firstName": "Kelly",
    "lastName":  "Door",
    "password":  "ChangeMe-9182"
  }'

A few notes:

  • Duplicate username is idempotent, not an error — POST with a userName that already exists in your enterprise returns the existing record with 200 OK. Safe to re-call on retry.
  • Password handling — if you omit password (or pass empty), the server generates one but does not return it in the response. There's no "show me the password" endpoint either. Practical implication: always pass an explicit password on create so you know what it is, or set one afterwards via the update endpoint below (send a password value).
  • Email is just a label here — Qflow doesn't send a welcome / verification email automatically. If you want one, send it yourself via the Comms API using a template you author.

Updating a team member

PUT /api/teammember/update updates editable fields on an existing member. Send the full record (the server uses what you send to replace what's there). The id is required.

curl -X PUT 'https://api.qflowhub.io/checkin/v1/api/teammember/update' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "id":        "<teamMemberId>",
    "userName":  "kelly.door",
    "email":     "kelly.new@example.com",
    "firstName": "Kelly",
    "lastName":  "Door"
  }'

To change the password, include a new value in the body. Omit / blank password to leave it untouched.

Deleting a team member

DELETE /api/teammember/delete removes the team member entirely — including their event assignments. Deletion is permanent; to bring someone back you'd re-create them + re-assign their events.

curl -X DELETE 'https://api.qflowhub.io/checkin/v1/api/teammember/delete' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>' \
  -H 'Content-Type: application/json' \
  -d '{ "id": "<teamMemberId>" }'

If you might want them back later (seasonal staff, recurring contractors), prefer unassigning them from active events via Event assignments rather than deleting — keeps their id stable for stat history.

Where to next

Try it
POST/teammember PUT/teammember/update DELETE/teammember/delete POST/teammember/{teamMemberId}/unassign/{eventId}
Team API

Listing & lookup

Four read endpoints — across events, across your whole enterprise, scoped to one event, or scoped to one member's events.

Four read shapes

The Team API has four list endpoints, each scoped differently:

  • /api/teammembers — members across every event you own (you're the event's primary user).
  • /api/teammembers/all — every member in your enterprise, regardless of who owns the events they're assigned to. Useful for enterprise admins; ignored for non-enterprise accounts.
  • /api/teammembers/event/assigned/{eventId} — members assigned to one specific event.
  • /api/teammembers/user/{username}/events — events one team member is assigned to (inverse lookup).

All members across your events

GET /api/teammembers — the most common read. Returns every team member who's assigned to any event you own.

curl 'https://api.qflowhub.io/checkin/v1/api/teammembers' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

Deduplicates — a member assigned to multiple events appears once. Good for "give me everyone I might want to manage".

All members in your enterprise

GET /api/teammembers/all — the enterprise-wide variant. Returns every team member in your enterprise namespace, including those assigned to events owned by other users in the same enterprise.

curl 'https://api.qflowhub.io/checkin/v1/api/teammembers/all' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

Enterprise accounts only. Calling this on a non-enterprise (standalone) account returns 502 Bad Gateway — not a fallback. Use /api/teammembers (above) for standalone accounts.

Members assigned to one event

GET /api/teammembers/event/assigned/{eventId} — narrow the list to a single event's roster. Use for door-side displays ("who's working tonight?").

curl 'https://api.qflowhub.io/checkin/v1/api/teammembers/event/assigned/<eventId>' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

Returns 200 with an empty array if the event has no team assigned, doesn't exist, or you don't have access. No 404 and no ownership check — pass an unknown / unauthorised eventId and you'll get the same empty-array response as a real-but-empty event. Validate the eventId on your side if telling those apart matters.

Events one member is assigned to

GET /api/teammembers/user/{username}/events — the inverse direction. Given a team member's username, list every event they're currently assigned to.

curl 'https://api.qflowhub.io/checkin/v1/api/teammembers/user/<username>/events' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

Use the Enterprise-namespaced username — what you'd see in the response from any of the list endpoints above (typically <enterprise>/<member>), not the bare value you passed at create time.

Where to next

Try it
GET/teammembers GET/teammembers/all GET/teammembers/user/{username}/events
Team API

Event assignments

Link or unlink a team member to a specific event — the gating mechanism that controls who can scan guests where.

Concept

A team member only has access to events they're explicitly assigned to. Creating the team member just makes the record; until you assign them to an event, they won't see anything in the check-in app.

Two symmetric endpoints — both take teamMemberId and eventId in the URL, no body.

Assigning a team member

POST /api/teammember/{teamMemberId}/assign/{eventId} grants access. Idempotent — calling on an already-assigned member returns success without duplicating the link.

curl -X POST 'https://api.qflowhub.io/checkin/v1/api/teammember/<teamMemberId>/assign/<eventId>' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

After this call, the team member can sign into the Qflow check-in app and operate on that event's attendees (look up, admit, etc.). Other events stay invisible to them.

Pass ?notifyTeamMember=true to email the member a welcome with the event details and app download links; omit it (or send false) to assign silently.

Returns 400 Bad Request if either id is missing / malformed / unknown, or if you don't own the event. (The shape's a little blunter than 404 would be — but the failure path is the same either way: assignment didn't happen.) Symmetric for unassign below.

Unassigning a team member

POST /api/teammember/{teamMemberId}/unassign/{eventId} revokes access. Existing check-in history is preserved (so stats still attribute past scans to them); they just lose access to do more.

curl -X POST 'https://api.qflowhub.io/checkin/v1/api/teammember/<teamMemberId>/unassign/<eventId>' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

Idempotent — calling on an already-unassigned member is a no-op.

Bulk operations?

There's no bulk-assign endpoint. For onboarding multiple staff to one event (or one staff member to multiple events), loop the single-assign call client-side — the calls are inexpensive and idempotent, with no rate-limit concerns at typical onboarding volumes.

Where to next

Try it
GET/teammembers/event/assigned/{id} POST/teammember/{teamMemberId}/assign/{eventId}
Team API

Check-in stats

Per-team-member check-in and check-out counts for one event, plus 5-minute time-slice activity for an arrivals curve.

Concept

The stats endpoint returns one row per team member assigned to the event, each with their checkedIn count, checkedOut count, and a checkedInActivity array of 5-minute time slices. It's what powers the "who scanned how many" leaderboard and the arrivals-rate chart in the dashboard.

Stats are computed live on each call — no cache. Inexpensive for events under ~10k attendees; the cost grows with attendee count above that.

Reading the stats

GET /api/team/event/{eventId} — note the different URL prefix from everything else on this page (/api/team/ not /api/teammember/ or /api/teammembers/).

curl 'https://api.qflowhub.io/checkin/v1/api/team/event/<eventId>' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Ocp-Apim-Subscription-Key: <subscription_key>'

Returns an array — one entry per team member assigned to the event (including those with no check-ins yet). Each entry includes:

  • teamMemberId / username — who.
  • checkedIn — how many attendees they've admitted.
  • checkedOut — present on the response schema but not populated server-side today. Treat as zero / ignore until the server-side rollup ships.
  • checkedInActivity — array of {admitted, admittedCount} time-slice buckets. admitted is a short time-of-day string (e.g. 14:30) at the start of a 5-minute window; admittedCount is how many scans happened in it.

Time-slice arrival curves

checkedInActivity is shaped specifically to drive an arrivals-rate chart. Each 5-minute bucket has a start time and a count — plot time on X and count on Y and you get the venue's arrivals curve over time.

Empty buckets (no scans in a 5-minute window) are not included — interpolate gaps client-side if you want a continuous timeline. The admitted value is a time-of-day only (no date), so it's intended for plotting a single event's curve.

Polling considerations

The endpoint is inexpensive to poll on small events but scales with the attendee count of the event. Sensible bounds:

  • Under 1,000 attendees: polling once a second is fine.
  • 1,000–10,000: every 3–5 seconds keeps the chart responsive without excessive load.
  • 10,000+: prefer driving the chart from the check-in webhook — each admission fires an event carrying the team member who scanned — rather than polling.

For a single team member's events list, use the inverse-lookup endpoint in Listing & lookup instead — that's lighter.

Where to next

Try it
GET/team/event/{id}
Team API

API Reference

Interactive reference for the Team surface — adding and managing team members who operate an event.