Devices
3 endpointsThe app installs behind your users. Set a correlation_id for each signed-in user in the SDK (an opaque member id, never an email or a name), then look their installs up here by it, and read what each did with your notifications. Needs the devices:read scope. Installs whose user withdrew consent are not returned.
List devices#
/devicesNewest first. Filter by correlation_id to find one user's installs (a phone, a tablet and a reinstall can share one). The push token, the install id and anything about where a device has been are never returned.
Query parameters
An opaque value from a previous page's meta.next_cursor. Omit for the first page.
How many to return, up to 100.
20Only devices whose correlation_id is exactly this.
Only ios or android.
Only devices seen at or after this ISO 8601 timestamp.
Responses
200
{
"data": [
{
"id": "0192f0a4-6b1e-7c3a-9d2f-5e8b1a4d8001",
"correlation_id": "member_8841",
"platform": "ios",
"os_version": "18.1",
"device_model": "iPhone16,1",
"manufacturer": "Apple",
"app_id": "com.example.coffee",
"app_version": "2.4.0",
"sdk_version": "5.1.0",
"locale": "en-GB",
"country": "GB",
"timezone": "Europe/London",
"permissions": {
"notifications": "granted",
"location": "always",
"precise_location": true
},
"segments": [
"vip"
],
"last_seen_at": "2026-10-07T08:30:00+00:00",
"created_at": "2026-09-20T09:12:00+00:00"
}
],
"meta": {
"next_cursor": null
}
}Response fields
401The token is missing, unknown, revoked or expired.
missing_tokeninvalid_tokentoken_revokedtoken_expired
missing_tokenMissing bearer token.
invalid_tokenUnknown API token. Check it was copied in full, and that it is for this environment.
token_revokedThe token "Zapier" was revoked on 2026-10-06 at 18:27 UTC. Issue a new one from Configuration › Platform API.
token_expiredThis token has expired. Issue a new one from Configuration › Platform API.
{
"error": {
"code": "missing_token",
"message": "Missing bearer token."
}
}403The token or workspace can't do this.
missing_abilityplatform_api_not_enabledwrong_environmentworkspace_paused
missing_abilityThis token doesn't have the campaigns:write scope.
platform_api_not_enabledThe full Platform API isn't enabled for this workspace yet. Contact customer services to turn it on.
wrong_environmentThis is a Sandbox token: use the Sandbox API address. https://api.sandbox.bubbl.tech/platform/v1
workspace_pausedThis workspace is scheduled for deletion; its API access is paused.
{
"error": {
"code": "missing_ability",
"message": "This token doesn't have the campaigns:write scope."
}
}422Something in the request isn't valid. fields says what, with the dashboard's wording.
invalid_parameterinvalid_cursor
fields says what, with the dashboard's wording.invalid_parameterupdated_since must be a valid date.
invalid_cursorThat cursor is invalid or has expired.
{
"error": {
"code": "invalid_parameter",
"message": "updated_since must be a valid date.",
"fields": {
"updated_since": [
"Must be a valid date."
]
}
}
}429Too many requests. Wait for the number of seconds in Retry-After.
rate_limitedtoo_many_failed_attempts
Retry-After.rate_limitedToo many requests. Slow down and try again shortly.
too_many_failed_attemptsToo many failed attempts. Try again shortly.
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Slow down and try again shortly."
}
}curl 'https://api.bubbl.tech/platform/v1/devices?limit=20' \
-H 'Authorization: Bearer bubbl_YOUR_TOKEN' \
-H 'Accept: application/json'const response = await fetch('https://api.bubbl.tech/platform/v1/devices?limit=20', {
method: 'GET',
headers: {
Authorization: 'Bearer bubbl_YOUR_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();import requests
response = requests.request(
'GET',
'https://api.bubbl.tech/platform/v1/devices?limit=20',
headers={
'Authorization': 'Bearer bubbl_YOUR_TOKEN',
'Accept': 'application/json',
},
)
response.raise_for_status()
data = response.json()<?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.bubbl.tech/platform/v1/devices?limit=20', [
'headers' => [
'Authorization' => 'Bearer bubbl_YOUR_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode((string) $response->getBody(), true);Get a device#
/devices/{device}Path parameters
The device ID
Responses
200
{
"data": {
"id": "0192f0a4-6b1e-7c3a-9d2f-5e8b1a4d8001",
"correlation_id": "member_8841",
"platform": "ios",
"os_version": "18.1",
"device_model": "iPhone16,1",
"manufacturer": "Apple",
"app_id": "com.example.coffee",
"app_version": "2.4.0",
"sdk_version": "5.1.0",
"locale": "en-GB",
"country": "GB",
"timezone": "Europe/London",
"permissions": {
"notifications": "granted",
"location": "always",
"precise_location": true
},
"segments": [
"vip"
],
"last_seen_at": "2026-10-07T08:30:00+00:00",
"created_at": "2026-09-20T09:12:00+00:00"
}
}Response fields
401The token is missing, unknown, revoked or expired.
missing_tokeninvalid_tokentoken_revokedtoken_expired
missing_tokenMissing bearer token.
invalid_tokenUnknown API token. Check it was copied in full, and that it is for this environment.
token_revokedThe token "Zapier" was revoked on 2026-10-06 at 18:27 UTC. Issue a new one from Configuration › Platform API.
token_expiredThis token has expired. Issue a new one from Configuration › Platform API.
{
"error": {
"code": "missing_token",
"message": "Missing bearer token."
}
}403The token or workspace can't do this.
missing_abilityplatform_api_not_enabledwrong_environmentworkspace_paused
missing_abilityThis token doesn't have the campaigns:write scope.
platform_api_not_enabledThe full Platform API isn't enabled for this workspace yet. Contact customer services to turn it on.
wrong_environmentThis is a Sandbox token: use the Sandbox API address. https://api.sandbox.bubbl.tech/platform/v1
workspace_pausedThis workspace is scheduled for deletion; its API access is paused.
{
"error": {
"code": "missing_ability",
"message": "This token doesn't have the campaigns:write scope."
}
}404Nothing with that ID in this workspace.
not_found
not_foundNo such resource in this workspace.
{
"error": {
"code": "not_found",
"message": "No such resource in this workspace."
}
}429Too many requests. Wait for the number of seconds in Retry-After.
rate_limitedtoo_many_failed_attempts
Retry-After.rate_limitedToo many requests. Slow down and try again shortly.
too_many_failed_attemptsToo many failed attempts. Try again shortly.
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Slow down and try again shortly."
}
}curl 'https://api.bubbl.tech/platform/v1/devices/{device}' \
-H 'Authorization: Bearer bubbl_YOUR_TOKEN' \
-H 'Accept: application/json'const response = await fetch('https://api.bubbl.tech/platform/v1/devices/{device}', {
method: 'GET',
headers: {
Authorization: 'Bearer bubbl_YOUR_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();import requests
response = requests.request(
'GET',
'https://api.bubbl.tech/platform/v1/devices/{device}',
headers={
'Authorization': 'Bearer bubbl_YOUR_TOKEN',
'Accept': 'application/json',
},
)
response.raise_for_status()
data = response.json()<?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.bubbl.tech/platform/v1/devices/{device}', [
'headers' => [
'Authorization' => 'Bearer bubbl_YOUR_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode((string) $response->getBody(), true);List a device's activity#
/devices/{device}/activityWhat this install did with your notifications and geofences, newest first: a notification delivered, displayed, opened or dismissed (with its campaign_id and notification_id), and geofence entries and exits. Raw position updates are not returned, and nor is any coordinate. Geofence events carry no location, because Bubbl records where, not which.
Path parameters
The device ID
Query parameters
An opaque value from a previous page's meta.next_cursor. Omit for the first page.
How many to return, up to 100.
20Only this kind of activity, e.g. notification or geofence.
Only activity that happened at or after this ISO 8601 timestamp.
Responses
200
{
"data": [
{
"id": "0192f0a4-6b1e-7c3a-9d2f-5e8b1a4d9001",
"type": "notification",
"activity": "opened",
"occurred_at": "2026-10-07T08:31:12+00:00",
"campaign_id": "0192f0a4-6b1e-7c3a-9d2f-5e8b1a4d4001",
"notification_id": "0192f0a4-6b1e-7c3a-9d2f-5e8b1a4d5001"
}
],
"meta": {
"next_cursor": null
}
}Response fields
401The token is missing, unknown, revoked or expired.
missing_tokeninvalid_tokentoken_revokedtoken_expired
missing_tokenMissing bearer token.
invalid_tokenUnknown API token. Check it was copied in full, and that it is for this environment.
token_revokedThe token "Zapier" was revoked on 2026-10-06 at 18:27 UTC. Issue a new one from Configuration › Platform API.
token_expiredThis token has expired. Issue a new one from Configuration › Platform API.
{
"error": {
"code": "missing_token",
"message": "Missing bearer token."
}
}403The token or workspace can't do this.
missing_abilityplatform_api_not_enabledwrong_environmentworkspace_paused
missing_abilityThis token doesn't have the campaigns:write scope.
platform_api_not_enabledThe full Platform API isn't enabled for this workspace yet. Contact customer services to turn it on.
wrong_environmentThis is a Sandbox token: use the Sandbox API address. https://api.sandbox.bubbl.tech/platform/v1
workspace_pausedThis workspace is scheduled for deletion; its API access is paused.
{
"error": {
"code": "missing_ability",
"message": "This token doesn't have the campaigns:write scope."
}
}404Nothing with that ID in this workspace.
not_found
not_foundNo such resource in this workspace.
{
"error": {
"code": "not_found",
"message": "No such resource in this workspace."
}
}422Something in the request isn't valid. fields says what, with the dashboard's wording.
invalid_parameterinvalid_cursor
fields says what, with the dashboard's wording.invalid_parameterupdated_since must be a valid date.
invalid_cursorThat cursor is invalid or has expired.
{
"error": {
"code": "invalid_parameter",
"message": "updated_since must be a valid date.",
"fields": {
"updated_since": [
"Must be a valid date."
]
}
}
}429Too many requests. Wait for the number of seconds in Retry-After.
rate_limitedtoo_many_failed_attempts
Retry-After.rate_limitedToo many requests. Slow down and try again shortly.
too_many_failed_attemptsToo many failed attempts. Try again shortly.
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Slow down and try again shortly."
}
}curl 'https://api.bubbl.tech/platform/v1/devices/{device}/activity?limit=20' \
-H 'Authorization: Bearer bubbl_YOUR_TOKEN' \
-H 'Accept: application/json'const response = await fetch('https://api.bubbl.tech/platform/v1/devices/{device}/activity?limit=20', {
method: 'GET',
headers: {
Authorization: 'Bearer bubbl_YOUR_TOKEN',
Accept: 'application/json',
},
});
const data = await response.json();import requests
response = requests.request(
'GET',
'https://api.bubbl.tech/platform/v1/devices/{device}/activity?limit=20',
headers={
'Authorization': 'Bearer bubbl_YOUR_TOKEN',
'Accept': 'application/json',
},
)
response.raise_for_status()
data = response.json()<?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.bubbl.tech/platform/v1/devices/{device}/activity?limit=20', [
'headers' => [
'Authorization' => 'Bearer bubbl_YOUR_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode((string) $response->getBody(), true);