# Tasks and calendar

> List, create, update and delete tasks, read a calendar window and find free times through the Fondaro API.

Tasks hang on leads. The calendar shows the key's person what is on their day. Reading needs `crm:read`; creating, changing and deleting tasks need `crm:write` and an active plan.

- **Tasks.** A member creates and reads tasks on leads they can reach. Ticking or unticking a task is limited to its owner, a teammate on it, or an admin. Reassigning (`assigneeIds`) is admin-only. A lead or task you cannot reach answers `404` with "Lead not found." or "Task not found.".
- **Calendar.** Always the key's person's own calendar, member or admin.

## Set a task's due date

A task's `dueDate` takes either form:

- `YYYY-MM-DD`: due that day with no time. It is stored and returned as midnight UTC on that date.
- A full ISO 8601 timestamp with an offset, such as `2026-10-12T09:30:00+02:00`: that exact moment.

The calendar routes take plain `YYYY-MM-DD` dates and a required `tz`, an IANA time zone such as `Europe/Madrid`. The dates are days in that zone, and `to` is exclusive. A request without `tz` answers `400`.

## List tasks

`GET /v1/tasks`

Without `leadId`, at most 500 tasks the key's person owns or is on. There is no agency-wide task list, even for admins. With `leadId`, that lead's tasks. `hasMore` is `true` only when the 500-row limit cut the results.

| Parameter | In | Type | Required | Description |
|-----------|----|------|----------|-------------|
| `leadId` | Query | integer | No | Only tasks on this lead. A member needs access to the lead |
| `status` | Query | string | No | `pending` or `completed`. Applies only without `leadId` |

```bash
curl "https://api.fondaro.com/v1/tasks?leadId=1042" \
  -H "Authorization: Bearer $FONDARO_API_KEY"
```

```json
{
  "data": [
    {
      "id": "3f6c2a10-0000-4000-8000-000000000008",
      "leadId": 1042,
      "assigneeIds": ["user_2abcDEF1234567890ghiJKL"],
      "createdBy": "user_2abcDEF1234567890ghiJKL",
      "title": "Viewing follow-up",
      "description": null,
      "dueDate": "2026-10-12T00:00:00.000Z",
      "status": "pending",
      "completedAt": null,
      "createdAt": "2026-10-04T12:02:13.420Z",
      "updatedAt": "2026-10-04T12:02:13.420Z"
    }
  ],
  "hasMore": false
}
```

## Create a task

`POST /v1/tasks`

Creates a task on a lead. The owner defaults to the key's person. Accepts an `Idempotency-Key` header.

| Parameter | In | Type | Required | Description |
|-----------|----|------|----------|-------------|
| `leadId` | Body | integer | Yes | The lead the task is on. A member needs access to it |
| `title` | Body | string | Yes | The task title |
| `description` | Body | string | No | More detail |
| `dueDate` | Body | string | No | `YYYY-MM-DD` or an ISO 8601 timestamp with an offset |
| `assigneeIds` | Body | string or string[] | No | Owners other than the key's person |
| `teamIds` | Body | UUID or UUID[] | No | Put the task on every member of these teams |

```bash
curl -X POST https://api.fondaro.com/v1/tasks \
  -H "Authorization: Bearer $FONDARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "leadId": 1042, "title": "Viewing follow-up", "dueDate": "2026-10-12" }'
```

The `201` response is the task, as in the list above. Errors: `404` "Lead not found." for a lead you cannot reach.

## Update a task

`PATCH /v1/tasks/{taskId}`

Changes the title, description, due date or status. Send `status: "completed"` to tick it and `"pending"` to untick it. Reassigning with `assigneeIds` or `teamIds` is admin-only.

| Parameter | In | Type | Required | Description |
|-----------|----|------|----------|-------------|
| `taskId` | Path | string | Yes | The id of the task |
| `title` | Body | string | No | New title |
| `description` | Body | string | No | New description |
| `dueDate` | Body | string | No | `YYYY-MM-DD` or an ISO 8601 timestamp with an offset |
| `status` | Body | string | No | `pending` or `completed` |
| `assigneeIds` | Body | string or string[] | No | Admins only |
| `teamIds` | Body | UUID or UUID[] | No | Admins only |

```bash
curl -X PATCH https://api.fondaro.com/v1/tasks/3f6c2a10-0000-4000-8000-000000000008 \
  -H "Authorization: Bearer $FONDARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "completed" }'
```

The response is the task with `"status": "completed"` and a `completedAt` time. Errors: `403` when you may not tick it or may not reassign; `404` "Task not found."

## Delete a task

`DELETE /v1/tasks/{taskId}`

Permanently deletes a task. Only its owner, a teammate on it, or an admin can.

| Parameter | In | Type | Required | Description |
|-----------|----|------|----------|-------------|
| `taskId` | Path | string | Yes | The id of the task |

```bash
curl -X DELETE https://api.fondaro.com/v1/tasks/3f6c2a10-0000-4000-8000-000000000008 \
  -H "Authorization: Bearer $FONDARO_API_KEY"
```

The response is `204` with no body.

## Read the calendar

`GET /v1/calendar`

The key's person's calendar for a window of days: meetings, viewings, tasks, open houses, expected deal closes and connected appointments. The window is at most 42 days. If more items exist than one response holds, `truncated` is `true`: ask for a shorter window.

| Parameter | In | Type | Required | Description |
|-----------|----|------|----------|-------------|
| `from` | Query | string | Yes | First day, `YYYY-MM-DD`, in `tz` |
| `to` | Query | string | Yes | The day after the last day (exclusive), `YYYY-MM-DD`. At most 42 days after `from` |
| `tz` | Query | string | Yes | IANA time zone, 1 to 64 characters, such as `Europe/Madrid` |

```bash
curl "https://api.fondaro.com/v1/calendar?from=2026-10-05&to=2026-10-12&tz=Europe%2FMadrid" \
  -H "Authorization: Bearer $FONDARO_API_KEY"
```

```json
{
  "window": { "from": "2026-10-05", "to": "2026-10-12", "tz": "Europe/Madrid" },
  "truncated": false,
  "items": [
    {
      "kind": "meeting",
      "title": "Weekly sales meeting",
      "startsAt": "2026-10-05T07:00:00.000Z",
      "endsAt": "2026-10-05T07:45:00.000Z",
      "allDay": false,
      "status": "confirmed",
      "leadId": null,
      "eventId": "3f6c2a10-0000-4000-8000-000000000020",
      "attendeeCount": 0,
      "done": false,
      "overdue": false
    }
  ]
}
```

Items carry `startsAt` and `endsAt` in UTC. Errors: `400` for a missing `tz`, an unknown time zone, or a window over 42 days.

## Find free times

`GET /v1/calendar/free-times`

When the key's person is free for a meeting or viewing of a given length, inside their working hours, on the half hour, earliest first. The window is at most 14 days. Pass `leadId` to also leave out times when that lead already has something.

| Parameter | In | Type | Required | Description |
|-----------|----|------|----------|-------------|
| `from` | Query | string | Yes | First day, `YYYY-MM-DD`, in `tz` |
| `to` | Query | string | Yes | The day after the last day (exclusive). At most 14 days after `from` |
| `tz` | Query | string | Yes | IANA time zone. Required |
| `durationMinutes` | Query | integer | Yes | 15 to 480 |
| `leadId` | Query | integer | No | A lead you can reach. Its own busy times are left out too |

```bash
curl "https://api.fondaro.com/v1/calendar/free-times?from=2026-10-05&to=2026-10-06&tz=Europe%2FMadrid&durationMinutes=30" \
  -H "Authorization: Bearer $FONDARO_API_KEY"
```

```json
{
  "timeZone": "Europe/Madrid",
  "durationMinutes": 30,
  "slots": [
    { "startsAt": "2026-10-05T06:00:00.000Z", "endsAt": "2026-10-05T06:30:00.000Z" },
    { "startsAt": "2026-10-05T06:30:00.000Z", "endsAt": "2026-10-05T07:00:00.000Z" }
  ]
}
```

Errors: `400` for a missing `tz` or a window over 14 days; `404` "Lead not found." when `leadId` is not yours.

Source: https://www.fondaro.com/docs/api/v1/tasks-and-calendar
