# Operations

## What is an operation?

An **operation** is an action that OpenGate executes on a remote entity: reboot a device, update its
firmware, read or write its configuration parameters, run a diagnostic, change its administrative
status. If data collection is how the platform *reads* from the field, operations are how it *writes*
to it.

Operations are the answer to a question every IoT deployment eventually asks: *I have fifty thousand
devices in the field — how do I make them all do something, and how do I know whether it worked?*

## Why operations matter

**They work at fleet scale.** A single API request can target one device or every device matching a
tag or a filter. OpenGate explodes that request into one operation per entity, tracks each one
independently, and gives you both an aggregated summary and the per-entity detail.

**They are asynchronous by nature, and modelled as such.** A device may be asleep, roaming, or out of
coverage. Operations have their own life cycle, with timeouts, retries, pause and resume, so a
request that cannot be served right now is not a request that failed.

**They are extensible without touching your code.** An operation is identified by a name and a
parameter object. Adding a new operation type to your organization does not change the API contract:
the same `POST` endpoint executes `REBOOT_EQUIPMENT` today and your own `CALIBRATE_SENSOR` tomorrow.

**They report progress, not just outcomes.** Operations can be multi-step. A firmware update reports
download progress, installation start and end, and the final result — so a two-hour update over a
narrowband link is observable while it runs.

**They are transport-agnostic.** Back-office applications always talk to the same north API. How the
operation actually reaches the device (HTTP, MQTT, a connector function) is resolved by the platform.

{{% notice style="primary" title="Operations act on the real world" icon="triangle-exclamation" %}}
A single request with a tag or a filter can reach thousands of entities, and cancelling a job does
**not** roll back steps that already executed. Verify the target selection before activating a job.
{{% /notice %}}

## The operation model

Five concepts carry the whole service:

```mermaid
flowchart TB
    OT["Operation type<br>REBOOT_EQUIPMENT<br>(what can be requested)"]
    TASK["Task<br>(a schedule)"]
    JOB["Job<br>(one execution over a target)"]
    OP1["Operation<br>device_1"]
    OP2["Operation<br>device_2"]
    OPN["Operation<br>device_N"]
    ST["Steps<br>progress and result<br>reported per entity"]

    OT --> JOB
    OT --> TASK
    TASK -->|"one job per scheduled run"| JOB
    JOB --> OP1
    JOB --> OP2
    JOB --> OPN
    OP1 --> ST
    OP2 --> ST
    OPN --> ST
```

| Concept | What it is | Where it lives |
|---|---|---|
| **Operation type** | The definition of an action: its name, its parameter schema and its steps. Cloned from the platform catalog or created by your organization. | [Operation types](operation_types/), [Default catalog](default_catalog/) |
| **Job** | One execution of an operation type over a target set of entities, with its own schedule, timeouts and retries. | [Jobs](jobs/) |
| **Task** | A schedule that creates jobs over time — periodically, or on a weekly, monthly or yearly pattern. | [Tasks](tasks/) |
| **Operation** | The execution on a single entity. A job with 300 targets produces 300 operations, each with its own status and result. | [Jobs](jobs/), [Status reference](status_reference/) |
| **Step** | A stage inside a single operation, with its own result and timestamp. Multi-step operations report each one as it happens. | [Execution flows](flows/) |

## Two ways to execute

|  | **Job** | **Task** |
|---|---|---|
| Purpose | Run an operation once | Run an operation repeatedly over time |
| Endpoint | `POST /v80/operation/jobs` | `POST /v80/operation/tasks` |
| Timing | Immediately, after a delay, or at a date | Start date + repetition period or calendar pattern |
| Produces | One set of operations | One job per scheduled execution |
| Changes apply to | The job itself, while it has not started | The next executions, never the job already running |

## Run your first operation

Create a job that reboots two devices. The operation name and its `parameters` come from your
organization's operation types; everything else configures *how* the execution is managed:

```bash
curl --request POST \
     --header "X-ApiKey: <your-api-key>" \
     --header "Content-Type: application/json" \
     --data @job.json \
     https://api.opengate.es/v80/operation/jobs
```

Content of `job.json`:

```json
{
  "job": {
    "request": {
      "name": "REBOOT_EQUIPMENT",
      "parameters": {
        "type": "HARDWARE"
      },
      "active": true,
      "notify": true,
      "schedule": {
        "start": {
          "date": "2010-12-11T10:10:00Z"
        },
        "stop": {
          "delayed": 300000
        }
      },
      "operationParameters": {
        "ackTimeout": 5000,
        "timeout": 60000,
        "retries": 0,
        "retriesDelay": 1000,
        "retryResultList": ["ERROR_PROCESSING"]
      },
      "target": {
        "append": {
          "entities": ["device_1", "device_2"]
        }
      }
    }
  }
}
```

The response returns `201` with a `location` header containing the job identifier. Read the job to
follow its progress:

```bash
curl --request GET \
     --header "X-ApiKey: <your-api-key>" \
     https://api.opengate.es/v80/operation/jobs/a38f7735-dcef-4f5a-9ca4-b6a8f7517522
```

The `report` tells you how the execution is going across the whole target set (trimmed response):

```json
{
  "id": "a38f7735-dcef-4f5a-9ca4-b6a8f7517522",
  "request": {
    "name": "REBOOT_EQUIPMENT",
    "parameters": {
      "TYPE": "HARDWARE"
    },
    "active": true,
    "notify": false,
    "user": "user@mail.com"
  },
  "report": {
    "execution": {
      "activatedDate": "2014-03-12T11:43:35Z",
      "startedDate": "2014-03-12T11:43:35Z",
      "finishedDate": "2014-03-12T11:44:52Z"
    },
    "summary": {
      "status": "FINISHED",
      "total": 3,
      "finished": {
        "total": 2,
        "successful": 1,
        "error": 0
      }
    }
  }
}
```

## Where to go next

- Executing and controlling operations: [Jobs](jobs/) and [Tasks](tasks/).
- Configuring what an operation does: [Operation parameters](parameters/).
- Being notified instead of polling: [Callbacks](callbacks/).
- Understanding what reaches the device: [Execution flows](flows/).
- Interpreting a response: [Status reference](status_reference/).
- Defining your own operations: [Operation types](operation_types/).

{{% children sort="weight" %}}
