## Call logs `GET /get-call-logs-api` Returns the authenticated user's **outbound** call logs from the Project Blue dialer, including a `recording_url` when a recording is available. This is the call-log analog of `/get-messages-api`. > **Outbound dialer calls only** > > This endpoint returns outbound calls placed from the Project Blue dialer. > **recording_url can be null — that's expected** > > This endpoint reports call **attempts**, not just recorded calls — so unanswered, busy, failed, and very short calls all show up with `recording_url: null`. Answered calls typically populate `recording_url` within seconds of `ended_at`.If a long-completed call still has `recording_url: null`, it usually means no audio was captured for that call (e.g. recording disabled on the line). ### Query parameters - `limit` (integer (1–100)) — Maximum number of call logs to return. Defaults to 100. - `offset` (integer (≥ 0)) — Pagination offset. Defaults to 0. offset + limit must be ≤ 2000; deeper pages return 400 regardless of limit. - `call_log_timestamp` ("asc" | "desc") — Sort direction by the call log's created_at, so unanswered attempts interleave with answered calls. Defaults to desc (newest first). - `pb_line_id` (string (UUID)) — Encoded Project Blue line id (from GET /get-lines). Returns 400 if the line does not belong to the API key's user. - `answered_at_gte` (string (ISO-8601)) — Inclusive lower bound on answered_at. Note: only matches calls that were actually answered. - `answered_at_lte` (string (ISO-8601)) — Inclusive upper bound on answered_at. Note: only matches calls that were actually answered. ### CallLog object - `id` (string, required) — Internal call log id (stable, useful for dedupe). - `line_id` (string | null, required) — UUID-encoded PB line id. Round-trips with the pb_line_id filter. - `from_number` (string, required) — E.164 sender (your line). - `to_number` (string, required) — E.164 recipient. - `status` (string, required) — Call status (completed, no-answer, busy, failed, canceled, …). - `disposition` (string | null, required) — AI-assigned disposition derived from the call transcript. See the Dispositions table below for all possible values. - `transcript` (string | null, required) — Speaker-labelled transcript when one was generated. - `duration_seconds` (number | null, required) — Connected duration. null for calls that never connected. - `answered_at` (string (ISO-8601) | null, required) — When the call was answered. - `ended_at` (string (ISO-8601) | null, required) — When the call ended. - `recording_url` (string | null, required) — URL to the call recording when one is available; null otherwise. ### Dispositions After a recording is transcribed, the transcript is run through an AI classifier that assigns one of the following dispositions. Use this for routing, follow-up automation, or analytics. The disposition can be `null` on calls that haven't been classified yet. | Value | Meaning | | --- | --- | | `answered` | A human answered and spoke (any clear human speech that isn't a voicemail greeting). | | `voicemail` | The call went to voicemail (voicemail greeting, beep, or 'leave a message' prompt detected). | | `busy` | The line was busy. | | `no_answer` | No one answered — just ringing or silence. | | `wrong_number` | The person on the other end indicated this is the wrong number. | | `not_interested` | The person explicitly declined or showed no interest. | | `callback_requested` | The person asked to be called back at a later time. | | `meeting_scheduled` | A meeting or appointment was scheduled on the call. | | `information_provided` | Information was exchanged but no clear next step was set. | | `no_speech` | The transcript was empty (no speech to classify). | | `unknown` | Truly cannot determine from the transcript. Used sparingly. | ### Status codes - **200** — Call logs returned - **400** — Invalid query parameter (limit/offset/call_log_timestamp/dates/pb_line_id) - **401** — Missing or invalid API key - **429** — Rate limit exceeded - **500** — Internal server error **Request — cURL** ```bash curl -G https://api.tryprojectblue.com/get-call-logs-api \ -H "Authorization: Bearer YOUR_API_KEY" \ --data-urlencode "pb_line_id=6121307b-c29e-41d5-426b-46b679ab8648" \ --data-urlencode "answered_at_gte=2026-04-01T00:00:00Z" \ --data-urlencode "answered_at_lte=2026-05-01T00:00:00Z" \ --data-urlencode "call_log_timestamp=asc" \ --data-urlencode "limit=50" ``` **Request — Pagination** ```bash # page 1 curl ".../get-call-logs-api?limit=100&offset=0" # page 2 curl ".../get-call-logs-api?limit=100&offset=100" # stop when data.length < limit, or offset >= pagination.total ``` **Request — Last 24h** Outbound calls for one line in the last day. ```bash GTE=$(date -u -v-24H +"%Y-%m-%dT%H:%M:%SZ") # macOS curl -sS \ -H "Authorization: Bearer $PB_API_KEY" \ "https://api.tryprojectblue.com/get-call-logs-api?pb_line_id=$LINE_ID&answered_at_gte=$GTE" ``` **Request — By disposition** The endpoint has no disposition filter — filter client-side. ```bash curl -sS -H "Authorization: Bearer $PB_API_KEY" \ "https://api.tryprojectblue.com/get-call-logs-api?limit=100" \ | jq '.data | map(select(.disposition == "answered"))' ``` **Response — 200 OK** ```json { "status": "OK", "data": [ { "id": "cmorpmiw5fyb513ynkuz8jr39", "line_id": "6121307b-c29e-41d5-426b-46b679ab8648", "from_number": "+16027184932", "to_number": "+18016966474", "status": "completed", "disposition": "answered", "transcript": "Speaker A: Hey Colton, how are you?\nSpeaker B: This is Camila from Project Blue…", "duration_seconds": 168, "answered_at": "2026-05-04T21:24:06.882Z", "ended_at": "2026-05-04T21:26:53.882Z", "recording_url": "https:///call-recordings/<...>.mp3" }, { "id": "cmorbzz12abcd13ynxxxxxxxx", "line_id": "6121307b-c29e-41d5-426b-46b679ab8648", "from_number": "+16027184932", "to_number": "+18015550199", "status": "no-answer", "disposition": null, "transcript": null, "duration_seconds": null, "answered_at": null, "ended_at": "2026-05-04T20:11:08.000Z", "recording_url": null } ], "pagination": { "limit": 100, "offset": 0, "total": 910 } } ``` **Response — 400 — line** ```json { "error": "Invalid or unavailable pb_line_id for this API key user." } ``` **Response — 400 — date** ```json { "error": "answered_at_gte is not a valid ISO-8601 date" } ``` **Response — 400 — depth** offset + limit may not exceed 2000. ```json { "error": "Pagination depth too deep. offset+limit must be <= 2000" } ```