# Tasks

A **task** is a schedule that creates jobs. Where a [job](../jobs/) runs an operation once, a task runs
it again and again — every night, every Monday, the first day of every month — creating one job per
execution.

```bash
POST /v80/operation/tasks
```

A task wraps a complete job request in its `job.request` field, so everything you know about jobs
applies: the operation name, its parameters, the target, the per-operation timeouts and the callback.
What the task adds on top is *when and how often*.

```mermaid
flowchart LR
    T["Task<br>schedule + job template"] --> J1["Job<br>run 1"]
    T --> J2["Job<br>run 2"]
    T --> JN["Job<br>run N"]
    J1 --> O1["operations<br>per entity"]
    J2 --> O2["operations<br>per entity"]
    JN --> ON["operations<br>per entity"]
```

## The task schedule

| Field | Purpose |
|---|---|
| `schedule.start` | First execution. Defaults to now when omitted. |
| `schedule.stop` | When to stop: a `date`, a number of `executions`, or nothing at all — which means forever. |
| `schedule.repeating.period` | Repeat every *n* time units. |
| `schedule.repeating.pattern` | Repeat on a calendar pattern: weekly, monthly or yearly. |
| `active` | When `false`, no jobs are launched. |
| `state` | Current task state: `ACTIVE`, `INACTIVE`, `FINISHED`, `CANCELLING`, `CANCELLED`. |

### Repeating by period

`period` repeats on a fixed interval — `each` time units of `unit`, where `unit` is one of `SECONDS`,
`MINUTES`, `HOURS` or `DAYS`.

### Repeating by calendar pattern

`pattern` targets specific calendar positions, optionally pinned to a `time` of day in
`hh:mm:ssTZD` format:

| Pattern | Fields | Values |
|---|---|---|
| `weekly` | `days` | `MON`, `TUE`, `WED`, `THU`, `FRI`, `SAT`, `SUN` — at least one |
| `monthly` | `day`, `months` | Day `1`–`31`; months `JAN` … `DEC` |
| `yearly` | `day`, `months` | Day `1`–`31`; months `JAN` … `DEC` |

Example: a reboot every Monday and Wednesday at 10:30 UTC, stopping after 10 executions.

```json
{
  "task": {
    "id": "task_1",
    "name": "task_1_name",
    "description": "example task request",
    "active": true,
    "schedule": {
      "start": { "date": "2010-12-11T10:10:00Z" },
      "stop": { "executions": 10 },
      "repeating": {
        "period": { "each": 7, "unit": "DAYS" },
        "pattern": {
          "time": "10:30:00Z",
          "weekly": { "days": ["MON", "WED"] }
        }
      }
    },
    "job": {
      "request": {
        "name": "REBOOT_EQUIPMENT",
        "parameters": { "TYPE": "HARDWARE" },
        "schedule": { "stop": { "delayed": 300000 } },
        "notify": true,
        "operationParameters": {
          "ackTimeout": 5000,
          "timeout": 60000
        },
        "target": { "append": { "entities": ["device_1", "device_2"] } }
      }
    }
  }
}
```

{{% notice style="info" title="Scheduling the job of a task" icon="lightbulb" %}}
Inside `job.request.schedule`, the only valid form of `start` and `stop` is `delayed` — an exact
`date` cannot be used, because the task itself decides when each job starts.
{{% /notice %}}

If `id` is omitted at creation, OpenGate generates a UUID. If provided, it must be unique.

## Selecting the target

Target selection works exactly as in jobs, inside `job.request.target`: an explicit list of
entities, a tag, or an inlined filter — never a combination of them. The same 300 KByte request size
limit applies, and large target lists can be built up with successive `PUT` requests.

The optional `resourceType` query string parameter restricts a filter to a single entity type
(`entity.device`, `entity.asset`, `entity.commsModule`, `entity.subscription`, `entity.subscriber`).

See [selecting the target](../jobs/#selecting-the-target) for the full description of the three modes
and their limits.

## Modifying a task

```bash
PUT /v80/operation/tasks/{taskId}
```

Changes apply to the **next** executions of the task, never to the job that is already running. This
includes appending or removing target entities.

## Listing the jobs created by a task

```bash
GET /v80/operation/tasks/{taskId}/jobs
GET /v80/tasks/{taskId}/entities
```

The first endpoint returns the jobs the task has produced, which is how you audit a recurring
operation over time. Each of those jobs is read exactly like a standalone job.

## Cancelling a task

```bash
DELETE /v80/operation/tasks/{taskId}
```

The task is marked `CANCELLED`. If the cancellation arrives while one of its jobs is running, the task
stays in `CANCELLING` until that job finishes cancelling all of its operations.

{{% notice style="warning" title="Cancellation does not roll back" icon="triangle-exclamation" %}}
As with jobs, cancelling a task does not undo steps already executed on the devices.
{{% /notice %}}

## Searching tasks

```bash
POST /v80/search/tasks
```

Tasks are searchable with the platform's standard filter, sort and select clauses. Every field of the
task object is available as a filter field, prefixed with `tasks.` — for example
`tasks.schedule.repeating.period.unit` or `tasks.job.request.name`. See the
[API reference](../api_reference/) for the complete list.
