Skip to content

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".

MethodAddressWhat it does
GET/teamsYour teams
GET/cloudflaresCloudflare accounts
GET/filter_accountsFilter accounts
GET/filter_accounts/{id}/streamsStreams 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.

ParameterWhat it filters
searchPart of the name
page, per_pagePage and its size (100 by default)
bash
curl https://panel.example.com/api/teams \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json"
php
<?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;
}
python
# 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"])
js
// 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
json
{
  "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.

ParameterWhat it filters
searchPart of the account email
healthok - only working ones, error - only those with an error
page, per_pagePage and its size (100 by default)
bash
curl "https://panel.example.com/api/cloudflares?health=ok" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json"
php
<?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;
}
python
# 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 "")
js
// 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
json
{
  "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.

ParameterWhat it filters
searchPart of the name
typeService: adspect, fraudfilter or trafficarmor
page, per_pagePage and its size (100 by default)
bash
curl "https://panel.example.com/api/filter_accounts?type=adspect" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json"
php
<?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;
}
python
# 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"])
js
// 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
json
{
  "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.

ParameterWhat it is
searchPart of the stream name
streamA stream's stream_id - return it in the selected field even if it didn't match the search
refresh1 - 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.

bash
curl "https://panel.example.com/api/filter_accounts/Rt7Q/streams?search=Promo" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json"
php
<?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;
}
python
# 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"])
js
// 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
json
{
  "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
CodemessageWhen
404Not foundNo such account
422Filter account not foundThe account is archived
422Adspect account has no API keyThe Adspect account has no API key set
422Adspect's error text, e.g. Invalid API keyAdspect rejected the account's key
502Adspect request failedAdspect 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.