Webhook Event Example
This page shows the complete structure of events sent to your webhook
How often are events sent?
Events are sent in real-time as soon as the SDK detects a user entering a monitored area. Typical latency is a few seconds, depending on device connectivity.
Event sending works as follows:
- Device entered the area of interest (monitored Cell ID), we send the
EVENT_INevent - If the device remains in the area, we don't send new entry events within 24 hours.
- When the event leaves the area and we have confirmation of this via the system, we will record this exit.
- If the user returns to the area of the last configured cell_id, we will send the
EVENT_INagain even if still within the 24-hour window.
Event Structure
When a user enters or leaves an area of interest, an event is sent via POST to your webhook endpoint in JSON format.
Complete Example
{
"mm": 1220290060,
"cell_id": "8881839825fffff",
"event_type": "EVENT_IN",
"event_duration": -1,
"created_at": 1767623650044,
"brand": "apple",
"model": "iPhone14,2",
"cfray": "55e5fg9e5ege4hgh-POA",
"origin": "beacon",
"adv_key": "com.grouplinknetwork.glconsumointeligente.sanasainteligente",
"os": "iOS",
"os_version": "26.1",
"package_name": "com.grouplinknetwork.glconsumointeligente.sanasainteligente"
}
Field Descriptions
Main Fields
| Field | Type | Description | Example |
|---|---|---|---|
mm | number | Unique mobile identifier (device ID hash) | 1220290060 |
cell_id | string | H3 cell identifier where the event occurred | "8881839825fffff" |
event_type | string | Event type: EVENT_IN (entry) | "EVENT_IN" |
event_duration | number | Event duration in milliseconds. -1 for entry events | -1 |
created_at | number | Unix timestamp in milliseconds when the event was created | 1767623650044 |
Device Information
| Field | Type | Description | Example |
|---|---|---|---|
brand | string | Device brand | "apple", "samsung", "xiaomi" |
model | string | Device model | "iPhone14,2", "SM-G998B" |
os | string | Device operating system | "iOS", "Android" |
os_version | string | Operating system version | "26.1", "14.0" |
Technical Fields
| Field | Type | Description | Example |
|---|---|---|---|
cfray | string | CloudFlare tracking identifier (for debugging) | "55e5fg9e5ege4hgh-POA" |
origin | string | Signal origin: "beacon", "gps", "network" | "beacon" |
adv_key | string | Advertising/beacon identification key | "com.app.example" |
package_name | string | Package name of the application that generated the event | "com.yourcompany.yourapp" |
Event Types
EVENT_IN - Area Entry
Triggered when the user enters an area of interest (monitored Cell ID).
{
"event_type": "EVENT_IN",
"event_duration": -1,
"cell_id": "8881839825fffff",
...
}
Characteristics:
event_type: always"EVENT_IN"event_duration: always-1(no duration yet as the user just entered)
Usage Examples
Example 1: Entry Event (iOS)
{
"mm": 1220290060,
"cell_id": "88a8100ecdfffff",
"event_type": "EVENT_IN",
"event_duration": -1,
"created_at": 1767623650044,
"brand": "apple",
"model": "iPhone15,3",
"cfray": "abc123def456-GRU",
"origin": "beacon",
"adv_key": "com.mango.nexopdf",
"os": "iOS",
"os_version": "17.2",
"package_name": "com.Dataoris.app"
}
Interpretation: A user with an iPhone 15 Pro entered cell 88a8100ecdfffff using the app with package name com.Dataoris.app.
Event Processing
Recommendations
- Validation: Always validate the received JSON structure
- Idempotency: Use the
created_at+mm+event_typefield to avoid processing duplicate events - Asynchronous: Return 200 OK immediately and process the event asynchronously
- Logging: Log all received events for analysis and debugging
Validation Example (Node.js)
function validateEvent(event) {
const requiredFields = ["mm", "cell_id", "event_type", "created_at"];
for (const field of requiredFields) {
if (!(field in event)) {
throw new Error(`Required field missing: ${field}`);
}
}
return true;
}
Timestamp Conversion
The created_at field is in Unix timestamp format (milliseconds).
JavaScript/Node.js
const date = new Date(event.created_at);
console.log(date.toISOString()); // "2026-01-05T12:34:10.044Z"
Python
from datetime import datetime
timestamp_ms = 1767623650044
date = datetime.fromtimestamp(timestamp_ms / 1000)
print(date.isoformat()) # "2026-01-05T12:34:10.044"
PHP
$timestamp_ms = 1767623650044;
$date = new DateTime('@' . ($timestamp_ms / 1000));
echo $date->format('Y-m-d H:i:s');
Fields that May Vary
Some fields may have different values depending on context:
origin
"beacon": Detection via Grouplink IoT"beacon-gps": Detection via Grouplink IoT GPS"gps": Detection via GPS
brand
"apple": iOS devices (iPhone, iPad)"samsung": Samsung devices"xiaomi": Xiaomi devices"motorola": Motorola devices- Among other Android manufacturers
os
"iOS": Apple operating system"Android": Android operating system
Frequently Asked Questions
Is the mm field unique per device?
Yes, mm is a hash of the device ID and represents a specific device in a pseudonymous way.
What to do if I receive duplicate events?
Implement deduplication using the combination of mm + created_at + event_type + cell_id.
Are events sent in real-time?
Yes, events are sent in real-time as soon as detected by the SDK. There may be a latency of a few seconds depending on device connectivity.
How do I know which specific user generated the event?
The mm field is a pseudonymous identifier. If you need to associate it with a specific user in your system, you can implement user identification in the SDK (see SDK documentation).
Next Steps
- Webhook Configuration: Configure your webhook to start receiving events
- Dataoris Introduction: Return to the home page
Support
Questions about event structure? Get in touch:
- Email: suporte@grouplinkone.com