CallGrid
API Documentation

CallGrid API

A REST API to automate tagging, tracking, routing, reporting, and campaign management. Authenticate once, then read and write the same data that powers your dashboard.

Looking for the Bid API?Bid API documentation

GETTING STARTED

Live in four steps.

Create an account, generate keys, review authentication, and start calling endpoints. The whole loop takes minutes.

  1. 1

    Create an account at app.callgrid.com/signup.

  2. 2

    Open your account settings and generate an API key.

  3. 3

    Review the authentication section below.

  4. 4

    Start making requests to the CallGrid endpoints.

AUTHENTICATION

Three ways to authenticate.

Include your API key using one of the following approaches. Bearer token is recommended for server-to-server use.

Recommended

Bearer Token

Pass your API key in the Authorization header.

Authorization: Bearer YOUR_API_KEY

Query Parameter

Append your API key as a URL query parameter.

GET /api/endpoint?apiKey=YOUR_API_KEY

Session Authentication

Users logged into the CallGrid dashboard are authenticated via session cookies. Used by the web app, no API key required.

bash
curl -X GET "https://api.callgrid.com/api/call" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

PAGINATION

Page-based, with cursors for calls.

Most endpoints use standard page-based pagination. The Call List endpoint uses cursor-based pagination for efficient traversal of large result sets.

Standard pagination

For most endpoints, use page and limit query parameters to control the results returned.

bash
curl -X GET "https://api.callgrid.com/api/destination?page=1&limit=100" \
  -H "Authorization: Bearer YOUR_API_KEY"

Cursor pagination

Calls Endpoint

The /api/call endpoint requires cursor-based pagination. Set useCursor to "true" and specify maxItems to control page size.

How it works

  1. 1

    Send your first request with useCursor: "true" and maxItems set to your desired page size.

  2. 2

    Check the response for hasMore. If true, a nextCursor value will be included.

  3. 3

    Pass the nextCursor value as the searchAfter parameter in your next request to fetch the next page.

  4. 4

    Repeat until hasMore is false.

Cursor parameters

ParameterTypeDescription
useCursorstring (query)Set to "true" to enable cursor pagination.
maxItemsstring (query)Number of results per page (e.g. "100").
searchAfterstring (query)JSON-encoded cursor from the previous response's nextCursor field.

CODE EXAMPLES

Download calls, in your language.

Full working examples for downloading calls using cursor pagination. Each handles pagination, rate limiting, and saves results to a JSON file.

TypeScript
import { writeFileSync } from "fs";
import { join } from "path";
// ── Configuration ───────────────────────────────────────────────────────────
// Note: In production you should use a secret store
// or environment variables to store your API key
const API_KEY = "your_key_here";
const LOOKBACK_MINUTES = 10;
const PAGE_SIZE = 100;
const SLEEP_BETWEEN_PAGES = 500; // milliseconds
const REQUEST_TIMEOUT = 60_000; // milliseconds
const OUTPUT_DIR = ".";
// ─────────────────────────────────────────────────────────────────────────────
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
async function fetchCalls(start: string, end: string): Promise<any[]> {
const endpoint = "https://api.callgrid.com/api/call";
const allRows: any[] = [];
let searchAfter: unknown = null;
let page = 0;
while (true) {
page++;
const params = new URLSearchParams({
startDate: start,
endDate: end,
maxItems: String(PAGE_SIZE),
useCursor: "true",
reportTimeZone: "US/Eastern",
// use optional filters.
// filters: '{"items":[{"operator":"AND","rules":[{"tagName":"CampaignId","values":["cmgn0asdl0gl6in04nkw6txyz"],"condition":"equals"}]}]}'
});
if (searchAfter !== null) {
params.set("searchAfter", JSON.stringify(searchAfter));
}
const resp = await fetch(`${endpoint}?${params}`, {
headers: {
Accept: "application/json",
Authorization: `Bearer ${API_KEY}`,
},
signal: AbortSignal.timeout(REQUEST_TIMEOUT),
});
if (!resp.ok) {
const body = await resp.text();
throw new Error(`HTTP ${resp.status}: ${body.slice(0, 1500)}`);
}
const payload = await resp.json();
const data = payload.data ?? [];
const rows: any[] = Array.isArray(data) ? data : (data.items ?? []);
allRows.push(...rows);
const hasMore = payload.hasMore ?? false;
const nextCursor = payload.nextCursor ?? null;
console.log(`Page ${page}: ${rows.length} rows (total: ${allRows.length})`);
if (!hasMore || nextCursor === null) break;
searchAfter = nextCursor;
await sleep(SLEEP_BETWEEN_PAGES);
}
return allRows;
}
async function main() {
const now = new Date();
const start = new Date(now.getTime() - LOOKBACK_MINUTES * 60_000);
const startStr = start.toISOString();
const endStr = now.toISOString();
console.log(`Fetching calls from ${startStr} to ${endStr}`);
const rows = await fetchCalls(startStr, endStr);
const filename = `calls_${start.toISOString().replace(/[:.]/g, "-")}.json`;
const filepath = join(OUTPUT_DIR, filename);
writeFileSync(filepath, JSON.stringify(rows, null, 2));
console.log(`Saved ${rows.length} calls to ${filepath}`);
}
main();

ERROR HANDLING

Clear errors, standard codes.

The API returns detailed error messages in the response body to help with debugging. Common HTTP status codes include:

Status CodeDescription
200Success
400Bad Request
401Unauthorized
429Rate Limit Exceeded
500Internal Server Error

RATE LIMITING

Predictable limits, clear headers.

Requests are rate limited per API key, or per user session for dashboard users. When a limit is exceeded, the API returns a 429 status code.

http
HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 80
RateLimit-Remaining: 0
RateLimit-Reset: 42

{
  "code": 5001,
  "message": "Rate limit exceeded. Please try again later."
}

Response headers

Every response includes standard rate limit headers so you can monitor usage:

RateLimit-LimitMaximum requests allowed in the current window
RateLimit-RemainingRequests remaining in the current window
RateLimit-ResetSeconds until the rate limit window resets

Endpoint rate limits

EndpointLimitWindow
General (most endpoints)80 requests1 minute
Call Details200 requests1 minute
RTB Bid Log150 requests1 minute
Postback Events200 requests1 minute
Recordings200 requests1 minute

Call logs export limits

The export endpoint (POST /api/export/create) enforces multiple rolling windows simultaneously:

5 requests/ 1 minute
20 requests/ 1 hour
200 requests/ 24 hours

WEBHOOKS

Real-time events, pushed to you.

CallGrid fires webhooks for real-time notifications, so you can integrate with CRMs, dialers, routing systems, and any other tool. Here is an example configuration.

Webhooks and postbacks
json
{
  "url": "https://your-app.com/webhook",
  "events": ["call.completed", "call.answered"],
  "secret": "your_webhook_secret"
}
Reference

The full interactive API reference.

Detailed endpoint documentation, request and response schemas, and interactive testing, all in one place.

View full API reference