API Documentation

AdServerX REST API — v1

Authentication

All protected API endpoints require a Bearer token in the Authorization header.

Authorization: Bearer YOUR_API_KEY

To obtain an API key:

  1. Use POST /api/v1/auth/login with your credentials to get a key programmatically, or
  2. Generate one from the API Keys page in your account.

API keys are stored as SHA256 hashes — the raw key is shown only once at creation time.

Error Responses

All responses are JSON. Errors follow this format:

{
  "success": false,
  "error": "Description of the error"
}
HTTP CodeMeaning
200OK
201Created
400Bad request / business rule violation
401Missing or invalid API key
403Forbidden
404Resource not found
422Validation error
429Rate limit exceeded
500Internal server error
501Not implemented
Rate Limits
Route GroupLimit
Auth login5 requests / 15 minutes
Ad serving (/api/v1/serve/*)1000 requests / minute
General API (/api/v1/*)60 requests / minute (configurable)

Rate limits are per IP address. When exceeded, the API returns HTTP 429.

Auth Endpoints
POST /api/v1/auth/login

Authenticate and receive an API key. No Bearer token required.

Request body:

{
  "email": "user@example.com",
  "password": "your_password",
  "name": "My App Key"   // optional label
}

Response (201):

{
  "success": true,
  "api_key": "ak_a1b2c3d4e5f6...",
  "key_prefix": "ak_a1b2c3",
  "message": "Store this API key securely — it will not be shown again."
}

POST /api/v1/auth/logout

Revoke the API key used in this request. Requires Bearer token.

Response (200):

{ "success": true, "message": "API key revoked." }
Campaign Endpoints

All campaign endpoints require Authorization: Bearer {key}

GET /api/v1/campaigns

List your campaigns.

Query params: page, per_page (max 100), status

{
  "success": true,
  "data": [ { "id": 1, "name": "My Campaign", "status": "active", ... } ],
  "pagination": { "page": 1, "per_page": 25, "count": 1 }
}

GET /api/v1/campaigns/{id}

Get a single campaign.


POST /api/v1/campaigns

Create a campaign.

{
  "name": "Summer Sale",
  "bid_amount": "1.50",
  "daily_budget": "50.00",
  "start_date": "2026-03-10",
  "end_date": null
}

PUT /api/v1/campaigns/{id}

Update a campaign. Send only the fields you want to change.


DELETE /api/v1/campaigns/{id}

Delete a campaign.

Ad Endpoints

All ad endpoints require Authorization: Bearer {key}

GET /api/v1/ads

List your ads. Filter with ?campaign_id=123, ?status=active.


GET /api/v1/ads/{id}

Get a single ad.


POST /api/v1/ads

Create an ad.

{
  "campaign_id": 1,
  "name": "Banner Ad 300x250",
  "type": "banner",
  "headline": "Click Here",
  "destination_url": "https://example.com",
  "image_url": "https://cdn.example.com/banner.jpg",
  "width": 300,
  "height": 250
}

PUT /api/v1/ads/{id}

Update an ad.


DELETE /api/v1/ads/{id}

Delete an ad.

Analytics Endpoints

All analytics endpoints require Authorization: Bearer {key}

GET /api/v1/analytics/campaigns/{id}

Get stats for a campaign.

Query params: period — one of today, yesterday, last_7_days, last_30_days, all (default: all)

{
  "success": true,
  "data": {
    "campaign_id": 1,
    "period": "last_7_days",
    "stats": { "impressions": 5000, "clicks": 120, "ctr": 2.4, ... },
    "daily_trend": [ { "date": "2026-03-09", "impressions": 700, ... } ]
  }
}

GET /api/v1/analytics/ads/{id}

Get stats for an ad. Same period param as above.


GET /api/v1/analytics/publishers/{id}

Get stats for a publisher. Same period param as above.


GET /api/v1/analytics/zones/{id}

Zone-level analytics are not yet implemented. Returns HTTP 501.

Publisher Endpoints

Requires Authorization: Bearer {key}. Create and delete are admin-only.

GET /api/v1/publishers

List publishers. Admins see all; publisher-role users see their own record.

Query params: page, per_page (max 100)


GET /api/v1/publishers/{id}

Get a single publisher.


GET /api/v1/publishers/{id}/analytics

Get publisher stats.

Query params: periodtoday, yesterday, last_7_days, last_30_days, all


POST /api/v1/publishers Admin

Create a publisher.

{
  "name": "My Publisher",
  "user_id": 5,
  "website_url": "https://example.com",
  "description": "Optional description"
}

PUT /api/v1/publishers/{id}

Update a publisher. Admins can update any; publisher users can update their own.


DELETE /api/v1/publishers/{id} Admin

Delete a publisher.

Website Endpoints

Requires Authorization: Bearer {key}. Access is scoped to the caller's publisher.

GET /api/v1/websites

List websites. Filter with ?publisher_id=1.

Query params: publisher_id, page, per_page


GET /api/v1/websites/{id}

Get a single website.


POST /api/v1/websites

Create a website. The caller must own the specified publisher_id.

{
  "publisher_id": 1,
  "name": "My Site",
  "url": "https://mysite.com",
  "category": "news"
}

PUT /api/v1/websites/{id}

Update a website.


DELETE /api/v1/websites/{id}

Delete a website.

Zone Endpoints

Requires Authorization: Bearer {key}. Access is scoped to the caller's publisher.

GET /api/v1/zones

List zones. Filter with ?website_id=1.

Query params: website_id, page, per_page


GET /api/v1/zones/{id}

Get a single zone.


POST /api/v1/zones

Create a zone. The caller must own the specified website_id's publisher.

{
  "website_id": 1,
  "name": "Header Banner",
  "type": "banner",
  "width": 728,
  "height": 90
}

PUT /api/v1/zones/{id}

Update a zone.


DELETE /api/v1/zones/{id}

Delete a zone.

Webhook Endpoints

Requires Authorization: Bearer {key}. Webhooks are identified by UUID.

GET /api/v1/webhooks

List your webhooks.


GET /api/v1/webhooks/{uuid}

Get a single webhook. The signing secret is never returned after creation.


POST /api/v1/webhooks

Create a webhook. The signing secret is returned once in this response only.

{
  "name": "My Webhook",
  "url": "https://example.com/webhook",
  "events": "campaign.created,ad.created",   // comma-separated string or JSON array
  "is_active": 1
}

Response (201):

{
  "success": true,
  "data": { "uuid": "...", "name": "My Webhook", ... },
  "secret": "whsec_...",
  "message": "Webhook created. Store the secret securely — it will not be shown again."
}

Available events: campaign.created, campaign.status_changed, campaign.deleted, ad.created, ad.status_changed, payment.completed, payment.failed, publisher.approved, publisher.rejected, fraud.alert, webhook.test

Signature verification: Each delivery includes an X-AdServerX-Signature: sha256=... header computed with HMAC-SHA256 over the raw request body using your webhook secret.


PUT /api/v1/webhooks/{uuid}

Update a webhook.


DELETE /api/v1/webhooks/{uuid}

Delete a webhook.


POST /api/v1/webhooks/{uuid}/test

Dispatch a webhook.test event to verify your endpoint is reachable.

Reports Endpoints

Requires Authorization: Bearer {key}.

GET /api/v1/reports

Summary financial report. Non-admins see their own data; admins see platform-wide data.

Query params: periodtoday, yesterday, last_7_days, last_30_days, all

{
  "success": true,
  "data": {
    "period": "last_7_days",
    "summary": { "total_revenue": "1234.56", "total_impressions": 50000, ... },
    "revenue_over_time": [ { "date": "2026-03-09", "revenue": "180.00" }, ... ]
  }
}

GET /api/v1/reports/financial Admin

Full financial report including per-advertiser revenue and per-publisher payouts.

{
  "success": true,
  "data": {
    "period": "all",
    "summary": { ... },
    "revenue_over_time": [ ... ],
    "per_advertiser_revenue": [ ... ],
    "per_publisher_payouts": [ ... ]
  }
}
Invoice Endpoints

Requires Authorization: Bearer {key}. Read-only — invoice management is handled via the web UI.

GET /api/v1/invoices

List invoices. Admins see all; others see their own.

Query params: page, per_page


GET /api/v1/invoices/{uuid}

Get a single invoice with line items and transactions.

{
  "success": true,
  "data": {
    "uuid": "...",
    "status": "paid",
    "total": "99.00",
    "items": [ { "description": "Campaign impressions", "amount": "99.00" } ],
    "transactions": [ { "type": "payment", "amount": "99.00", "created_at": "..." } ]
  }
}
User Endpoints Admin Only

All user endpoints require Authorization: Bearer {key} with an admin account. Returns 403 for non-admins.

GET /api/v1/users

List all users.

Query params: page, per_page


GET /api/v1/users/{id}

Get a single user. Password hash is never returned.


POST /api/v1/users

Create a user.

{
  "name": "Jane Doe",
  "email": "jane@example.com",
  "password": "SecurePass123!",
  "role_id": 4
}

PUT /api/v1/users/{id}

Update a user. Omit password to leave it unchanged.


DELETE /api/v1/users/{id}

Soft-delete a user. Cannot delete your own account.

Settings Endpoints Admin Only

Requires Authorization: Bearer {key} with an admin account. Returns 403 for non-admins. Sensitive values (SMTP passwords, Stripe/PayPal keys) are masked in responses.

GET /api/v1/settings

Get all platform settings as a key/value object.

{
  "success": true,
  "data": {
    "site_name": "AdServerX",
    "currency": "USD",
    "smtp_password": "********",
    ...
  }
}

PUT /api/v1/settings

Update one or more settings. Send only the keys you want to change.

{ "site_name": "My Ad Network", "currency": "EUR" }
Ad Serving (Public)

No authentication required. Returns the best ad for a zone.

GET /api/v1/serve/{zone_uuid}

Query params: device, browser, os, country, region

GET /api/v1/serve/550e8400-e29b-41d4-a716-446655440000
    ?device=mobile&country=US
Tracking (Public)

No authentication required. CORS enabled for cross-origin requests.

POST /api/v1/track/impression
{ "zone_uuid": "...", "ad_uuid": "..." }
GET /api/v1/track/impression/pixel

1×1 pixel tracking. Returns a transparent GIF.

GET /api/v1/track/impression/pixel?zone_uuid=...&ad_uuid=...
POST /api/v1/track/click
{ "ad_uuid": "...", "impression_uuid": "...", "destination_url": "https://..." }
POST /api/v1/track/conversion
{ "click_uuid": "...", "type": "sale", "value": "29.99" }