
# Tasks API

Tasks are the to-dos and follow-ups attached to your account — optionally linked to a contact, deal, or campaign. They move through the **stages** of your task board (your kanban columns) and have a **type** and **priority**. This guide covers managing them over the API.

- **Base URL** — `https://api.youraiconnector.com/v1`
- **Authentication** — your API key (see [Authentication](authentication.md))
- **Errors & paging** — see [Errors & Pagination](errors-and-pagination.md)

All examples below show the `?apiKey=` query form in cURL and the `X-API-Key` header in JavaScript and Python — either works on every endpoint.

---

## The task object

```json
{
  "id": "tsk_abc123",
  "title": "Call Jane about her quote",
  "description": "She asked for pricing on the annual plan.",
  "type": "to_do",
  "priority": "high",
  "stage": "stage-1",
  "due_date": "2026-06-15T09:00:00.000Z",
  "remind_before_minutes": 15,
  "contact": "contacts/uid_whatsapp_15551234567",
  "campaign": "campaigns/abc123",
  "tags": ["sales"],
  "notes": "",
  "source": "api"
}
```

- **`type`** — `to_do`, `faq_update`, or your configured task types (see [List task types](#list-task-types)).
- **`priority`** — `none`, `low`, `normal`, `high`, or `urgent`.
- **`stage`** — the id of a stage on your task board (see [List task stages](#list-task-stages)). When omitted on create, the task lands in your first stage.
- **`remind_before_minutes`** — how many minutes before `due_date` to send a reminder. `0` means at the due time; omit it or send `null` for no reminder. Must be a whole number from `0` to `1440` (1 day) — anything larger is rejected. The reminder needs a `due_date` to fire, and rescheduling the task moves the reminder with it.

---

## Create a task

`POST /tasks` — only `title` is required.

::: note
**Note:** `due_date` accepts an ISO 8601 timestamp, including a time of day. Pair it with `remind_before_minutes` to have the reminder delivered on your **Tasks** notification settings. `contact_id`, `deal_id`, and `campaign_id` link the task to those records. `assigned_to` is a team member's user id.
:::


> **Getting `assigned_to` right.** It should be the user id of the account owner or of an active team member on the same account. This endpoint does not currently check that, so an id belonging to nobody is accepted and stored exactly as you sent it — you still get a `201`. Copy the id rather than retyping it: these ids mix `l` with `L` and the letter `O` with the digit `0`, and one wrong character is enough. To check what you actually sent, open the task in the dashboard: the **Assignee** field on the task record falls back to showing the raw id when it matches nobody, and the assignee picker in **Edit task** shows **Unassigned**.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/tasks?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Call Jane about her quote",
    "priority": "high",
    "due_date": "2026-06-15T09:00:00.000Z",
    "contact_id": "uid_whatsapp_15551234567",
    "tags": ["sales"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/tasks", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    title: "Call Jane about her quote",
    priority: "high",
    due_date: "2026-06-15T09:00:00.000Z",
    contact_id: "uid_whatsapp_15551234567",
    tags: ["sales"],
  }),
});
const data = await res.json();
console.log(data.task_id);
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/tasks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "title": "Call Jane about her quote",
        "priority": "high",
        "due_date": "2026-06-15T09:00:00.000Z",
        "contact_id": "uid_whatsapp_15551234567",
        "tags": ["sales"],
    },
)
print(res.json()["task_id"])
```

**Response** (`201`)

```json
{ "success": true, "task_id": "tsk_abc123", "task": { "title": "Call Jane about her quote", "...": "..." } }
```

---

## List tasks

`GET /tasks` — returns the tasks for your account, with optional filters.

**Query parameters** (all optional): `stage`, `priority`, `contact_id`, `deal_id`, `assigned_to`, `due_before`, `due_after` (ISO timestamps).

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/tasks?apiKey=YOUR_API_KEY&stage=stage-1&priority=high"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/tasks?stage=stage-1&priority=high", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { tasks } = await res.json();
```

**Python**

```python
res = requests.get(
    "https://api.youraiconnector.com/v1/tasks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"stage": "stage-1", "priority": "high"},
)
tasks = res.json()["tasks"]
```

**Response** (`200`)

```json
{ "success": true, "tasks": [{ "id": "tsk_abc123", "title": "Call Jane about her quote", "...": "..." }] }
```

---

## Search tasks

`POST /tasks/search` — full-text match on title and description, with the same optional filters as listing.

```bash
curl -X POST "https://api.youraiconnector.com/v1/tasks/search?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "quote", "priority": "high" }'
```

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/tasks/search", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ query: "quote", priority: "high" }),
});
```

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/tasks/search",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"query": "quote", "priority": "high"},
)
```

---

## Get a task

`GET /tasks/{taskId}`

```bash
curl "https://api.youraiconnector.com/v1/tasks/tsk_abc123?apiKey=YOUR_API_KEY"
```

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/tasks/tsk_abc123", { headers: { "X-API-Key": "YOUR_API_KEY" } });
```

```python
res = requests.get("https://api.youraiconnector.com/v1/tasks/tsk_abc123", headers={"X-API-Key": "YOUR_API_KEY"})
```

A task that doesn't exist on your account returns `404`.

---

## Update a task

`PUT /tasks/{taskId}` — send only the fields you want to change (`title`, `description`, `type`, `priority`, `stage`, `due_date`, `remind_before_minutes`, `contact_id`, `deal_id`, `assigned_to`, `tags`, `notes`).

```bash
curl -X PUT "https://api.youraiconnector.com/v1/tasks/tsk_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "priority": "urgent", "notes": "Left a voicemail." }'
```

```javascript
await fetch("https://api.youraiconnector.com/v1/tasks/tsk_abc123", {
  method: "PUT",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ priority: "urgent", notes: "Left a voicemail." }),
});
```

```python
requests.put(
    "https://api.youraiconnector.com/v1/tasks/tsk_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"priority": "urgent", "notes": "Left a voicemail."},
)
```

---

## Complete a task

`POST /tasks/{taskId}/complete` — moves the task to your board's completed stage. An optional `notes` field records a closing note.

```bash
curl -X POST "https://api.youraiconnector.com/v1/tasks/tsk_abc123/complete?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "notes": "Closed — customer signed up." }'
```

```javascript
await fetch("https://api.youraiconnector.com/v1/tasks/tsk_abc123/complete", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ notes: "Closed — customer signed up." }),
});
```

```python
requests.post(
    "https://api.youraiconnector.com/v1/tasks/tsk_abc123/complete",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"notes": "Closed — customer signed up."},
)
```

---

## Move & reorder (kanban)

**Move a task to another stage** — `POST /tasks/{taskId}/move` with `new_stage_id` (the destination stage) and `new_position` (the zero-based slot within that stage; required, must be a non-negative integer):

```bash
curl -X POST "https://api.youraiconnector.com/v1/tasks/tsk_abc123/move?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "new_stage_id": "stage-2", "new_position": 0 }'
```

**Reorder tasks within a stage** — `POST /tasks/reorder` with `stage_id` and the task ids in their new order:

```bash
curl -X POST "https://api.youraiconnector.com/v1/tasks/reorder?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "stage_id": "stage-1", "ordered_task_ids": ["tsk_3", "tsk_1", "tsk_2"] }'
```

```javascript
await fetch("https://api.youraiconnector.com/v1/tasks/reorder", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ stage_id: "stage-1", ordered_task_ids: ["tsk_3", "tsk_1", "tsk_2"] }),
});
```

```python
requests.post(
    "https://api.youraiconnector.com/v1/tasks/reorder",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"stage_id": "stage-1", "ordered_task_ids": ["tsk_3", "tsk_1", "tsk_2"]},
)
```

---

## Tasks for a contact

`GET /tasks/contact/{contactId}` — every task linked to one contact.

```bash
curl "https://api.youraiconnector.com/v1/tasks/contact/uid_whatsapp_15551234567?apiKey=YOUR_API_KEY"
```

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/tasks/contact/uid_whatsapp_15551234567", { headers: { "X-API-Key": "YOUR_API_KEY" } });
```

```python
res = requests.get("https://api.youraiconnector.com/v1/tasks/contact/uid_whatsapp_15551234567", headers={"X-API-Key": "YOUR_API_KEY"})
```

---

## Task board configuration

### List task stages

`GET /tasks/stages` — your board's columns, in order. Use a stage `id` as the `stage` field when creating or moving tasks.

```bash
curl "https://api.youraiconnector.com/v1/tasks/stages?apiKey=YOUR_API_KEY"
```

```json
{ "success": true, "stages": [{ "id": "stage-1", "name": "To Do", "is_completed_stage": false }, { "id": "stage-done", "name": "Done", "is_completed_stage": true }] }
```

### Update task stages

`PUT /tasks/stages` — replace your board's stage configuration. Send the full ordered `stages` array.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/tasks/stages?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "stages": [
    { "id": "stage-1", "name": "To Do", "is_completed_stage": false },
    { "id": "stage-2", "name": "In Progress", "is_completed_stage": false },
    { "id": "stage-done", "name": "Done", "is_completed_stage": true }
  ] }'
```

### List task types

`GET /tasks/types` — the task types configured on your account (used as the `type` field).

```bash
curl "https://api.youraiconnector.com/v1/tasks/types?apiKey=YOUR_API_KEY"
```

---

## Approve an FAQ suggestion

When the AI bot proposes a new FAQ, it creates a task of type `faq_update`. `POST /tasks/{taskId}/approve-faq` turns that suggestion into a real FAQ in the knowledge base of the AI agent that raised it and completes the task. You can override the question/answer in the body.

Add `"send_follow_up": true` to also have the AI send the answer to the task's linked contact right away, as a natural message in that chat (the same thing the **Send the answer to the contact now** toggle does in the app). The reply goes out through the AI agent that handles that contact.

```bash
curl -X POST "https://api.youraiconnector.com/v1/tasks/tsk_faq99/approve-faq?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "question": "Do you offer refunds?", "answer": "Yes, within 30 days.", "send_follow_up": true }'
```

```json
{ "success": true, "faq_id": "faq_xyz", "task_id": "tsk_faq99", "follow_up_status": "published" }
```

`follow_up_status` tells you what happened to the message: `not_requested` (flag not set), `published` (sent), `queued` (the bot was mid-reply to that contact, the answer goes out as soon as it finishes), `skipped_no_contact` (the task has no linked contact), `skipped_no_campaign` (no agent or campaign could answer for that contact) or `skipped_error`. The FAQ is created in every case.

See the [FAQs API](faqs.md) to manage the resulting FAQ.

---

## Delete a task

`DELETE /tasks/{taskId}`

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/tasks/tsk_abc123?apiKey=YOUR_API_KEY"
```

```javascript
await fetch("https://api.youraiconnector.com/v1/tasks/tsk_abc123", { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } });
```

```python
requests.delete("https://api.youraiconnector.com/v1/tasks/tsk_abc123", headers={"X-API-Key": "YOUR_API_KEY"})
```

---

## Next steps

- [Contacts API](contacts.md) — link tasks to the right contact
- [Webhooks API](webhooks.md) — get notified on `Task Created`, `Task Updated`, and `Task Completed`
- [API Reference](reference.md) — the full interactive endpoint explorer
