Developer Reference

REST API

Create, list, update, delete, and report on Browser Simulation and Google Analytics campaigns from any HTTP client.

8 Endpoints
Full CRUD for both services
Bearer Auth
Sanctum tokens, scoped abilities
OpenAPI 3.0
Machine-readable spec

What the API does

The TrafficBot REST API mirrors what the dashboard does for campaigns. Anything you can do in the UI — list, create, update, toggle, delete, and pull hourly reports — you can do over HTTP with a bearer token.

Two services are exposed: Browser Simulation (bsim-campaigns) and Google Analytics (ga-campaigns). Social Media orders are not part of the API. Subscriptions and credit purchases stay in the browser checkout flow.

Same data as the UI

Reads and writes go through the same service layer the dashboard uses. No drift.

Per-token scopes

Six abilities (read, write, delete × two services). Mint read-only tokens for analytics scripts.

Predictable shapes

All endpoints under /api/v1/. Versioned. Breaking changes ship under /api/v2/.

1

Generate a token

Tokens are minted from your dashboard. Pick the abilities you want, copy the plaintext token once, and pass it as a bearer header on every request.

1.1 Mint a token

Visit /dashboard/api-tokens/create. Give the token a recognizable name (e.g., "MCP integration"), tick the abilities you need, and (optionally) set an expiry date.

After clicking Create token the plaintext is shown once in a banner. Copy it then. We only store the hash, so you can't retrieve it later — only revoke and recreate.

1.2 Choose abilities

Ability Grants
ga-campaigns:readList, get, and report on GA campaigns
ga-campaigns:writeCreate and update GA campaigns
ga-campaigns:deleteDelete GA campaigns
bsim-campaigns:readList, get, and report on Bsim campaigns
bsim-campaigns:writeCreate and update Bsim campaigns
bsim-campaigns:deleteDelete Bsim campaigns

Abilities are independent. write does not imply read. /api/v1/me and /api/v1/bsim/proxy-countries work with any valid token.

1.3 Use the token

Pass the token in the Authorization header. Always set Accept: application/json so error responses come back as JSON instead of HTML.

curl https://trafficbot.co/api/v1/me \
  -H "Authorization: Bearer 1|abc123def456..." \
  -H "Accept: application/json"

Treat tokens like passwords. Anyone with the plaintext can act as you within the granted abilities. Revoke immediately at /dashboard/api-tokens if a token leaks.

Want to try requests in your browser? The interactive Swagger UI lives at /api/documentation. Click Authorize, paste your token (without the Bearer prefix — the UI adds it), and use Try it out on any endpoint.

Prefer the spec? Import /api/v1/openapi.json into Postman, Insomnia, or any OpenAPI-aware tool.

2

Conventions

Same shape across every endpoint. Knowing these four rules covers most of the API.

Base URL & versioning

All endpoints sit under https://trafficbot.co/api/v1/. Breaking changes ship under /api/v2/; we won't change v1 shapes without a new major.

Single resource shape

A single resource is wrapped in { "data": {...} }:

{
  "data": {
    "id": 42,
    "name": "Homepage promo",
    "is_active": true,
    "...": "..."
  }
}
Paginated list shape

List endpoints return Laravel's standard paginated envelope. data is the page; links has prev/next page URLs; meta has pagination metadata.

{
  "data": [ { "id": 1, "...": "..." }, { "id": 2, "...": "..." } ],
  "links": {
    "first": "https://trafficbot.co/api/v1/ga-campaigns?page=1",
    "last":  "https://trafficbot.co/api/v1/ga-campaigns?page=4",
    "prev":  null,
    "next":  "https://trafficbot.co/api/v1/ga-campaigns?page=2"
  },
  "meta": {
    "current_page": 1, "from": 1, "to": 5,
    "per_page": 5, "last_page": 4, "total": 18,
    "path": "https://trafficbot.co/api/v1/ga-campaigns",
    "links": [ /* paginator nav entries */ ]
  }
}

Common query params: page, search, status=active|inactive, sort, direction=asc|desc.

Error envelope

Every non-2xx response uses the same shape:

{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name field is required."]
  }
}

See Error responses for the full list of status codes and field keys.

3

Endpoint reference

Cheat sheet of every endpoint. Both services have the same six routes; account and reference endpoints sit alongside.

Google Analytics campaigns

Method Path Ability Description
GET/ga-campaignsga-campaigns:readPaginated list
POST/ga-campaignsga-campaigns:writeCreate campaign
GET/ga-campaigns/{id}ga-campaigns:readGet one campaign
PATCH/ga-campaigns/{id}ga-campaigns:writePartial update
DELETE/ga-campaigns/{id}ga-campaigns:deleteDelete campaign
GET/ga-campaigns/{id}/reportga-campaigns:readHourly report (≤ 90 days)

Browser Simulation campaigns

Method Path Ability Description
GET/bsim-campaignsbsim-campaigns:readPaginated list
POST/bsim-campaignsbsim-campaigns:writeCreate campaign
GET/bsim-campaigns/{id}bsim-campaigns:readGet one campaign
PATCH/bsim-campaigns/{id}bsim-campaigns:writePartial update
DELETE/bsim-campaigns/{id}bsim-campaigns:deleteDeactivate first; deleting an active campaign returns 422
GET/bsim-campaigns/{id}/reportbsim-campaigns:readHourly report (≤ 90 days)

Account & reference

Method Path Ability Description
GET/menoneProfile + credit balances
GET/bsim/proxy-countriesnoneAvailable proxy country codes
4

Google Analytics examples

List campaigns

curl "https://trafficbot.co/api/v1/ga-campaigns?status=active&page=1" \
  -H "Authorization: Bearer 1|abc..." \
  -H "Accept: application/json"

Create a campaign

curl -X POST https://trafficbot.co/api/v1/ga-campaigns \
  -H "Authorization: Bearer 1|abc..." \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Homepage promo",
    "tracker_id": "G-XXXXXXX",
    "events_per_day": 100,
    "bounce_rate": 0.5,
    "max_events_per_visitor": 5,
    "fluctuate_event_rate": 0.1,
    "event_duration": 60,
    "fluctuate_duration_rate": 0.1,
    "device_rate": 0.5,
    "timezone": "America/New_York",
    "locations": ["US"],
    "urls": [{"url": "https://example.com", "title": "Home"}],
    "daily_rates": {"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1},
    "is_active": true
  }'

Returns 201 Created with the new campaign in data.

Toggle on / off

curl -X PATCH https://trafficbot.co/api/v1/ga-campaigns/42 \
  -H "Authorization: Bearer 1|abc..." \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'

PATCH supports partial payloads — send only the fields you want to change.

Pull a report

curl "https://trafficbot.co/api/v1/ga-campaigns/42/report?start_date=2026-04-01&end_date=2026-04-30" \
  -H "Authorization: Bearer 1|abc..." \
  -H "Accept: application/json"

Default window: last 7 days in the campaign's timezone. Maximum range: 90 days.

5

Browser Simulation examples

Create a campaign

curl -X POST https://trafficbot.co/api/v1/bsim-campaigns \
  -H "Authorization: Bearer 1|abc..." \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "US homepage",
    "url": "https://example.com",
    "visits_per_day": 100,
    "bounce_rate": 0.5,
    "max_pages_per_visit": 3,
    "dwell_time_min": 5,
    "dwell_time_max": 30,
    "device_rate": 0.5,
    "countries": ["US"],
    "fluctuate_visit_rate": 0.1,
    "daily_rates": {"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1},
    "is_active": true
  }'

Validate countries first. Bsim campaigns only run in countries we have residential proxies for. Pull the live list from /api/v1/bsim/proxy-countries before submitting, and pick from that array.

Delete a campaign

Bsim campaigns must be inactive before they can be deleted. PATCH first, then DELETE.

curl -X PATCH https://trafficbot.co/api/v1/bsim-campaigns/42 \
  -H "Authorization: Bearer 1|abc..." \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'

curl -X DELETE https://trafficbot.co/api/v1/bsim-campaigns/42 \
  -H "Authorization: Bearer 1|abc..."

Deleting an active Bsim campaign returns 422 with errors.is_active.

Rate limits

Three tiered limits apply per request. Hitting any one returns 429 Too Many Attempts. with a Retry-After header (seconds until you can retry).

Bucket Limit Applies to
Read (per token)120 / minuteAll GET endpoints
Write (per token)30 / minutePOST, PATCH, DELETE
Per IP300 / minuteDefense-in-depth across all endpoints

Error responses

All errors share the { message, errors } envelope. The status code tells you the category; errors keys tell you which field needs attention.

Status When Common errors keys
401Missing or invalid token
403Token lacks the required ability
404Resource doesn't exist or isn't yours
422Validation or domain rule failedname, url, is_active, limit, end_date
429Rate limit exceeded— (see Retry-After)
Insufficient credits (Bsim activation)
HTTP 422
{ "message": "...", "errors": { "is_active": ["..."] } }
Campaign cap reached (100 / service)
HTTP 422
{ "message": "Campaign limit reached...", "errors": { "limit": ["..."] } }
Date range exceeds 90 days
HTTP 422
{ "message": "Date range cannot exceed 90 days.", "errors": { "end_date": ["..."] } }

Frequently asked questions

Is there a sandbox or test environment?

No separate sandbox. Production is the only environment — but campaigns can be created with is_active: false for safe round-trip testing without spending credits.

Are there client SDKs?

Not officially. The OpenAPI 3.0 spec at /api/v1/openapi.json works with code generators (openapi-generator, openapi-typescript, etc.) if you want a typed client.

Can I buy credits or manage subscriptions over the API?

No. Billing stays in the browser via PayPal. The API is scoped to campaign management. Use /me to read current credit balances.

What's the per-account campaign limit?

100 per service per user (so 100 GA + 100 Bsim). Hitting the cap returns 422 with errors.limit. Need more? Talk to us.

How do I revoke a leaked token?

Go to /dashboard/api-tokens, click Revoke on the token in question. Revocation is immediate. The "Last used" column helps you spot tokens that look unfamiliar.

Ready to wire it up?

Mint a token, copy the bearer string, start hitting /api/v1/.