References
Read-only methods: where to get team_id, cloudflare_id, filter_account_id and filter_stream_id for creating PWAs, splits and domains. To check the key itself and find out whose it is, use the profile request - see "API introduction".
| Method | Address | What it does |
|---|---|---|
| GET | /teams | Your teams |
| GET | /cloudflares | Cloudflare accounts |
| GET | /filter_accounts | Filter accounts |
| GET | /filter_accounts/{id}/streams | Streams in an Adspect account |
Replace YOUR_KEY and panel.example.com with your own.
Teams
GET/teams
Teams you are a member of, alphabetically. admin sees all teams of the panel.
| Parameter | What it filters |
|---|---|
search | Part of the name |
page, per_page | Page and its size (100 by default) |
curl https://panel.example.com/api/teams \
-H "Authorization: Bearer YOUR_KEY" \
-H "Accept: application/json"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$teams = json_decode($api->get('teams')->getBody(), true)['data']['teams'];
foreach ($teams as $team) {
echo "{$team['id']} {$team['name']}" . PHP_EOL;
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}
teams = requests.get(f"{API}/teams", headers=HEADERS, timeout=30).json()["data"]["teams"]
for team in teams:
print(team["id"], team["name"])// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };
const response = await fetch(`${API}/teams`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
for (const team of data.teams) {
console.log(team.id, team.name);
}Response
{
"data": {
"meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 1 },
"teams": [
{ "id": "WQby", "name": "Team A", "users_count": 4, "created_at": "05 Oct 2026 14:23", "updated_at": "05 Oct 2026 14:23" }
]
}
}Only the common errors - see "API introduction".
Cloudflare accounts
GET/cloudflares
The panel's Cloudflare accounts, the main one (Primary) first. Archived ones are not shown. The accounts themselves are added by an administrator in the panel.
| Parameter | What it filters |
|---|---|
search | Part of the account email |
health | ok - only working ones, error - only those with an error |
page, per_page | Page and its size (100 by default) |
curl "https://panel.example.com/api/cloudflares?health=ok" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Accept: application/json"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$response = $api->get('cloudflares', ['query' => ['health' => 'ok']]);
$accounts = json_decode($response->getBody(), true)['data']['cloudflares'];
foreach ($accounts as $account) {
echo "{$account['id']} {$account['email']}" . ($account['is_primary'] ? ' (main)' : '') . PHP_EOL;
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}
response = requests.get(f"{API}/cloudflares", headers=HEADERS, params={"health": "ok"}, timeout=30)
accounts = response.json()["data"]["cloudflares"]
for account in accounts:
print(account["id"], account["email"], "(main)" if account["is_primary"] else "")// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };
const params = new URLSearchParams({ health: 'ok' });
const response = await fetch(`${API}/cloudflares?${params}`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
for (const account of data.cloudflares) {
console.log(account.id, account.email, account.is_primary ? '(main)' : '');
}Response
{
"data": {
"meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 1 },
"cloudflares": [
{
"id": "Lm3T",
"email": "[email protected]",
"is_primary": true,
"archived": false,
"status_error": null,
"status_checked_at": "05 Oct 2026 14:00",
"domains_count": 12
}
]
}
}status_error - the last account check error, null - the account is fine. domains_count - how many domains it has.
Only the common errors - see "API introduction".
Filter accounts
GET/filter_accounts
Traffic filter accounts, the main one first. Archived ones are not shown.
| Parameter | What it filters |
|---|---|
search | Part of the name |
type | Service: adspect, fraudfilter or trafficarmor |
page, per_page | Page and its size (100 by default) |
curl "https://panel.example.com/api/filter_accounts?type=adspect" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Accept: application/json"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$response = $api->get('filter_accounts', ['query' => ['type' => 'adspect']]);
$accounts = json_decode($response->getBody(), true)['data']['filter_accounts'];
foreach ($accounts as $account) {
echo "{$account['id']} {$account['name']}" . PHP_EOL;
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}
response = requests.get(f"{API}/filter_accounts", headers=HEADERS, params={"type": "adspect"}, timeout=30)
accounts = response.json()["data"]["filter_accounts"]
for account in accounts:
print(account["id"], account["name"])// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };
const params = new URLSearchParams({ type: 'adspect' });
const response = await fetch(`${API}/filter_accounts?${params}`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
for (const account of data.filter_accounts) {
console.log(account.id, account.name);
}Response
{
"data": {
"meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 1 },
"filter_accounts": [
{ "id": "Rt7Q", "name": "Adspect main", "type": "adspect", "is_primary": true, "archived": false }
]
}
}Only the common errors - see "API introduction".
Adspect streams
GET/filter_accounts/{id}/streams
Streams in an Adspect account. The stream_id from the response is the filter_stream_id for PWAs and splits.
| Parameter | What it is |
|---|---|
search | Part of the stream name |
stream | A stream's stream_id - return it in the selected field even if it didn't match the search |
refresh | 1 - request the list from Adspect again, bypassing the cache |
For fraudfilter and trafficarmor the list is always empty: these services have no streams API, take the stream identifier from their dashboard.
curl "https://panel.example.com/api/filter_accounts/Rt7Q/streams?search=Promo" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Accept: application/json"<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';
$api = new GuzzleHttp\Client([
'base_uri' => 'https://panel.example.com/api/',
'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
'timeout' => 30,
]);
$response = $api->get('filter_accounts/Rt7Q/streams', ['query' => ['search' => 'Promo']]);
$streams = json_decode($response->getBody(), true)['data']['streams'];
foreach ($streams as $stream) {
echo "{$stream['stream_id']} {$stream['name']}" . PHP_EOL;
}# pip install requests
import requests
API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}
response = requests.get(f"{API}/filter_accounts/Rt7Q/streams", headers=HEADERS, params={"search": "Promo"}, timeout=30)
streams = response.json()["data"]["streams"]
for stream in streams:
print(stream["stream_id"], stream["name"])// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };
const params = new URLSearchParams({ search: 'Promo' });
const response = await fetch(`${API}/filter_accounts/Rt7Q/streams?${params}`, {
method: 'GET',
headers,
signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();
for (const stream of data.streams) {
console.log(stream.stream_id, stream.name);
}Response
{
"data": {
"streams": [
{ "stream_id": "a1b2c3", "name": "Promo EN", "mode": "Filter" },
{ "stream_id": "d4e5f6", "name": "Promo DE", "mode": "Filter" }
],
"selected": null
}
}No more than 100 streams come back - if the one you need is missing, refine search.
Errors
| Code | message | When |
|---|---|---|
404 | Not found | No such account |
422 | Filter account not found | The account is archived |
422 | Adspect account has no API key | The Adspect account has no API key set |
422 | Adspect's error text, e.g. Invalid API key | Adspect rejected the account's key |
502 | Adspect request failed | Adspect didn't answer |
Don't add refresh=1 to loops
The stream list is cached for 5 minutes. With refresh=1 every request goes to Adspect - in a loop that quickly hits Adspect's own limits. Use it once, if you've just created a stream in the Adspect dashboard and don't see it in the list.