Delegate
A delegate is a user that interacts with Satellite Tag devices, usually through a NFC chip or a barcode. Examples of interactions can be:
the delegate registers at a registration desk by showing their barcode and/or providing some personal details;
the delegate scans their wristband or lanyard against a mobile phone when entering a room to attend a session;
the delegate scans their wristband or lanyard against a mobile phone after taking a picture to receive their personalised content in their mobile site companion;
two delegates scan their wristband or lanyard against a tablet to connect with each other and exchange their virtual business card.
All these interactions involve:
a unique code that identifies the delegate, it’s either a NFC chip or a barcode/QR code, but it can be the raw ID of the delegate
a device, usually a session, a sponsor or a UHF reader, but can be literally any registered device (the word device is used here as a generic term that encompass all different objects the delegate can interact with, see Basic Concepts for more details)
a recording device (or app), it can be a mobile phone, a registration station or any other digital device consuming our REST API.
Some simple interactions are check-ins and joins and complex interactions are for example leads and connections because they involve extra steps.
Delegate Flags
Flags are a simple way of tracking some specific choices or interactions made or triggered by the delegate. Flags should always be stored lowercase. The following list includes only the core flags:
Flags |
Meaning |
|---|---|
a,b,c,d |
Reserved for instance specific purposes |
e |
The delegate has opened an email sent by Tag |
f |
The delegate has sent their feedback |
k |
The delegate is a Spark customer |
p |
The delegate has made their profile public for other delegate to see |
s |
The delegate has seen the splash screen page/pop-up and answered any questions in it |
v |
The delegate has visited their mobile site |
Flags from a to d are reserved for instance specific purposes.
Object Shape
A delegate object will always have this shape when not embedded into another object:
{
"id": "integer",
"_type": "string",
"parent": "object:delegate",
"children": "array:delegate",
"barcode": "string",
"publicId": "string",
"rfid": "string",
"externalId": "string",
"firstName": "string",
"lastName": "string",
"email": "string",
"phone": "string",
"jobTitle": "string",
"company": "string",
"sources": "array:string",
"data": "object",
"firstInteractions": "array:interaction",
"secondInteractions": "array:interaction",
"thirdInteractions": "array:interaction",
"createdAt": "string",
"updatedAt": "string"
}
The data property inside the delegate object will have this shape:
{
"Section1": "object",
"Section2": "object",
"Section3": "object"
}
Where the sections are defined in the system configuration and are available for inspection in the Control Room.
The interactions property inside the delegate object is a list of interaction. Refer to the shape of interaction
objects to understand how the list will look like.
GET /delegate/list
Gets all delegates.
All properties available for the authenticated client will be returned.
Note
This method supports pagination.
Use limit and offset to paginate returned results. The defaults if no limit or offset are provided are limit=5000 and offset=0.
GET /delegate/list?offset=0&limit=5000
The total result set count is returned in all responses in the meta property. Links to the next or previous page
are also provided in the same property.
Searching delegates
Pass a search query parameter with a JSON expression to filter the list. See Searching lists for the full
operator reference.
Category |
Fields |
|---|---|
Direct fields |
|
Relations (by ID) |
|
UniqueCode (auto-join) |
|
Interaction filters |
|
UD data fields |
|
Statement fields |
|
Comms filters |
|
Batch filter |
|
Find a delegate by name:
GET /delegate/list?search={"==":["firstName","Alice"]}
Partial match on email:
GET /delegate/list?search={"*=":["email","satellite"]}
Delegates of a specific type, created after a date:
GET /delegate/list?search={"and":[{"==":["delegateType","Crew"]},{">=":["createdAt","2025-01-01 00:00:00"]}]}
Find by barcode (UniqueCode auto-join):
GET /delegate/list?search={"==":["barcode","299281713529"]}
Delegates joined to a device:
GET /delegate/list?search={"fi":["join",{"firstDevice":[89]},">= 1"]}
Filter by UD data field (delegates from New Zealand):
GET /delegate/list?search={"ud":["Data.country","==","New Zealand"]}
Filter by statement (delegates with Points >= 50):
GET /delegate/list?search={"st":["Points",">=","50"]}
Filter by comms (delegates who received the welcome email):
GET /delegate/list?search={"comms":["emailSent","welcome-email"]}
Filter by batch (delegates in batch device 42):
GET /delegate/list?search={"batch":[42]}
Response
The response is a collection of delegates. The collection can be empty ([] in JSON).
{
"data": [
{
"id": 1,
"_type": "delegate",
"firstName": "Someone",
"lastName": "Gioffreda",
"sources": [
"admin",
"api"
],
"createdAt": "2017-09-28T12:35:38+13:00",
"updatedAt": "2017-09-28T13:23:02+13:00"
},
{
"id": 8,
"_type": "delegate",
"rfid": "7894561230",
"firstName": "Someone",
"sources": [
"admin",
"api"
],
"createdAt": "2017-09-28T13:18:56+13:00",
"updatedAt": "2017-09-28T13:22:43+13:00"
}
],
"meta": {
"pagination": {
"totalItems": 1056,
"totalPages": 528,
"offset": 0,
"limit": 2,
"next": "/api/5/delegate/list.json?q=firstName%3Dsomeone"
}
}
}
Errors and Exceptions
General rule is that this method should not return an exception because it’s read only. Although general failures or service unavailability may occur, in that case a 5xx error will be returned.
See the list of Error Responses for more information.
GET /delegate/{idType}:{id}
Gets a specific delegate.
All properties available for the authenticated client will be returned.
Available identifier types are: id, rfid, barcode, externalId, publicId.
GET /delegate/id:820
GET /delegate/rfid:1234567890
GET /delegate/barcode:9876543210
GET /delegate/publicId:337cb1d6-ec42-417b-b9b6-596458c679bc
See the list of Error Responses for more information, in particular error 1301.
Example request:
GET /delegate/barcode:299281713529
Example response:
{
"data": {
"id": 29,
"_type": "delegate",
"barcode": "299281713529",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+123456789",
"jobTitle": "Dev",
"company": "Acme Ltd",
"sources": [
"api"
],
"createdAt": "2018-03-13T23:31:32+00:00",
"updatedAt": "2018-03-13T23:31:32+00:00"
},
"meta": {}
}
GET /delegate/{idType}:{id}/info
Returns one or more content regions rendered as Twig templates, with the loaded
delegate exposed as the delegate variable.
Use this when the client needs the server to compose a delegate-aware view (a badge, a confirmation card, a profile summary) from regions configured in the Control Room, instead of fetching the delegate and re-implementing the same templating client-side.
The same identifier types accepted by GET /delegate/{idType}:{id} work here.
Query parameters
region(optional) — comma-separated list of region paths to render, in the order they will appear in the response. Each path must start with/api/delegate-info. Whitespace around each path is trimmed.When
regionis omitted (or empty), the endpoint falls back to a single region at/api/delegate-info.
Permissions
Identical to GET /delegate/{idType}:{id}: the caller needs
ROLE_OAUTH2_DELEGATE_READ (or to be the logged-in delegate / its owner).
The regions themselves are not gated separately — anything published under
/api/delegate-info is fair game.
Example request:
GET /delegate/id:820/info.json?region=/api/delegate-info/badge,/api/delegate-info/profile
Example response:
{
"data": {
"regions": [
{
"path": "/api/delegate-info/badge",
"content": "<h1>Hello Jane</h1>",
"tags": [],
"references": [],
"publishedFrom": null,
"publishedTo": null,
"createdAt": "2026-04-01 09:00:00",
"updatedAt": "2026-04-01 09:00:00"
},
{
"path": "/api/delegate-info/profile",
"content": "<p>Jane Doe — Acme Ltd</p>",
"tags": [],
"references": [],
"publishedFrom": null,
"publishedTo": null,
"createdAt": "2026-04-01 09:00:00",
"updatedAt": "2026-04-01 09:00:00"
}
]
},
"meta": {}
}
The internal numeric region id is intentionally not returned; clients
address regions by path.
Errors and exceptions
400 Bad Requestif any providedregionpath does not start with/api/delegate-info, or if a path (including the default) does not match any published region exposed to the API.Error
1301if the delegate cannot be found.
See the list of Error Responses for more information.
PATCH /delegate/{idType}:{id}
Patches a delegate.
All properties provided in the request will be updated to the given value.
When calling this you must only provide the properties that you want to change, and nothing else.
See the list of Error Responses for more information, in particular error 1301.
Example request:
PATCH /delegate/barcode:299281713529
{
"firstName": "Jane",
"company": "Acme Ltd",
}
Example response:
{
"data": {
"id": 29,
"_type": "delegate",
"barcode": "299281713529",
"firstName": "Jane",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+123456789",
"jobTitle": "Dev",
"company": "Acme Ltd",
"sources": [
"api"
],
"createdAt": "2018-03-13T23:31:32+00:00",
"updatedAt": "2018-03-13T23:31:32+00:00"
},
"meta": {}
}
POST /delegate/new
Creates a new delegate.
Example request:
POST /delegate/new
{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+123456789",
"jobTitle": "Dev",
"company": "Acme Ltd",
"barcode": "299281713529"
}
Example response:
{
"data": {
"id": 29,
"_type": "delegate",
"barcode": "299281713529",
"firstName": "Jane",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+123456789",
"jobTitle": "Dev",
"company": "Acme Ltd",
"sources": [
"api"
],
"createdAt": "2018-03-13T23:31:32+00:00",
"updatedAt": "2018-03-13T23:31:32+00:00"
},
"meta": {}
}
DELETE /delegate/{idType}:{id}
Deletes a delegate.
This will soft-delete a delegate from the system, hard deletion is available only from the Control Room.
See the list of Error Responses for more information, in particular error 1301.
GET /delegate/myself
Gets the logged in delegate.
For this endpoint to work, the client must use a “user access token” obtained through the “password” grant type. The output of this API is identical to the output of the GET /delegate/{idType}:{id} endpoint.
If the client uses a “client credentials” access token, a 401 error will be returned.
PATCH /delegate/myself
Patches the logged in delegate.
All properties provided in the request will be updated to the given value.
When calling this you must only provide the properties that you want to change, and nothing else.
For this endpoint to work, the client must use a “user access token” obtained through the “password” grant type. The output of this API is identical to the output of the GET /delegate/{idType}:{id} endpoint.
If the client uses a “client credentials” access token, a 401 error will be returned.
Registering Firebase push notification tokens and topics
Mobile apps that want to receive push notifications from TAG record their Firebase
Cloud Messaging (FCM) state against the authenticated delegate’s unstructured data,
using the same PATCH /delegate/myself endpoint described above. There is no
dedicated registration endpoint — two unstructured data fields carry everything:
data.Data.firebaseTokens— an array of FCM device tokens. Each install of the app on a device holds one token (and may rotate it); the server pushes to every token in this array.data.Data.firebaseTopics— an array of FCM topic names the device is subscribed to. TAG does not subscribe devices to topics. Subscription is performed by the mobile app via the Firebase client SDK. This field exists so administrators can see and broadcast to the topics users are actually listening on. Keep it in sync with the real SDK-side subscriptions.
Typical lifecycle on the mobile app:
On first launch, the app asks the user for permission to receive push notifications. If granted, the Firebase SDK issues a device token.
The app decides which topics it should subscribe to (this is entirely app logic — e.g. based on the user’s role, event, language, preferences). It calls the Firebase SDK’s
subscribeToTopicfor each.After the user logs in to TAG, the app reads
data.Data.firebaseTokensanddata.Data.firebaseTopicsviaGET /delegate/myself, appends its current token and topics to those arrays (deduplicating), and writes them back withPATCH /delegate/myself.Whenever the token rotates, the app replaces the old token with the new one in the
firebaseTokensarray (and may prune obviously stale entries).Whenever the app subscribes to or unsubscribes from a topic with the Firebase SDK, it mirrors that change into
firebaseTopicswith anotherPATCH /delegate/myself.
Do not overwrite the whole array. A delegate may have the app installed on multiple devices; each install’s token must be preserved. Merge with what’s already there.
Example — append a new token and a new topic.
Step 1 — read the current values:
GET /api/v5/delegate/myself.json HTTP/1.1
Authorization: Bearer <user-access-token>
The response includes the existing unstructured data:
{
"data": {
"id": 42,
"data": {
"Data": {
"firebaseTokens": ["existing-token-from-another-device"],
"firebaseTopics": ["news"]
}
}
},
"meta": {}
}
Step 2 — send back the merged arrays. Include only the fields you are changing:
PATCH /api/v5/delegate/myself.json HTTP/1.1
Authorization: Bearer <user-access-token>
Content-Type: application/json
{
"data": {
"Data": {
"firebaseTokens": [
"existing-token-from-another-device",
"new-token-from-this-device"
],
"firebaseTopics": [
"news",
"event-42"
]
}
}
}
The endpoint accepts any keys under data.Data; there is no server-side schema
to update when these two arrays first appear on a delegate.
Removing a token or topic.
To deregister a token (for example on sign-out, or after Firebase reports the
token as permanently invalid), PATCH /delegate/myself with the array minus
that entry. The same applies when the app unsubscribes from a topic via the
Firebase SDK — mirror the removal into firebaseTopics.
If the app unsubscribes from all topics and no longer holds any token, send empty arrays rather than omitting the fields.
DELETE /delegate/myself
Deletes the logged in user and attached delegate. This operation cannot be undone.
All interactions belonging to the logged in user will also be deleted, and their details erased from the denormalisation tables. Any token issued will also be cancelled and invalid.
For this endpoint to work, the client must use a “user access token” obtained through the “password” grant type.
If the client uses a “client credentials” access token, a 401 error will be returned.
POST /delegate/send-comm
Sends an SMS and/or email to a delegate. The response is an object with sms_sent and email_sent properties that
tell if the communication was sent successfully or not. Common reasons for a comm not to be send are:
backend settings: communications to delegates can be turned off
invalid recipient: the email or phone number don’t match the requirements
gateway is down: ie EziTxt or SendGrid are unavailable or the credentials are wrong
See the list of Error Responses for more information, in particular error 1301.
Example request:
{
"sms_code": "WELCOME",
"email_id": 8,
"delegate_id": 4
}
Example response:
{
"data": {
"sms_sent": true,
"email_sent": false
},
"meta": {}
}