Touchpoint Scanner Metrics
Retrieve QR scan metrics for touchpoints. The response shape changes based on the metricsType parameter — you can pull a summary across all touchpoints in an experience, drill into a specific user's scan history, or get detailed visit data for a single touchpoint.
Endpoint
GET https://api.distinct.so/v3/touchpoint/metrics
Request Headers
| Key | Value |
|---|---|
x-distinct-api-key | Your admin API key |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
metricsType | String | Yes | Controls the level of metrics returned. Must be one of EXPERIENCE, USER, or TOUCHPOINT |
experienceId | String | Conditional | The experience to scope the query to. Required when metricsType is EXPERIENCE or USER |
userId | String | Conditional | The user whose scan history to retrieve. Required when metricsType is USER |
touchpointId | String | Conditional | The specific touchpoint to get metrics for. Required when metricsType is TOUCHPOINT |
visitsType | String | No | Controls which visit breakdown is included. Only applies when metricsType is TOUCHPOINT. Must be TOTAL or UNIQUE. Defaults to TOTAL |
pageSize | Integer | No | Number of items to return per page. Defaults to 50 |
offset | Integer | No | Number of items to skip before returning results. Defaults to 0 |
metricsTypeis always required. Missing or invalid values return400 Bad Request.experienceIdis not required whenmetricsTypeisTOUCHPOINT.visitsTypehas no effect whenmetricsTypeisEXPERIENCEorUSER.pageSizeandoffsetapply to the paginatedtotalVisitsDetailsanduniqueVisitsDetailsfields in theTOUCHPOINTresponse.
Metrics Type Quick Reference
| Goal | Required Params | Optional Params |
|---|---|---|
| All touchpoints in an experience | metricsType=EXPERIENCE, experienceId | pageSize, offset |
| A user's scan history in an experience | metricsType=USER, experienceId, userId | — |
| Total visits for a single touchpoint | metricsType=TOUCHPOINT, touchpointId | experienceId, pageSize, offset |
| Unique visitors for a single touchpoint | metricsType=TOUCHPOINT, touchpointId, visitsType=UNIQUE | experienceId, pageSize, offset |
Response
All responses share this common envelope:
{
"statusCode": 200,
"message": "Touchpoint scanner metrics fetched successfully",
"data": { ... }
}
The contents of data differ by metricsType — see the sections below.
metricsType = EXPERIENCE
Returns aggregated scan counts for every touchpoint in the experience.
{
"statusCode": 200,
"message": "Touchpoint scanner metrics fetched successfully",
"data": {
"totalTouchpoints": 2,
"touchpoints": [
{
"id": "tp-1",
"name": "Entry Scan",
"value": "entry_scan",
"totalVisits": 3,
"uniqueVisits": 2
},
{
"id": "tp-2",
"name": "Exit Scan",
"value": "exit_scan",
"totalVisits": 1,
"uniqueVisits": 1
}
]
}
}
| Field | Type | Description |
|---|---|---|
totalTouchpoints | Integer | Total number of touchpoints in the experience |
touchpoints[].id | String | Touchpoint ID |
touchpoints[].name | String | Touchpoint display name |
touchpoints[].value | String | Touchpoint identifier value |
touchpoints[].totalVisits | Integer | All scans at this touchpoint, including repeat scans by the same user |
touchpoints[].uniqueVisits | Integer | Distinct users who scanned at this touchpoint |
metricsType = USER
Returns each touchpoint the user scanned within the experience, along with every scan timestamp.
{
"statusCode": 200,
"message": "Touchpoint scanner metrics fetched successfully",
"data": {
"totalTouchpoints": 2,
"touchpoints": [
{
"id": "tp-1",
"name": "Entry Scan",
"value": "entry_scan",
"totalVisits": 2,
"timestampsUTC": [
"2024-01-01T10:00:00Z",
"2024-01-03T10:00:00Z"
]
}
]
}
}
| Field | Type | Description |
|---|---|---|
totalTouchpoints | Integer | Number of touchpoints the user scanned |
touchpoints[].totalVisits | Integer | Number of times this user scanned this touchpoint |
touchpoints[].timestampsUTC | String[] | Ordered list of all scan times in UTC for this user at this touchpoint |
metricsType = TOUCHPOINT
Returns detailed scan data for a single touchpoint. The fields present depend on visitsType.
touchpoints is a single object in this response (not an array), and totalTouchpoints is not included.
visitsType = TOTAL (default)
{
"statusCode": 200,
"message": "Touchpoint scanner metrics fetched successfully",
"data": {
"touchpoints": {
"id": "tp-1",
"name": "Entry Scan",
"value": "entry_scan",
"totalVisits": 3,
"totalVisitsDetails": {
"items": [
{ "userId": "user-1", "timestampUTC": "2024-01-01T10:00:00Z" },
{ "userId": "user-2", "timestampUTC": "2024-01-02T10:00:00Z" },
{ "userId": "user-1", "timestampUTC": "2024-01-03T10:00:00Z" }
],
"pagination": { "offset": 0, "pageSize": 50 }
}
}
}
}
| Field | Type | Description |
|---|---|---|
totalVisits | Integer | Total number of scans, including repeats |
totalVisitsDetails.items[].userId | String | ID of the user who scanned |
totalVisitsDetails.items[].timestampUTC | String | Scan timestamp in UTC |
totalVisitsDetails.pagination.offset | Integer | Current pagination offset |
totalVisitsDetails.pagination.pageSize | Integer | Current page size |
visitsType = UNIQUE
{
"statusCode": 200,
"message": "Touchpoint scanner metrics fetched successfully",
"data": {
"touchpoints": {
"id": "tp-1",
"name": "Entry Scan",
"value": "entry_scan",
"uniqueVisits": 2,
"uniqueVisitsDetails": {
"items": [
{ "userId": "user-1", "timestampUTC": "2024-01-01T10:00:00Z" },
{ "userId": "user-2", "timestampUTC": "2024-01-02T10:00:00Z" }
],
"pagination": { "offset": 0, "pageSize": 50 }
}
}
}
}
| Field | Type | Description |
|---|---|---|
uniqueVisits | Integer | Number of distinct users who scanned |
uniqueVisitsDetails.items[].userId | String | ID of the user who scanned |
uniqueVisitsDetails.items[].timestampUTC | String | First scan timestamp in UTC for this user |
uniqueVisitsDetails.pagination.offset | Integer | Current pagination offset |
uniqueVisitsDetails.pagination.pageSize | Integer | Current page size |
Example Requests
Experience Metrics
curl -X GET 'https://api.distinct.so/v3/touchpoint/metrics?metricsType=EXPERIENCE&experienceId=<experience-id>&offset=0&pageSize=50' \
-H 'x-distinct-api-key: <admin-api-key>'
Replace the placeholders:
<admin-api-key>— your admin API key provided by Distinct<experience-id>— the ID of the experience to query
User Scan History
curl -X GET 'https://api.distinct.so/v3/touchpoint/metrics?metricsType=USER&experienceId=<experience-id>&userId=<user-id>' \
-H 'x-distinct-api-key: <admin-api-key>'
Replace the placeholders:
<admin-api-key>— your admin API key provided by Distinct<experience-id>— the ID of the experience to query<user-id>— the ID of the user whose scan history you want
Touchpoint Total Visits
curl -X GET 'https://api.distinct.so/v3/touchpoint/metrics?metricsType=TOUCHPOINT&touchpointId=<touchpoint-id>&offset=0&pageSize=50' \
-H 'x-distinct-api-key: <admin-api-key>'
Replace the placeholders:
<admin-api-key>— your admin API key provided by Distinct<touchpoint-id>— the ID of the touchpoint to query
Touchpoint Unique Visitors
curl -X GET 'https://api.distinct.so/v3/touchpoint/metrics?metricsType=TOUCHPOINT&touchpointId=<touchpoint-id>&visitsType=UNIQUE&offset=0&pageSize=50' \
-H 'x-distinct-api-key: <admin-api-key>'
Replace the placeholders:
<admin-api-key>— your admin API key provided by Distinct<touchpoint-id>— the ID of the touchpoint to query
Error Responses
400 Bad Request — Missing or Invalid Parameter
{
"statusCode": 400,
"message": "Missing required parameter: metricsType"
}
Cause: A required parameter is missing, or a parameter value is invalid (e.g., an unrecognized metricsType or visitsType value).
404 Not Found — Resource Not Found
{
"statusCode": 404,
"message": "Experience not found"
}
Cause: The provided experienceId, userId, or touchpointId does not exist in the system.
Notes
- The
x-distinct-api-keywill be shared with you by the Distinct team and must be included in every API request. - The
metricsTypeparameter determines the shape of the response — refer to the response sections above for each type. - When
metricsTypeisTOUCHPOINT, thetouchpointsfield in the response is a single object, not an array. - Pagination (
pageSizeandoffset) only applies tototalVisitsDetailsanduniqueVisitsDetailsin theTOUCHPOINTresponse. - The
visitsTypeparameter is only relevant whenmetricsTypeisTOUCHPOINTand defaults toTOTALif omitted. - Optional IP allowlisting — You can share a list of IP addresses with the Distinct team to be whitelisted against your API key for an additional layer of security. When configured, requests from any other IP are rejected with
403.