API Reference
Full REST API reference for Adspyre. Authenticate with an API key to access all platform features programmatically.
Authentication
All API v1 endpoints require an API key. Generate keys in Settings → API Keys.
Pass the key in one of three ways:
| Method | Example |
|---|---|
| Header (recommended) | X-Api-Key: as_live_... |
| Bearer token | Authorization: Bearer as_live_... |
| Query parameter | ?api_key=as_live_... |
Security: Never expose your API key in client-side code. All requests should be made server-side.
Base URL
https://adspyre.com/apiAll v1 endpoints are prefixed with /v1/.
Endpoints
GET /v1/account
Returns current account status: tariff plan, credit balance, and plan expiry date.
Request
GET /api/v1/account
X-Api-Key: as_live_your_key_hereResponse
{
"success": true,
"message": "OK",
"tariff": "Pro",
"credits_available": 18450,
"credits_reserved": 550,
"credits_used": 6000,
"credits_per_month": 25000,
"credits_used_percent": 26.2,
"plan_expires": "2025-12-31 23:59:59",
"max_concurrent_tasks": 3,
"active_tasks": 1,
"retention_days": 30,
"threads": 4
}Response fields
| Field | Type | Description |
|---|---|---|
tariff | string | Plan name (e.g. Free Trial, Pro, Enterprise) |
credits_available | integer | Credits ready to use |
credits_reserved | integer | Credits held by pending/processing tasks |
credits_used | integer | Credits consumed this billing cycle |
credits_per_month | integer | Monthly credit quota (0 = unlimited) |
credits_used_percent | float | credits_used / credits_per_month × 100 |
plan_expires | string|null | ISO datetime of plan expiry, null if no expiry |
max_concurrent_tasks | integer | Maximum simultaneous tasks allowed |
active_tasks | integer | Currently running or queued tasks |
retention_days | integer | How long results are stored |
threads | integer | Scraper threads allocated to the account |
GET /v1/tasks
Returns a paginated list of tasks for the authenticated account.
Request
GET /api/v1/tasks?page=1&per_page=20&status=completed
X-Api-Key: as_live_your_key_hereQuery parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
per_page | integer | 20 | Results per page (max 100) |
status | string | — | Filter by status: pending, processing, completed, failed |
Response
{
"success": true,
"message": "Tasks fetched",
"tasks": [
{
"id": 42,
"status": "completed",
"target_query": "nike shoes",
"found_ads": 350,
"credits_limit": 500,
"credits_reserved": 0,
"credits_spent": 350,
"created_at": "2025-11-10 14:22:00",
"updated_at": "2025-11-10 14:24:38"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 87,
"total_pages": 5
}
}Task status values
| Status | Description |
|---|---|
pending | Queued, waiting for a scraper slot |
processing | Actively scraping |
completed | Finished successfully |
failed | Scraping failed |
POST /v1/tasks
Creates a new scraping task. Credits are reserved immediately on creation and released or spent when the task finishes.
Request
POST /api/v1/tasks
X-Api-Key: as_live_your_key_here
Content-Type: application/jsonRequest body
{
"query": "nike shoes",
"credits_limit": 500,
"filters": {
"country": "US",
"active_status": "ACTIVE",
"media_type": "ALL",
"search_type": "KEYWORD_UNORDERED",
"sort_mode": "RELEVANCY_MONTHLY_GROUPED",
"sort_direction": "DESCENDING",
"publisher_platforms": ["facebook", "instagram"],
"content_languages": "en",
"advertiser_id": "",
"start_date_min": "",
"start_date_max": "",
"result_count": 500,
"get_eu_info": false,
"is_targeted_country": false
},
"notifications": {}
}Body fields
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search keyword or advertiser URL |
credits_limit | integer | No | Max credits to spend on this task. Clamped to 1–50000. Defaults to result_count from filters |
filters | object | No | Search filters (see below) |
notifications | object | No | Notification config (Telegram, email) |
filters object
| Field | Type | Default | Allowed values |
|---|---|---|---|
country | string | ALL | ISO 3166-1 alpha-2 code or ALL |
active_status | string | ACTIVE | ACTIVE, INACTIVE, ALL |
media_type | string | ALL | ALL, IMAGE, VIDEO, MEME, IMAGE_AND_MEME, NONE |
search_type | string | KEYWORD_UNORDERED | KEYWORD_UNORDERED, KEYWORD_EXACT_PHRASE |
sort_mode | string | RELEVANCY_MONTHLY_GROUPED | LAST_ACTIVITY_DATE, TOTAL_IMPRESSIONS, START_DATE, RELEVANCY_MONTHLY_GROUPED |
sort_direction | string | DESCENDING | DESCENDING, ASCENDING |
publisher_platforms | array | all platforms | facebook, instagram, audience_network, messenger |
content_languages | string|array | — | Language code(s), e.g. "en" or ["en","fr"] |
advertiser_id | string | — | Numeric Facebook Page ID to scope to a single advertiser |
start_date_min | string | — | YYYY-MM-DD — ads launched on or after this date |
start_date_max | string | — | YYYY-MM-DD — ads launched on or before this date |
result_count | integer | 50 | Target number of ads to collect (1–5000) |
get_eu_info | boolean | false | Include EU transparency data |
is_targeted_country | boolean | false | Filter by country of targeting (not ad origin) |
Response (success)
{
"success": true,
"message": "Task created and added to queue",
"task_id": 43,
"credits_held": 500
}Response fields
| Field | Type | Description |
|---|---|---|
task_id | integer | ID to use when polling status or fetching results |
credits_held | integer | Credits reserved from your balance (0 for Enterprise/unlimited plans) |
Error codes
| Code | HTTP | Description |
|---|---|---|
CONCURRENT_LIMIT | 400 | Max simultaneous tasks reached; wait for a running task to complete |
INSUFFICIENT_CREDITS | 400 | Not enough available credits to reserve for this task |
RATE_LIMIT | 429 | Too many task creation requests (20 per 5 min / 100 per hour) |
GET /v1/results
Returns paginated ad results for a completed (or in-progress) task.
Request
GET /api/v1/results?task_id=43&page=1&per_page=50
X-Api-Key: as_live_your_key_hereQuery parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
task_id | integer | Yes | — | Task ID returned by POST /v1/tasks |
page | integer | No | 1 | Page number |
per_page | integer | No | 50 | Results per page (max 100) |
Response
{
"success": true,
"message": "Results fetched",
"task": {
"id": 43,
"target_query": "nike shoes",
"status": "completed",
"found_ads": 350,
"credits_reserved": 0,
"created_at": "2025-11-10 14:22:00",
"updated_at": "2025-11-10 14:24:38",
"execution_time": "2m 38s"
},
"results": [
{
"id": 1001,
"ad_archive_id": "123456789",
"published_at": "2025-10-01 08:00:00",
"stop_at": null,
"page_id": "987654321",
"page_name": "Nike",
"page_url": "https://www.facebook.com/nike",
"page_picture": "https://...",
"captions": ["Just Do It"],
"cta_text": ["Shop Now"],
"cta_type": ["SHOP_NOW"],
"display_format": "VIDEO",
"links": ["https://nike.com/..."],
"platforms": ["facebook", "instagram"],
"body_text": ["Introducing the Air Max 2025..."],
"link_description": ["New collection — limited time offer"],
"images": ["https://..."],
"videos": ["https://..."],
"created_at": "2025-11-10 14:23:11"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 350,
"total_pages": 7
}
}Result object fields
| Field | Type | Description |
|---|---|---|
ad_archive_id | string | Facebook Ad Library unique identifier |
published_at | string|null | When the ad started running |
stop_at | string|null | When the ad stopped running (null = still active) |
page_id | string | Facebook Page ID of the advertiser |
page_name | string | Advertiser page name |
page_url | string | Advertiser page URL |
page_picture | string | Advertiser profile picture URL |
captions | array | Ad caption texts |
cta_text | array | Call-to-action button labels |
cta_type | array | CTA type codes (e.g. SHOP_NOW, LEARN_MORE) |
display_format | string | IMAGE, VIDEO, MEME, etc. |
links | array | Destination URLs in the ad |
platforms | array | Platforms the ad ran on |
body_text | array | Main ad copy variants |
link_description | array | Link card descriptions |
images | array | Image asset URLs |
videos | array | Video asset URLs |
Error responses
All errors follow this shape:
{
"success": false,
"message": "Human-readable description",
"code": "MACHINE_READABLE_CODE"
}Common error codes
| Code | HTTP | Description |
|---|---|---|
AUTH_REQUIRED | 401 | Missing or invalid API key / session |
API_KEY_LIMIT | 429 | API key daily request limit reached |
NOT_FOUND | 404 | Resource not found or belongs to another account |
METHOD_NOT_ALLOWED | 405 | Wrong HTTP method |
RATE_LIMIT | 429 | Too many requests |
SYSTEM_ERROR | 500 | Internal server error — contact support |
Code examples
cURL
# Account info
curl -H "X-Api-Key: as_live_your_key" \
https://adspyre.com/api/v1/account
# Create task
curl -X POST \
-H "X-Api-Key: as_live_your_key" \
-H "Content-Type: application/json" \
-d '{"query":"nike","credits_limit":200,"filters":{"country":"US","result_count":200}}' \
https://adspyre.com/api/v1/tasks
# Poll task list
curl -H "X-Api-Key: as_live_your_key" \
"https://adspyre.com/api/v1/tasks?status=completed&per_page=5"
# Fetch results
curl -H "X-Api-Key: as_live_your_key" \
"https://adspyre.com/api/v1/results?task_id=43&per_page=50"JavaScript (fetch)
const API_KEY = 'as_live_your_key';
const BASE = 'https://adspyre.com/api';
const headers = { 'X-Api-Key': API_KEY, 'Content-Type': 'application/json' };
// Create a task
const { task_id } = await fetch(`${BASE}/v1/tasks`, {
method: 'POST',
headers,
body: JSON.stringify({
query: 'nike shoes',
credits_limit: 300,
filters: { country: 'US', result_count: 300 },
}),
}).then(r => r.json());
// Poll until completed
let status = 'pending';
while (status === 'pending' || status === 'processing') {
await new Promise(r => setTimeout(r, 5000));
const tasks = await fetch(`${BASE}/v1/tasks?per_page=1&page=1`, { headers }).then(r => r.json());
status = tasks.tasks.find(t => t.id === task_id)?.status ?? status;
}
// Fetch results (page 1)
const data = await fetch(`${BASE}/v1/results?task_id=${task_id}&per_page=100`, { headers })
.then(r => r.json());
console.log(data.results);Python
import requests, time
API_KEY = "as_live_your_key"
BASE = "https://adspyre.com/api"
HEADERS = {"X-Api-Key": API_KEY, "Content-Type": "application/json"}
# Create task
res = requests.post(f"{BASE}/v1/tasks", json={
"query": "nike shoes",
"credits_limit": 300,
"filters": {"country": "US", "result_count": 300},
}, headers=HEADERS)
task_id = res.json()["task_id"]
# Poll until done
while True:
tasks = requests.get(f"{BASE}/v1/tasks", params={"per_page": 100}, headers=HEADERS).json()
task = next((t for t in tasks["tasks"] if t["id"] == task_id), None)
if task and task["status"] in ("completed", "failed"):
break
time.sleep(5)
# Fetch results
page, all_results = 1, []
while True:
r = requests.get(f"{BASE}/v1/results", params={"task_id": task_id, "page": page, "per_page": 100}, headers=HEADERS).json()
all_results.extend(r["results"])
if page >= r["pagination"]["total_pages"]:
break
page += 1
print(f"Collected {len(all_results)} ads")