Scan history for a code
Overview
Get each scan of a code: when and, where available, from what device.
Use this for detail on one code.
You'll need the QR code's id.
Returns the scans, newest first, 15 per page unless you set per_page.
Prerequisites
- A bearer token. See Authentication.
- The QR code's id (
qrCodeId), from List QR codes.
Base URL
| Environment | URL |
|---|---|
| Production | https://production-api.shoutaboutus.com |
| Development | https://development-api.shoutaboutus.com |
Endpoint
GET /api/v1/qr-codes/{qrCodeId}/scan-history
Authentication
Account token
- The QR code must belong to the caller's own company; otherwise
404QR code not found. An id that doesn't exist at all returns422.
QR codes belong to the account company that created them, and every QR endpoint matches on that company exactly; it does not walk the partner hierarchy. A Partner token sees nothing, even for a location inside the partner's own tree: list and stats endpoints return an empty result, and single-record endpoints return
404. The404means "not visible to this token", not "this QR code does not exist". Use an account token for every endpoint in this section.
Rate limit
120 requests per minute, counted per user (the token’s user). See Rate limits.
Request parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
qrCodeId | path | integer | Yes | The QR code's id (digits only). |
per_page | query | integer | No | Scans per page, 10 to 100. Values below 10 are raised to 10; above 100 returns 422. Default 15. |
Request body
None.
Request payload
None.
Response body
The payload is inside data; the scans are a page object in data.data.
| Field | Type | Description |
|---|---|---|
status | string | success. |
data | object | One page of scans, newest first. |
data.current_page | integer | This page's number. |
data.data[] | array of objects | The scans on this page, newest first. [] when there are none. |
data.data[].id | integer | The scan's id. |
data.data[].qr_code_id | integer | The QR code that was scanned. |
data.data[].qr_code_template_id | integer or null | The design (template) of that code, if any. |
data.data[].ip_address | string or null | IP address of the scan. |
data.data[].user_agent | string or null | Browser user agent of the scan. |
data.data[].referer | string or null | Referring page, when the browser sent one. |
data.data[].country | string or null | Country of the scan, e.g. US. |
data.data[].city | string or null | City of the scan. |
data.data[].device_type | string or null | Device type, e.g. mobile. |
data.data[].browser | string or null | Browser, e.g. Chrome. |
data.data[].os | string or null | Operating system, e.g. iOS. |
data.data[].latitude | string or null | Latitude of the scan, as a decimal string. |
data.data[].longitude | string or null | Longitude of the scan, as a decimal string. |
data.data[].metadata | object or null | Extra details stored with the scan. |
data.data[].scanned_at | string | When the code was scanned. |
data.data[].deleted_at | string or null | Always null here (deleted scans aren't listed). |
data.data[].created_at | string or null | When the record was created. |
data.data[].updated_at | string or null | When the record was last updated. |
data.first_page_url | string | URL of the first page. |
data.from | integer or null | Position of the first row on this page; null when the page is empty. |
data.last_page | integer | Number of the last page. |
data.last_page_url | string | URL of the last page. |
data.links[] | array of objects | Pager links: previous, each page number, next. |
data.links[].url | string or null | URL of that page; null when there is no such page. |
data.links[].label | string | Link text: a page number, « Previous or Next ». |
data.links[].page | integer or null | Page number the link goes to; null when there is no such page. |
data.links[].active | boolean | true for the current page. |
data.next_page_url | string or null | URL of the next page; null on the last page. |
data.path | string | URL of this endpoint, without query string. |
data.per_page | integer | Scans per page (per_page). |
data.prev_page_url | string or null | URL of the previous page; null on the first page. |
data.to | integer or null | Position of the last row on this page; null when the page is empty. |
data.total | integer | Scans across all pages. |
message | string | QR code scan history retrieved successfully. |
qr_code | object | The QR code. |
qr_code.id | integer | The QR code's id. |
qr_code.name | string | The QR code's name. |
qr_code.destination_type | string | Where the code points: landing_page, review_site or custom_url. |
Response payload
{
"data": {
"status": "success",
"data": {
"current_page": 1,
"data": [
{
"id": 123,
"qr_code_id": 2964,
"qr_code_template_id": null,
"ip_address": "203.0.113.5",
"user_agent": "Mozilla/5.0",
"referer": null,
"country": "US",
"city": "New York",
"device_type": "mobile",
"browser": "Chrome",
"os": "iOS",
"latitude": null,
"longitude": null,
"metadata": null,
"scanned_at": "2026-06-15T10:30:00.000000Z",
"deleted_at": null,
"created_at": "2026-06-15T10:30:00.000000Z",
"updated_at": "2026-06-15T10:30:00.000000Z"
}
],
"first_page_url": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?page=1",
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": null,
"label": "Next »",
"page": null,
"active": false
}
],
"next_page_url": null,
"path": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history",
"per_page": 15,
"prev_page_url": null,
"to": 1,
"total": 1
},
"message": "QR code scan history retrieved successfully",
"qr_code": {
"id": 2964,
"name": "Default QR Code",
"destination_type": "landing_page"
}
}
}Examples
Success payload
A code with one scan: see Response payload.
No scans yet:
{
"data": {
"status": "success",
"data": {
"current_page": 1,
"data": [],
"first_page_url": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?page=1",
"from": null,
"last_page": 1,
"last_page_url": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?page=1",
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": null,
"label": "Next »",
"page": null,
"active": false
}
],
"next_page_url": null,
"path": "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history",
"per_page": 15,
"prev_page_url": null,
"to": null,
"total": 0
},
"message": "QR code scan history retrieved successfully",
"qr_code": {
"id": 2964,
"name": "Default QR Code",
"destination_type": "landing_page"
}
}
}Error payload
404 QR code not found
{
"message": "QR code not found",
"status": "error",
"errors": []
}422 Id doesn't exist
{
"message": "The selected id is invalid.",
"errors": {
"id": [
"The selected id is invalid."
]
}
}422 per_page above 100
{
"message": "The per page field must not be greater than 100.",
"errors": {
"per_page": [
"The per page field must not be greater than 100."
]
}
}429 Too many requests
{
"message": "Too Many Attempts."
}| Status | Meaning |
|---|---|
200 | One page of scans. |
401 | The token is missing, expired or invalid. |
404 | The QR code isn't in your company (QR code not found). |
422 | The QR code id doesn't exist, or per_page is above 100. |
429 | More than 120 requests in a minute from this user. |
500 | Unexpected server error. |
Example request
curl --request GET \
--url "https://production-api.shoutaboutus.com/api/v1/qr-codes/2964/scan-history?per_page=15" \
--header 'Authorization: Bearer <bearer-token>' \
--header 'Accept: application/json'Updated 17 days ago
