Developers

CallTracker REST API

The CallTracker API gives your own systems read access to one workspace: calls with their marketing attribution, placements and tracking numbers. It is read-only; to receive calls as they happen, use signed webhooks. The machine-readable spec is at /api/v1/openapi.json (OpenAPI 3.1).

Authentication

  • Create a key in Settings β†’ API access. Only members who can manage integrations can create or revoke keys.
  • Choose the permissions the key needs: calls:read, placements:read, numbers:read.
  • The full key (ct_live_…) is shown once. CallTracker stores only a SHA-256 hash of it.
  • Send it on every request as 'Authorization: Bearer ct_live_…'. A key only sees data in the workspace it was created in.
  • Revoking a key takes effect immediately. A workspace can have up to 10 active keys.

Endpoints

Base URL: https://calltracker.dev/api/v1

EndpointScopeDescription
GET /callscalls:readList calls, newest first. Filters: from, to (ISO 8601), placementId, status.
GET /calls/{id}calls:readOne call with its attribution and Google Ads upload status.
GET /placementsplacements:readList placements. Filter: active=true|false.
GET /numbersnumbers:readEvery tracking number: single placement numbers and dynamic number insertion pool numbers.

Example

curl "https://calltracker.dev/api/v1/calls?from=2026-10-01T00:00:00Z&limit=50" \
  -H "Authorization: Bearer $CALLTRACKER_API_KEY"
{
  "data": [
    {
      "id": "clx2k9d0f0001",
      "placementId": "clx2k8z1a0000",
      "callerNumber": "+4791234567",
      "status": "completed",
      "durationSeconds": 184,
      "connectedSeconds": 179,
      "aiHandled": false,
      "tags": ["new-customer"],
      "hasRecording": true,
      "transcriptionStatus": "completed",
      "startedAt": "2026-10-01T09:14:03.000Z",
      "attribution": {
        "trafficSource": "GOOGLE_ADS",
        "utmSource": "google",
        "utmMedium": "cpc",
        "utmCampaign": "plumbing-oslo",
        "utmTerm": "emergency plumber",
        "utmContent": null,
        "gclid": "Cj0KCQjw...",
        "gbraid": null,
        "wbraid": null,
        "fbclid": null,
        "msclkid": null,
        "referrerUrl": "https://www.google.com/",
        "landingPage": "https://example.com/emergency"
      },
      "googleAdsUploadStatus": "uploaded"
    }
  ],
  "nextCursor": "MjAyNi0xMC0wMVQwOToxNDowMy4wMDBafGNseDJrOWQwZjAwMDE"
}

Values above are illustrative.

Pagination

  • List endpoints return up to limit items (default 50, maximum 100), newest first.
  • When more results exist, the response has a nextCursor. Pass it back as ?cursor=… with the same filters to get the next page; it is null on the last page.
  • Cursors are stable while new calls arrive, so paging does not skip or repeat calls.

Rate limits

  • Each key can make 120 requests per minute.
  • Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds).
  • Over the limit you get HTTP 429 with a Retry-After header in seconds.

Errors

Errors use one JSON shape with a stable code:

{ "error": { "code": "insufficient_scope", "message": "This API key needs the 'placements:read' scope." } }
  • 400 invalid_request: an unknown or malformed query parameter.
  • 401 unauthorized: the key is missing, malformed or revoked.
  • 403 insufficient_scope: the key lacks the permission for this endpoint.
  • 404 not_found: no such record in this workspace.
  • 429 rate_limited: wait for Retry-After seconds.

What the API does not do

  • It cannot create, change or delete data.
  • Recording audio and transcripts are not served by the API; hasRecording and transcriptionStatus tell you whether they exist in the dashboard.
  • There is no OAuth app flow for third-party apps; keys belong to one workspace.

Pull call data into your stack

The REST API and webhooks are included in CallTracker Pro at no extra cost.