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.
GETTING STARTED
Live in four steps.
Create an account, generate keys, review authentication, and start calling endpoints. The whole loop takes minutes.
- 1
Create an account at app.callgrid.com/signup.
- 2
Open your account settings and generate an API key.
- 3
Review the authentication section below.
- 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.
Bearer Token
Pass your API key in the Authorization header.
Authorization: Bearer YOUR_API_KEYQuery Parameter
Append your API key as a URL query parameter.
GET /api/endpoint?apiKey=YOUR_API_KEYSession Authentication
Users logged into the CallGrid dashboard are authenticated via session cookies. Used by the web app, no API key required.
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.
curl -X GET "https://api.callgrid.com/api/destination?page=1&limit=100" \
-H "Authorization: Bearer YOUR_API_KEY"Cursor pagination
Calls EndpointThe /api/call endpoint requires cursor-based pagination. Set useCursor to "true" and specify maxItems to control page size.
How it works
- 1
Send your first request with
useCursor: "true"andmaxItemsset to your desired page size. - 2
Check the response for
hasMore. Iftrue, anextCursorvalue will be included. - 3
Pass the
nextCursorvalue as thesearchAfterparameter in your next request to fetch the next page. - 4
Repeat until
hasMoreisfalse.
Cursor parameters
| Parameter | Type | Description |
|---|---|---|
useCursor | string (query) | Set to "true" to enable cursor pagination. |
maxItems | string (query) | Number of results per page (e.g. "100"). |
searchAfter | string (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.
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 keyconst API_KEY = "your_key_here";const LOOKBACK_MINUTES = 10;const PAGE_SIZE = 100;const SLEEP_BETWEEN_PAGES = 500; // millisecondsconst REQUEST_TIMEOUT = 60_000; // millisecondsconst 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 Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request |
| 401 | Unauthorized |
| 429 | Rate Limit Exceeded |
| 500 | Internal 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/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 windowRateLimit-RemainingRequests remaining in the current windowRateLimit-ResetSeconds until the rate limit window resetsEndpoint rate limits
| Endpoint | Path | Limit | Window |
|---|---|---|---|
| General (most endpoints) | Any | 80 requests | 1 minute |
| Call Details | GET /api/call/:id | 200 requests | 1 minute |
| RTB Bid Log | GET /api/bid/log/:id | 150 requests | 1 minute |
| Postback Events | /api/postback/event/:id | 200 requests | 1 minute |
| Recordings | /api/recordings | 200 requests | 1 minute |
Call logs export limits
The export endpoint (POST /api/export/create) enforces multiple rolling windows simultaneously:
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.
{
"url": "https://your-app.com/webhook",
"events": ["call.completed", "call.answered"],
"secret": "your_webhook_secret"
}The full interactive API reference.
Detailed endpoint documentation, request and response schemas, and interactive testing, all in one place.
View full API reference