> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goliathdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tasks API

> Create, list, reschedule, and complete CRM to-do tasks through the Goliath developer API

## About

A task is one actionable line item — a follow-up call, a document to chase, a
step in an onboarding SOP. It has a title, an optional description, a due date,
and assignees, and it gets checked off when the work is done.

Two things a task is *not*:

* **A calendar event.** Something with a start time and attendees is an
  appointment — see the [Appointments API](/developer-api/appointments).
* **A background job.** The async jobs that ops like `addContactTags` return a
  `bulkTaskId` for live under the [Bulk Tasks API](/developer-api/bulk-tasks),
  and are unrelated to the CRM tasks on this page.

Tasks anchor either to a **contact** (the usual case — follow-ups on a person)
or directly to a **deal** (pipeline work that belongs to the deal itself, with
no contact involved). Which one it is determines how you complete it, so the
distinction matters — see the callout below.

All operations go through the developer API gateway — one endpoint, called by
`operationId`. If you haven't set up a key yet, start with the
[Developer API Overview](/developer-api/overview).

## Operations

### Reading tasks (`READ` scope)

| operationId        | What it does                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `listMyTasks`      | The working queue — open and completed tasks, filterable by `taskStatus` (`OVERDUE` \| `TODAY` \| `FUTURE`), `completed`, a `dueBefore`/`dueAfter` window, `participants`, and `searchTerm`. Pass `timezone` so day boundaries land correctly. Returns each task's `dueDate`, `completedAt`, and its linked contact (id + name) — plus the unpaged total. Capped at 50 per call; narrow the date window to page, as there is no cursor. |
| `listContactTasks` | Every task on one contact by `contactId` — title, description, `dueDate`, `completedAt`, and assigned participants. Use it to review outstanding work before a call, or to find the `taskId` + `contactId` pair the write operations need.                                                                                                                                                                                              |

<Note>
  **What `listMyTasks` returns depends on the key's role**

  A `MEMBER` or `ISA` key always sees only the key owner's own tasks, whatever
  filters you pass. A team-admin key with no `participants` filter gets the
  org's feed **narrowed to contacts the key owner can access** — tasks on
  contacts visible only to teammates are silently omitted, so don't treat that
  default as a complete org backlog. To read a specific teammate's queue, pass
  their `userIds` in `participants` (from `listTeammates`, same-org only).
</Note>

### Writing tasks (`WRITE` scope)

| operationId           | What it does                                                                                                                                                                                                                                                                         |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `createTaskOnContact` | Create a task on a contact. Requires `contactId`, `title`, `dueDate`, and `timezone`; optional `description`, `taskType` (free-text label like `Call`), `participants`, and `dealIds` to also link it to deals.                                                                      |
| `createTaskOnDeal`    | Create a task attached directly to a deal, with no contact. Requires `dealId`, `title`, `dueDate`, and `timezone`; optional `description`, `taskType`, and `participants`. For pipeline work that belongs to the deal rather than to a person.                                       |
| `updateTask`          | Edit a task by `taskId` + its linked `contactId`. Patch semantics — only the fields you pass change. This is how you reschedule ("push that follow-up to Friday"): update in place rather than deleting and recreating. Passing `participants` **replaces** the whole assignee list. |
| `completeTask`        | Tick off a task that has a contact, by `taskId` + `contactId`. Also writes the completion onto that contact's timeline. Pass `isCompleted: false` to reopen one completed by mistake.                                                                                                |
| `completeTaskById`    | Tick off a task that has **no** contact, by `taskId` alone. Refuses a task that does have a contact rather than quietly skipping the timeline entry.                                                                                                                                 |
| `deleteTask`          | Permanently delete one task by `taskId` + `contactId`. No undo. One task per call — there is no bulk delete.                                                                                                                                                                         |

<Warning>
  **A task with no participants is invisible**

  `participants` (teammate `userId`s — from `getMyProfile` for the key owner, or
  `listTeammates` for a colleague) is what puts a task in someone's queue. Create
  a task without them and it is **unassigned**: it exists, but it will never
  appear in anyone's `listMyTasks`. This is the most common way a scripted
  checklist silently goes missing.
</Warning>

<Note>
  **Which complete operation to use**

  `listMyTasks` tells you: if a task comes back with `contact: null`, there is no
  `contactId` to pass and `completeTask` cannot touch it — use `completeTaskById`.
  If it has a contact, use `completeTask`, which records the completion on that
  contact's timeline as well. `completeTaskById` refuses a task that has a
  contact, so an error there means you want the other operation.
</Note>

<Note>
  **Due dates are a local day, not an instant**

  `timezone` (`PST`, `MST`, `CST`, `EST`, …) is the zone the due date's day is
  read in, and it decides which `TODAY` / `OVERDUE` bucket the task lands in.
  Send the user's own zone, and for a day-level request ("follow up Friday")
  pick an end-of-business time in that zone rather than a bare midnight.
</Note>

<Note>
  **No bulk create, and no re-anchoring**

  There is no multi-task call: a checklist is built by calling
  `createTaskOnContact` once per step, in order, with staggered due dates. The
  response echoes the contact's full task list every time, so the last call
  confirms the whole set landed.

  A task also cannot be moved to a different contact. `contactId` on `updateTask`
  *identifies* the task's existing contact — any other contact is rejected.
  Delete-and-recreate is not equivalent: a fresh task loses the original's
  `completedAt` history, created date, and notification links.
</Note>

<Note>
  **Organization guard**

  Every id you pass is org-guarded before the operation runs: `taskId` (via its
  linked contact, or via an in-org participant for a contact-less task),
  `contactId`, `dealId`/`dealIds`, and `participants` user ids. The write
  operations additionally **bind the pair** — a foreign task id can never be
  completed or edited under a contact you do own, and vice versa. See
  [Authorization](/developer-api/authorization) for the model.
</Note>

## Example

List everything overdue, then complete one of them:

```bash theme={null}
curl -X POST https://server.goliathdata.com/api/v1/call \
  -H "Authorization: Bearer gsk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "operationId": "listMyTasks", "variables": { "taskStatus": "OVERDUE", "timezone": "PST" } }'
```

```bash theme={null}
curl -X POST https://server.goliathdata.com/api/v1/call \
  -H "Authorization: Bearer gsk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "operationId": "completeTask", "variables": { "taskId": "YOUR_TASK_ID", "contactId": "YOUR_CONTACT_ID", "isCompleted": true } }'
```

Full variable schemas, response shapes, and worked examples for every
operation are available from the
[discovery endpoint](/developer-api/overview#discovering-operations).
