GET /api/v1/calendar
Returns the full merged view a rep sees on their in-app calendar for a date range: task/appointments, deal close dates, scheduled campaign sends, follow-ups due, and contact birthdays — all in one query. Requires the read:calendar scope (or * for full access).
This is different from GET /api/v1/tasks, which only returns raw Task rows. GET /api/v1/calendar additionally surfaces deal closes, campaign sends, follow-ups, and birthdays, and reshapes every kind into one common entry format — see the Calendar entry object for the full field-by-field breakdown.
This endpoint is read-only. There is no write path here — booking or cancelling an appointment goes through POST /api/v1/tasks: create a task with type: "MEETING" and a clock-time dueDate, and it shows up here as a task entry.
Request
GET /api/v1/calendar?from=2026-09-08&to=2026-09-12 HTTP/1.1
Host: agentlyleads.com
Authorization: Bearer alk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxQuery parameters
| Parameter | Description |
|---|---|
from | YYYY-MM-DD. First day of the range. Defaults to today's date in the workspace's own timezone. |
to | YYYY-MM-DD, inclusive. Last day of the range. Defaults to 7 days after from. |
kind | Filter to one or more of task, deal-close, campaign, followup, birthday. Repeatable (?kind=task&kind=deal-close) and/or comma-separated (?kind=task,deal-close) — both forms work and can be combined. Omit to return every kind. |
All parameters are optional. The range from from to to cannot exceed 90 days — a wider request returns a 400.
Only appointments and deal closes:
GET /api/v1/calendar?from=2026-09-08&to=2026-09-12&kind=task,deal-close HTTP/1.1
Authorization: Bearer alk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxResponse — 200
{
"from": "2026-09-08",
"to": "2026-09-12",
"timeZone": "America/New_York",
"entries": [
{
"id": "task:cmq7task0alk34567890",
"kind": "task",
"date": "2026-09-10",
"startAt": "2026-09-10T18:00:00.000Z",
"endAt": "2026-09-10T18:30:00.000Z",
"allDay": false,
"title": "Discovery call with Acme",
"href": "/tasks",
"meta": "Jane Buyer",
"done": false,
"taskId": "cmq7task0alk34567890",
"seriesId": null
},
{
"id": "deal:cmq3deal0alk34567890",
"kind": "deal-close",
"date": "2026-09-12",
"startAt": null,
"endAt": null,
"allDay": true,
"title": "Close: Acme Corp — Annual Contract",
"href": "/deals/cmq3deal0alk34567890",
"meta": "$12,000 · QUALIFIED"
}
]
}from/toecho back the resolved range (after defaults are applied), not necessarily what you passed.timeZoneis the workspace's IANA timezone — the framedatevalues are bucketed in.entriesis a flat, already-sorted list mixing every requested kind. See the Calendar entry object for what each field means and how it differs bykind— in particular, onlytaskentries carrydone,taskId, andseriesId, and only a timed task has non-nullstartAt/endAt.
There is no pagination on this endpoint — the 90-day range cap keeps a single response bounded.
What's never in the response
A workspace's connected Google/Outlook calendar ("external" busy time, shown in the in-app calendar UI) is never included here. Those events are only fetched for a specific signed-in user, and a workspace API key has no single "current user" to attribute them to — including them would leak whichever user's personal calendar to every caller of the key. See The Calendar entry object for more.