TrackSERPs
Log in

API Reference

Comprehensive endpoint specifications, parameter schemas, code samples, and response payloads for the TrackSERPs REST API.

Account

Account details, plan metadata, check credit balances, and API call quotas.

GET/accountScope: rankings:read

Get account profile

Returns the authenticated account's basic profile, timezone, and effective API plan identifier (trial accounts without an active subscription report `starter`).

Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/account" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const account = await client.account.get();
console.log(account.name, account.plan);
Response (200 Account profile retrieved successfully.)
HTTP 200
{
  "id": "acc_demo123",
  "name": "Acme Agency",
  "plan": "growth",
  "timezone": "America/New_York"
}
GET/account/usageScope: rankings:read

Get account credit and API usage

Exposes the account's monthly check credit balance, topup balance, and API call quota for the billing period.

Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/account/usage" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const usage = await client.account.usage();
console.log(usage.credits.monthly_remaining, usage.api.calls_this_month);
Response (200 Account usage statistics retrieved successfully.)
HTTP 200
{
  "credits": {
    "monthly_remaining": 2450,
    "monthly_allowance": 3390,
    "topup_remaining": 5000
  },
  "api": {
    "calls_this_month": 12400,
    "calls_allowance": 100000,
    "rate_limit_per_minute": 120
  },
  "period_end": "2026-12-01T00:00:00.000Z"
}

Discovery

Explore and query projects, settings, and supported geographic search locations.

GET/projectsScope: rankings:read

List projects

Returns paginated list of tracking projects for the account. Supports cursor pagination.

Parameters
NameInTypeRequiredDescription
limitqueryintegerOptionalNumber of records to return per page (default 50, max 500).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
for await (const project of client.projects.list()) {
  console.log(project.id, project.name, project.domain);
}
Response (200 Paginated projects list.)
HTTP 200
{
  "projects": [
    {
      "id": "proj_abc123",
      "name": "Main Site SEO",
      "domain": "example.com",
      "location_code": 2840,
      "location_name": "United States",
      "language_code": "en",
      "devices": [
        "desktop",
        "mobile"
      ],
      "schedule": "daily",
      "keywords_count": 42,
      "last_run_at": "2026-11-09T08:00:00.000Z",
      "paused_reason": null,
      "estimated_monthly_credits": 2520
    }
  ],
  "next_cursor": "cur_987xyz"
}
GET/projects/{project_id}Scope: rankings:read

Get project details

Retrieves metadata, settings, and keyword statistics for a specific project.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const project = await client.projects.get("proj_abc123");
console.log(project.name, project.keywords_count);
Response (200 Project retrieved successfully.)
HTTP 200
{
  "id": "proj_abc123",
  "name": "Main Site SEO",
  "domain": "example.com",
  "location_code": 2840,
  "location_name": "United States",
  "language_code": "en",
  "devices": [
    "desktop",
    "mobile"
  ],
  "schedule": "daily",
  "keywords_count": 42,
  "last_run_at": "2026-11-09T08:00:00.000Z",
  "paused_reason": null,
  "estimated_monthly_credits": 2520
}
GET/locationsScope: rankings:read

Search locations

Searches geographic locations supported by DataForSEO and Google SERP tracking.

Parameters
NameInTypeRequiredDescription
qquerystringOptionalSearch term (city, state, or country name).
countryquerystringOptionalTwo-letter ISO country code (e.g. US, GB, CA).
limitqueryintegerOptionalMaximum number of locations to return (default 20, max 100).
Default: 20
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/locations" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const res = await client.locations.list({ q: "New York", country: "US" });
console.log(res.locations);
Response (200 List of matched geographic locations.)
HTTP 200
{
  "locations": [
    {
      "code": 2840,
      "name": "United States",
      "type": "Country",
      "country_iso": "US"
    },
    {
      "code": 1023191,
      "name": "New York, New York, United States",
      "type": "City",
      "country_iso": "US"
    }
  ]
}

Keywords

Manage keyword portfolios, device targeting, location overrides, and tag groupings.

GET/projects/{project_id}/keywordsScope: rankings:read

List project keywords

Returns paginated keywords tracked in a project. Effective devices and location code are shown.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
tagquerystringOptionalFilter results by keyword tag.
limitqueryintegerOptionalNumber of records to return per page (default 50, max 500).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/keywords" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
for await (const kw of client.keywords.list("proj_abc123", { tag: "core" })) {
  console.log(kw.phrase, kw.devices);
}
Response (200 Paginated keyword list.)
HTTP 200
{
  "keywords": [
    {
      "id": "kw_abc123",
      "phrase": "rank tracker api",
      "normalized_phrase": "rank tracker api",
      "devices": [
        "desktop",
        "mobile"
      ],
      "location_code": 2840,
      "tags": [
        "core",
        "b2b"
      ],
      "tracked_urls": [
        {
          "id": "tu_123",
          "url": "example.com/rank-tracker",
          "match": "prefix"
        }
      ],
      "created_at": "2026-11-01T10:00:00.000Z"
    }
  ],
  "next_cursor": "cur_kw_456"
}
POST/projects/{project_id}/keywordsScope: keywords:write

Upsert keywords

Adds or updates keywords in the project (up to 500 keywords per request). Upsert matches on normalised phrase. Existing keywords have tags and tracked URLs merged. Requires `keywords:write` scope and an active plan with write access.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
Idempotency-KeyheaderstringOptionalOptional unique idempotency key (UUID or client-generated string, up to 100 characters) to prevent duplicate execution of write requests.
Request Body
JSON Payload
{
  "keywords": [
    {
      "phrase": "rank tracker api",
      "devices": [
        "desktop",
        "mobile"
      ],
      "tags": [
        "api",
        "v1"
      ],
      "tracked_urls": [
        {
          "url": "example.com/api",
          "match": "prefix"
        }
      ]
    }
  ]
}
Example Request
cURL
curl -X POST "https://api.trackserps.com/v1/projects/proj_abc123/keywords" \
  -H "Authorization: Bearer ts_live_your_key" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"keywords":[{"phrase":"rank tracker api","devices":["desktop","mobile"],"tags":["api","v1"],"tracked_urls":[{"url":"example.com/api","match":"prefix"}]}]}'
Node SDK (@trackserps/sdk)
const res = await client.keywords.create("proj_abc123", {
  keywords: [
    { phrase: "rank tracker api", devices: ["desktop", "mobile"] }
  ]
});
console.log(res.results, res.estimated_monthly_credits.after);
Response (200 Keywords upserted successfully with updated monthly credit estimates.)
HTTP 200
{
  "results": [
    {
      "status": "created",
      "keyword": {
        "id": "kw_new123",
        "phrase": "rank tracker api",
        "normalized_phrase": "rank tracker api",
        "devices": [
          "desktop",
          "mobile"
        ],
        "location_code": 2840,
        "tags": [
          "api",
          "v1"
        ],
        "tracked_urls": [
          {
            "id": "tu_987",
            "url": "example.com/api",
            "match": "prefix"
          }
        ],
        "created_at": "2026-11-10T04:00:00.000Z"
      }
    }
  ],
  "estimated_monthly_credits": {
    "before": 2460,
    "after": 2520
  },
  "monthly_allowance": 3390
}
DELETE/projects/{project_id}/keywords/{keyword_id}Scope: keywords:write

Archive keyword

Soft-archives a keyword from the project. Requires `keywords:write` scope.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
keyword_idpathstringRequiredThe unique identifier of the keyword (e.g. `kw_abc123`).
Example Request
cURL
curl -X DELETE "https://api.trackserps.com/v1/projects/proj_abc123/keywords/kw_123" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
await client.keywords.delete("proj_abc123", "kw_123");
console.log("Keyword archived");

Rankings

Query latest ranking snapshots across devices, keyword time series, and 400-day bulk movements.

GET/projects/{project_id}/rankings/latestScope: rankings:read

Get latest rankings across project

Returns the latest ranking snapshot for every keyword and device in the project.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
devicequerystringOptionalFilter results by device (`desktop` or `mobile`).
tagquerystringOptionalFilter results by keyword tag.
limitqueryintegerOptionalNumber of records to return per page (default 50, max 500).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/rankings/latest" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
for await (const rank of client.rankings.latest("proj_abc123")) {
  console.log(rank.phrase, rank.device, rank.rank);
}
Response (200 Latest rankings retrieved successfully.)
HTTP 200
{
  "rankings": [
    {
      "keyword_id": "kw_abc123",
      "phrase": "rank tracker api",
      "device": "desktop",
      "date": "2026-11-09",
      "rank": 4,
      "rank_absolute": 4,
      "ranking_url": "example.com/rank-tracker",
      "serp_features": [
        "featured_snippet",
        "people_also_ask"
      ],
      "change_7d": 2,
      "change_30d": 5,
      "checked": true
    }
  ],
  "next_cursor": "cur_rank_789"
}
GET/projects/{project_id}/keywords/{keyword_id}/rankings/latestScope: rankings:read

Get latest rankings for a keyword

Returns the latest ranking snapshot for all tracked devices of a specific keyword.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
keyword_idpathstringRequiredThe unique identifier of the keyword (e.g. `kw_abc123`).
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/keywords/kw_123/rankings/latest" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const res = await client.rankings.keywordLatest("proj_abc123", "kw_123");
console.log(res.phrase, res.latest);
Response (200 Latest keyword ranking per device.)
HTTP 200
{
  "keyword_id": "kw_abc123",
  "phrase": "rank tracker api",
  "latest": [
    {
      "device": "desktop",
      "date": "2026-11-09",
      "rank": 4,
      "rank_absolute": 4,
      "ranking_url": "example.com/rank-tracker",
      "serp_features": [
        "featured_snippet"
      ],
      "checked": true
    },
    {
      "device": "mobile",
      "date": "2026-11-09",
      "rank": 6,
      "rank_absolute": 6,
      "ranking_url": "example.com/rank-tracker",
      "serp_features": [],
      "checked": true
    }
  ]
}
GET/projects/{project_id}/keywords/{keyword_id}/rankings/historyScope: rankings:read

Get keyword ranking history

Returns chronological ranking series for a keyword, including delta summary (start_rank, end_rank, rank_change).

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
keyword_idpathstringRequiredThe unique identifier of the keyword (e.g. `kw_abc123`).
startquerystringOptionalStart date in `YYYY-MM-DD` format (UTC).
endquerystringOptionalEnd date in `YYYY-MM-DD` format (UTC).
devicequerystringOptionalFilter results by device (`desktop` or `mobile`).
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/keywords/kw_123/rankings/history" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const history = await client.rankings.keywordHistory("proj_abc123", "kw_123", {
  start: "2026-10-01",
  end: "2026-11-01"
});
console.log(history.delta.rank_change, history.series);
Response (200 Keyword history time series and net delta.)
HTTP 200
{
  "keyword_id": "kw_abc123",
  "phrase": "rank tracker api",
  "series": [
    {
      "date": "2026-11-01",
      "device": "desktop",
      "rank": 8,
      "rank_absolute": 8,
      "ranking_url": "example.com/rank-tracker",
      "serp_features": []
    },
    {
      "date": "2026-11-09",
      "device": "desktop",
      "rank": 4,
      "rank_absolute": 4,
      "ranking_url": "example.com/rank-tracker",
      "serp_features": [
        "featured_snippet"
      ]
    }
  ],
  "delta": {
    "start_rank": 8,
    "end_rank": 4,
    "rank_change": 4
  }
}
GET/projects/{project_id}/rankings/historyScope: rankings:read

Bulk ranking history

Returns bulk history grouped by keyword, paginated by keyword (default 50, max 200). Range is capped at 400 days. Includes aggregate summary with improved, declined, unchanged, and average rank change. Counts as 5 requests toward rate limit and monthly quota. Accepts `application/json` or `application/x-ndjson` (one keyword per line).

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
startquerystringOptionalStart date in `YYYY-MM-DD` format (UTC).
endquerystringOptionalEnd date in `YYYY-MM-DD` format (UTC).
devicequerystringOptionalFilter results by device (`desktop` or `mobile`).
tagquerystringOptionalFilter results by keyword tag.
updated_afterquerystringOptionalISO 8601 timestamp to retrieve keywords updated after this time.
limitqueryintegerOptionalMax keywords per page (default 50, max 200).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
unranked_asqueryintegerOptionalPosition value assigned to unranked keywords when computing average rank change (e.g. 101). Default leaves unranked pairs out.
AcceptheaderstringOptionalResponse format (`application/json` or `application/x-ndjson`).
Default: application/json
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/rankings/history" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const bulk = await client.rankings.history("proj_abc123", {
  start: "2026-10-01",
  end: "2026-11-01"
});
console.log(bulk.summary.average_rank_change);
Response (200 Bulk ranking history with aggregate movement summary.)
HTTP 200
{
  "keywords": [
    {
      "keyword_id": "kw_abc123",
      "phrase": "rank tracker api",
      "series": [
        {
          "date": "2026-11-01",
          "device": "desktop",
          "rank": 8,
          "rank_absolute": 8,
          "ranking_url": "example.com/rank-tracker",
          "serp_features": []
        },
        {
          "date": "2026-11-09",
          "device": "desktop",
          "rank": 4,
          "rank_absolute": 4,
          "ranking_url": "example.com/rank-tracker",
          "serp_features": [
            "featured_snippet"
          ]
        }
      ],
      "delta": {
        "start_rank": 8,
        "end_rank": 4,
        "rank_change": 4
      }
    }
  ],
  "summary": {
    "keywords": 1,
    "improved": 1,
    "declined": 0,
    "unchanged": 0,
    "average_rank_change": 4
  },
  "summary_total": {
    "keywords": 1,
    "improved": 1,
    "declined": 0,
    "unchanged": 0
  },
  "next_cursor": null
}

Search Volume

Monthly historical Google search volume, estimated CPC, and competition benchmarks.

GET/projects/{project_id}/keywords/{keyword_id}/volumeScope: rankings:read

Get keyword search volume

Returns monthly historical search volume, CPC, and competition for a keyword.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
keyword_idpathstringRequiredThe unique identifier of the keyword (e.g. `kw_abc123`).
monthsqueryintegerOptionalNumber of historical months to retrieve (1 to 24, default 12).
Default: 12
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/keywords/kw_123/volume" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const vol = await client.volume.get("proj_abc123", "kw_123", { months: 12 });
console.log(vol.series);
Response (200 Keyword search volume series.)
HTTP 200
{
  "keyword_id": "kw_abc123",
  "phrase": "rank tracker api",
  "location_code": 2840,
  "series": [
    {
      "month": "2026-10",
      "volume": 1400,
      "cpc": 2.85,
      "competition": 0.64
    },
    {
      "month": "2026-09",
      "volume": 1350,
      "cpc": 2.7,
      "competition": 0.62
    }
  ]
}
GET/projects/{project_id}/volumeScope: rankings:read

Get latest search volume for project keywords

Returns latest month search volume data across all keywords in the project.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
limitqueryintegerOptionalNumber of records to return per page (default 50, max 500).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/volume" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
for await (const item of client.volume.list("proj_abc123")) {
  console.log(item.phrase, item.volume, item.cpc);
}
Response (200 Latest month volume data for keywords.)
HTTP 200
{
  "keywords": [
    {
      "keyword_id": "kw_abc123",
      "phrase": "rank tracker api",
      "location_code": 2840,
      "month": "2026-10",
      "volume": 1400,
      "cpc": 2.85,
      "competition": 0.64
    }
  ],
  "next_cursor": null
}

Runs

Trigger manual depth-100 check runs and simulate credit charges with dry-run calculations.

POST/projects/{project_id}/runsScope: runs:write

Trigger manual check run

Starts a manual ranking check run for all active keywords in the project. Enforces one manual run per project per hour and maximum 10 run requests per key per hour. Pass `?dry_run=true` to test credit balance and allowance without starting the run or spending credits. Requires `runs:write` scope.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
dry_runquerybooleanOptionalIf true, calculates credit requirements without starting the run.
Default: false
Idempotency-KeyheaderstringOptionalOptional unique idempotency key (UUID or client-generated string, up to 100 characters) to prevent duplicate execution of write requests.
Example Request
cURL
curl -X POST "https://api.trackserps.com/v1/projects/proj_abc123/runs" \
  -H "Authorization: Bearer ts_live_your_key" \
  -H "Idempotency-Key: $(uuidgen)"
Node SDK (@trackserps/sdk)
// 1. Dry run:
const dryRun = await client.runs.create("proj_abc123", { dry_run: true });
console.log(dryRun.would_hold, dryRun.allowed);

// 2. Start run:
const run = await client.runs.create("proj_abc123");
console.log(run.run_id, run.credits_held);
Response (200 Dry run result when `dry_run=true`.)
HTTP 200
{
  "would_hold": 42,
  "balance_after": 2408,
  "allowed": true,
  "reason": null
}
GET/projects/{project_id}/runs/latestScope: rankings:read

Get latest check run

Returns the status and execution metrics of the most recent run for the project.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/runs/latest" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const latestRun = await client.runs.latest("proj_abc123");
console.log(latestRun.status, latestRun.keywords_checked);
Response (200 Latest run details.)
HTTP 200
{
  "run_id": "run_abc123",
  "status": "completed",
  "trigger": "scheduled",
  "started_at": "2026-11-09T08:00:00.000Z",
  "finished_at": "2026-11-09T08:03:12.000Z",
  "keywords_checked": 42,
  "credits_charged": 42
}
GET/projects/{project_id}/runs/{run_id}Scope: rankings:read

Get check run by ID

Returns status and progress metrics of a specific check run.

Parameters
NameInTypeRequiredDescription
project_idpathstringRequiredThe unique identifier of the project (e.g. `proj_abc123`).
run_idpathstringRequiredThe unique identifier of the check run (e.g. `run_abc123`).
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/projects/proj_abc123/runs/run_abc123" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const run = await client.runs.get("proj_abc123", "run_123");
console.log(run.status);
Response (200 Run details retrieved successfully.)
HTTP 200
{
  "run_id": "run_abc123",
  "status": "completed",
  "trigger": "manual",
  "started_at": "2026-11-09T10:00:00.000Z",
  "finished_at": "2026-11-09T10:02:45.000Z",
  "keywords_checked": 42,
  "credits_charged": 42
}

Webhooks

Register, update, and monitor signed real-time HTTPS webhook delivery endpoints.

GET/webhooksScope: webhooks:write

List webhook endpoints

Returns all configured webhook notification endpoints for the account. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
limitqueryintegerOptionalNumber of records to return per page (default 50, max 500).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/webhooks" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const res = await client.webhooks.list();
console.log(res.webhooks);
Response (200 List of registered webhook endpoints.)
HTTP 200
{
  "webhooks": [
    {
      "id": "wh_123",
      "url": "https://example.com/api/webhooks/trackserps",
      "description": "Slack and internal sync",
      "events": [
        "run.completed",
        "rankings.updated",
        "alert.triggered"
      ],
      "enabled": true,
      "consecutive_failures": 0,
      "created_at": "2026-11-01T12:00:00.000Z"
    }
  ],
  "next_cursor": null
}
POST/webhooksScope: webhooks:write

Create webhook endpoint

Registers a new HTTPS webhook destination. Validates destination host with SSRF protection (refuses loopback, link-local, and private RFC-1918 IPs). Returns signing secret once. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
Idempotency-KeyheaderstringOptionalOptional unique idempotency key (UUID or client-generated string, up to 100 characters) to prevent duplicate execution of write requests.
Request Body
JSON Payload
{
  "url": "https://example.com/api/webhooks/trackserps",
  "description": "Production rank alerts",
  "events": [
    "run.completed",
    "rankings.updated",
    "alert.triggered"
  ]
}
Example Request
cURL
curl -X POST "https://api.trackserps.com/v1/webhooks" \
  -H "Authorization: Bearer ts_live_your_key" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/api/webhooks/trackserps","description":"Production rank alerts","events":["run.completed","rankings.updated","alert.triggered"]}'
Node SDK (@trackserps/sdk)
const { webhook, secret } = await client.webhooks.create({
  url: "https://example.com/api/webhook",
  events: ["run.completed", "rankings.updated"]
});
console.log(webhook.id, secret);
Response (201 Webhook endpoint registered. Secret is revealed only once.)
HTTP 201
{
  "webhook": {
    "id": "wh_123",
    "url": "https://example.com/api/webhooks/trackserps",
    "description": "Production rank alerts",
    "events": [
      "run.completed",
      "rankings.updated",
      "alert.triggered"
    ],
    "enabled": true,
    "consecutive_failures": 0,
    "created_at": "2026-11-10T04:00:00.000Z"
  },
  "secret": "whsec_abc123secret999"
}
GET/webhooks/{id}Scope: webhooks:write

Get webhook endpoint

Returns configuration details of a specific webhook endpoint. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
idpathstringRequiredThe unique identifier of the webhook endpoint (e.g. `wh_123`).
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/webhooks/wh_123" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
const webhook = await client.webhooks.get("wh_123");
console.log(webhook.url, webhook.events);
Response (200 Webhook configuration.)
HTTP 200
{
  "id": "wh_123",
  "url": "https://example.com/api/webhooks/trackserps",
  "description": "Production rank alerts",
  "events": [
    "run.completed",
    "rankings.updated",
    "alert.triggered"
  ],
  "enabled": true,
  "consecutive_failures": 0,
  "created_at": "2026-11-01T12:00:00.000Z"
}
PATCH/webhooks/{id}Scope: webhooks:write

Update webhook endpoint

Modifies URL, subscribed event types, description, or enabled status of a webhook endpoint. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
idpathstringRequiredThe unique identifier of the webhook endpoint (e.g. `wh_123`).
Request Body
JSON Payload
{
  "events": [
    "run.completed",
    "alert.triggered"
  ],
  "enabled": true
}
Example Request
cURL
curl -X PATCH "https://api.trackserps.com/v1/webhooks/wh_123" \
  -H "Authorization: Bearer ts_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"events":["run.completed","alert.triggered"],"enabled":true}'
Node SDK (@trackserps/sdk)
const webhook = await client.webhooks.update("wh_123", {
  enabled: false
});
console.log(webhook.enabled);
Response (200 Webhook endpoint updated.)
HTTP 200
{
  "id": "wh_123",
  "url": "https://example.com/api/webhooks/trackserps",
  "description": "Production rank alerts",
  "events": [
    "run.completed",
    "alert.triggered"
  ],
  "enabled": true,
  "consecutive_failures": 0,
  "created_at": "2026-11-01T12:00:00.000Z"
}
DELETE/webhooks/{id}Scope: webhooks:write

Delete webhook endpoint

Removes a webhook endpoint and cancels any pending delivery retries. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
idpathstringRequiredThe unique identifier of the webhook endpoint (e.g. `wh_123`).
Example Request
cURL
curl -X DELETE "https://api.trackserps.com/v1/webhooks/wh_123" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
await client.webhooks.delete("wh_123");
console.log("Webhook deleted");
POST/webhooks/{id}/rotate-secretScope: webhooks:write

Rotate webhook signing secret

Invalidates the current signing secret and issues a new secret. Revealed once. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
idpathstringRequiredThe unique identifier of the webhook endpoint (e.g. `wh_123`).
Example Request
cURL
curl -X POST "https://api.trackserps.com/v1/webhooks/wh_123/rotate-secret" \
  -H "Authorization: Bearer ts_live_your_key" \
  -H "Idempotency-Key: $(uuidgen)"
Node SDK (@trackserps/sdk)
const { secret } = await client.webhooks.rotateSecret("wh_123");
console.log("New secret:", secret);
Response (200 Webhook signing secret rotated.)
HTTP 200
{
  "secret": "whsec_newRotatedSecret999"
}
POST/webhooks/{id}/testScope: webhooks:write

Send test webhook event

Dispatches an immediate test event ping to the endpoint to verify receiver signatures and connectivity. Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
idpathstringRequiredThe unique identifier of the webhook endpoint (e.g. `wh_123`).
Example Request
cURL
curl -X POST "https://api.trackserps.com/v1/webhooks/wh_123/test" \
  -H "Authorization: Bearer ts_live_your_key" \
  -H "Idempotency-Key: $(uuidgen)"
Node SDK (@trackserps/sdk)
const result = await client.webhooks.test("wh_123");
console.log(result.status, result.status_code);
Response (200 Test event dispatched and delivery outcome recorded.)
HTTP 200
{
  "delivery_id": "del_test123",
  "status": "succeeded",
  "status_code": 200,
  "duration_ms": 145,
  "error": null
}
GET/webhooks/{id}/deliveriesScope: webhooks:write

List webhook deliveries

Returns paginated delivery log history for an endpoint (kept for 30 days). Requires `webhooks:write` scope.

Parameters
NameInTypeRequiredDescription
idpathstringRequiredThe unique identifier of the webhook endpoint (e.g. `wh_123`).
limitqueryintegerOptionalMax deliveries to return (default 50, max 200).
Default: 50
cursorquerystringOptionalOpaque pagination cursor for fetching the next page of results.
Example Request
cURL
curl -X GET "https://api.trackserps.com/v1/webhooks/wh_123/deliveries" \
  -H "Authorization: Bearer ts_live_your_key"
Node SDK (@trackserps/sdk)
for await (const delivery of client.webhooks.deliveries("wh_123")) {
  console.log(delivery.id, delivery.status, delivery.event_type);
}
Response (200 Paginated delivery logs.)
HTTP 200
{
  "deliveries": [
    {
      "id": "del_abc123",
      "endpoint_id": "wh_123",
      "event_id": "evt_run999",
      "event_type": "run.completed",
      "payload": {
        "id": "evt_run999",
        "type": "run.completed",
        "created_at": "2026-11-09T08:03:12.000Z",
        "account_id": "acc_demo123",
        "data": {
          "project_id": "proj_abc123",
          "run_id": "run_abc123",
          "status": "completed",
          "keywords_checked": 42
        }
      },
      "status": "succeeded",
      "attempts": 1,
      "status_code": 200,
      "response_snippet": "{\"ok\":true}",
      "duration_ms": 85,
      "created_at": "2026-11-09T08:03:13.000Z"
    }
  ],
  "next_cursor": null
}
API Reference · TrackSERPs API Docs