agentlyleads docs
Calendar API

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Query parameters

ParameterDescription
fromYYYY-MM-DD. First day of the range. Defaults to today's date in the workspace's own timezone.
toYYYY-MM-DD, inclusive. Last day of the range. Defaults to 7 days after from.
kindFilter 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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Response — 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/to echo back the resolved range (after defaults are applied), not necessarily what you passed.
  • timeZone is the workspace's IANA timezone — the frame date values are bucketed in.
  • entries is a flat, already-sorted list mixing every requested kind. See the Calendar entry object for what each field means and how it differs by kind — in particular, only task entries carry done, taskId, and seriesId, and only a timed task has non-null startAt/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.

On this page