agentlyleads docs
Tasks API

The Task object

The following fields are accepted on write via POST /api/v1/tasks.

A task is also how calendar appointments work in agentlyleads: a timed task — one whose dueDate carries a clock time — shows up on the CRM calendar as an appointment. An all-day task — a bare date, or no dueDate at all — is a plain to-do with no clock time.

FieldTypeNotes
idstringCUID, assigned on create (read-only)
titlestring (required)Max 200 characters. What the task/appointment is
dueDatestring | nullWhen it's due/starts. Three accepted shapes — see below
allDaybooleanNormally inferred from dueDate's shape; set to override
endAtstring | nullWhen it stops (same shapes as dueDate). Only meaningful on a timed entry; must be after dueDate
descriptionstring | nullMax 5,000 characters. Free text — agenda, call notes, etc.
typeenumTODO (default) · CALL · EMAIL · MEETING — use MEETING for an appointment
priorityenumLOW · MEDIUM (default) · HIGH
donebooleanDefaults to false
externalIdstring | nullYour system's ID — upsert key and dedupe handle (max 200 chars)
contactIdstring | nullLink to an existing contact by its agentlyleads record ID
leadIdstring | nullLink to an existing lead by its agentlyleads record ID
dealIdstring | nullLink to an existing deal by its agentlyleads record ID
contactExternalIdstring | nullResolve the linked contact by its externalId instead of contactId (max 200 chars)
leadExternalIdstring | nullResolve the linked lead by its externalId instead of leadId (max 200 chars)
dealExternalIdstring | nullResolve the linked deal by its externalId instead of dealId (max 200 chars)
assigneeIdstring | nullWorkspace user to assign to, by user ID
assigneeEmailstring | nullResolve the assignee by their workspace login email instead of assigneeId
createdAtstring (ISO 8601)Assigned on create (read-only)
updatedAtstring (ISO 8601)Updated on every write (read-only)

The dueDate/endAt shapes

This is the part that's easy to get wrong, so read it before you send your first booking. dueDate and endAt each accept three shapes, and the shape you send controls how the value is read:

1. A bare date"YYYY-MM-DD", e.g. "2026-09-10". An all-day entry, no clock time. This is a plain to-do.

2. A datetime with no timezone offset — e.g. "2026-09-10T14:00:00" or "2026-09-10T14:00". Read as wall-clock time in the workspace's own timezone. This is what turns the row into a timed appointment that shows on the calendar with a clock time.

Do not send Z or a +HH:MM offset for this shape, or it will be read as that exact UTC/offset instant instead of the workspace's local time — almost never what you want for a booking made in local time.

3. A datetime with a Z or offset — e.g. "2026-09-10T18:00:00Z". Treated as an exact instant and converted for display. Use this only when you deliberately already have a UTC/offset timestamp — not for a wall-clock booking time.

Omit dueDate (or send null) for no due date.

allDay and endAt

allDay is normally inferred from dueDate's shape above — you don't need to set it. Set it explicitly only to override that inference.

endAt is only meaningful on a timed entry: it turns a 2pm call into a 2–3pm meeting. On an all-day entry it's ignored/cleared. When present, endAt must be after dueDate.

Example object — a timed appointment

{
  "id": "cmq7task0alk34567890",
  "title": "Discovery call with Acme",
  "done": false,
  "dueDate": "2026-09-10T14:00:00.000Z",
  "allDay": false,
  "endAt": "2026-09-10T14:30:00.000Z",
  "description": null,
  "type": "MEETING",
  "priority": "MEDIUM",
  "externalId": "booking_9F3K2",
  "contact": { "name": "Jane Buyer", "externalId": "hs_contact_123" },
  "lead": null,
  "deal": null,
  "createdAt": "2025-06-01T12:00:00.000Z",
  "updatedAt": "2025-06-01T12:00:00.000Z"
}

dueDate/endAt are always returned as full ISO 8601 datetimes on read, regardless of the shape you wrote them in.

Notes on specific fields

title is the only required field. All other fields are optional on write.

externalId is the upsert key. A row with an externalId that matches an existing task in the workspace updates that task instead of creating a duplicate. It's also required to later reference this task from GET/DELETE by external ID — strongly recommended for anything you might need to update or cancel later, like a booking-site appointment.

Linking a contact, lead, or deal can be done either by agentlyleads record ID (contactId/leadId/dealId) or by an external system's ID (contactExternalId/leadExternalId/dealExternalId), which is resolved against that record's own externalId. If an *ExternalId is supplied but no matching record exists in the workspace, that row fails — it does not fall back to creating an unlinked task.

assigneeId/assigneeEmail picks which workspace user (sales rep or staff member) the appointment is assigned to. Omit both to leave it unassigned.

Recurring/repeating appointments are not supported via this endpoint — each occurrence must be created as its own row. Recurrence exists in the product via the MCP tools schedule_appointment/manage_task, not yet via public REST.

On this page