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.

Operations act on the real world

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.

The operation model

Five concepts carry the whole service:

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, Default catalog
Job One execution of an operation type over a target set of entities, with its own schedule, timeouts and retries. Jobs
Task A schedule that creates jobs over time β€” periodically, or on a weekly, monthly or yearly pattern. Tasks
Operation The execution on a single entity. A job with 300 targets produces 300 operations, each with its own status and result. Jobs, 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

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:

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:

{
  "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:

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):

{
  "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

Subsections of Operations

Jobs

A job is one execution of an operation type over a target set of entities. Creating a job is the normal way to run an operation: you POST a job request, and OpenGate turns it into one operation per target entity.

POST /v80/operation/jobs

Anatomy of a job request

Section Purpose
name The operation type to execute, for example REBOOT_EQUIPMENT.
parameters The parameters of the operation itself. See Operation parameters.
target Which entities the operation runs on.
active Whether the job starts. false creates the job without launching it.
schedule When the job runs and when it gives up.
operationParameters Timeouts and retry policy applied to each individual operation.
notify Whether to notify the operation result by email or trap. Defaults to false.
callback URI to be notified on job progress instead of polling. See Callbacks.
userNotes Free-text notes attached to the job instance.

Selecting the target

There are three ways to reference the entities a job acts on, and they are mutually exclusive β€” a single job cannot mix entity lists, tags and filters.

An explicit list of entities

"target": { "append": { "entities": ["device_1", "device_2"] } }

The same parametrization is applied to every entity in the list. Two limits apply:

  • Entities per array: 100 by default.
  • Request body size: 300 KBytes by default.

Both are configurable per platform, so check the values with your administrator. To launch an operation over a larger list, create the job with active set to false and use PUT requests to append entities in batches, activating the job in the last call.

A tag

"target": { "append": { "tags": ["fleet_north"] } }

Only one tag name can be passed. OpenGate resolves the tag into the target set and builds the internal structure of the job; when that work finishes the job waits in IDLE if it is not active, or in SCHEDULED if it is.

A filter

"target": { "append": { "filter": { "eq": { "device.model": "MDL-1" } } } }

The filter is evaluated by the platform to resolve the target set. Previously created filters cannot be reused here β€” the filter must be inlined in the request.

The optional resourceType query string parameter restricts the filter to one entity type:

Value Entities considered
entity.device Devices
entity.asset Assets
entity.commsModule Communication modules
entity.subscription Subscriptions
entity.subscriber Subscribers
Filter targets cannot be updated

The target section of a filter-based job cannot be modified afterwards. To change the target set, deactivate the job and create a new one with the new filter.

Scheduling

The schedule block controls when the job runs. start accepts either an exact date or a delayed value in milliseconds; stop sets the deadline after which pending operations are cancelled.

Two optional modes refine how the operations are distributed inside that window.

Window

window restricts execution to given weekdays and a daily time range β€” useful when field interventions are only acceptable during a maintenance window.

Periods must be whole hours; intermediate periods are rejected:

Window Allowed
"start": "09:00:00Z" β€” "stop": "15:00:00Z" Yes
"start": "09:30:00Z" β€” "stop": "15:30:00Z" Yes
"start": "09:00:00Z" β€” "stop": "15:30:00Z" No

Scattering

scattering spreads the individual operations across the available time instead of firing them all at once. It exists to protect shared infrastructure β€” typically a mobile operator cell that would collapse if thousands of devices woke up simultaneously.

Field Meaning
maxSpread Percentage (0–100) of the job’s effective time used to spread operations. 0 runs as fast as possible, 100 spreads over the whole window. Default 0.
strategy.field Entity field used to group operations. Currently only subscription.collected.cellInfo.
strategy.factor Dispersion level (0–100) applied within each group. 0 clusters maximally, 100 scatters maximally. Default 0.
strategy.warningMaxRate Speed control in operations per second, to verify the resulting rate stays within maxSpread.

Per-operation timeouts and retries

operationParameters applies to each individual operation, not to the job as a whole:

Field Meaning
ackTimeout Milliseconds to wait for the device to accept the operation. On expiry the operation is cancelled.
timeout Milliseconds to wait for the operation to finish. Default 60000.
retries Number of retries when the operation gets no acknowledgement or times out. Default 0.
retriesDelay Milliseconds between retries.
retryResultList Results that trigger a retry. ERROR_TIMEOUT is always included.
Minimum internal timeout

OpenGate enforces a minimum internal timeout of 40 seconds, so timeout plus ackTimeout must be greater than that. The default of 60 seconds is a good starting point.

Job life cycle

A job’s status reflects the aggregate progress of all its operations:

stateDiagram-v2
    direction TB
    [*] --> IDLE: active=false
    [*] --> SCHEDULED: active=true<br>start delayed
    [*] --> IN_PROGRESS: active=true<br>start now

    IDLE --> SCHEDULED: active=true<br>start delayed
    IDLE --> IN_PROGRESS: active=true<br>start now
    SCHEDULED --> IDLE: active=false
    SCHEDULED --> IN_PROGRESS: start time<br>reached

    IN_PROGRESS --> PAUSED: active=false
    PAUSED --> IN_PROGRESS: active=true

    IN_PROGRESS --> FINISHED: all ok
    IN_PROGRESS --> FINISHED_WITH_ERRORS: with errors
    IN_PROGRESS --> CANCELLING_BY_USER: cancelled<br>by a user
    IN_PROGRESS --> CANCELLING_BY_ENGINE: timeout<br>reached
    SCHEDULED --> CANCELLING_BY_USER: cancelled<br>by a user
    CANCELLING_BY_USER --> CANCELLED: all operations<br>cancelled
    CANCELLING_BY_ENGINE --> TIMEOUT_CANCELLED: all operations<br>cancelled

    FINISHED --> [*]
    FINISHED_WITH_ERRORS --> [*]
    TIMEOUT_CANCELLED --> [*]
    CANCELLED --> [*]
Transition Trigger
Into IDLE The job is created or updated with active set to false.
Into SCHEDULED The job is active and its schedule.start is a date or a delay.
Into IN_PROGRESS The job is active with an immediate start, or the scheduled start time is reached.
IN_PROGRESS β†’ PAUSED active set to false on a running job.
PAUSED β†’ IN_PROGRESS active set to true on a paused job.
Into FINISHED Every operation reached a final state successfully.
Into FINISHED_WITH_ERRORS Operations failed or were cancelled.
Into CANCELLING_BY_USER A user cancels the job, through the console or the API.
Into CANCELLING_BY_ENGINE The job’s timeout is reached, so the platform cancels it.
Into CANCELLED Every entity operation of a user-cancelled job finished cancelling.
Into TIMEOUT_CANCELLED The same, for a job the timeout cancelled.

Both cancelling states are transient: the job stays there until every one of its operations has finished cancelling, which on a job targeting thousands of entities is not instant.

One detail still unconfirmed

The specification defines what each state means but not which terminal state the engine path ends in. The pairing above β€” a user cancellation ending in CANCELLED, a timeout ending in TIMEOUT_CANCELLED β€” follows from their descriptions and is pending confirmation.

See the status reference for the complete list of job, operation and step values.

Reading the result

An execution involves as many entities as the target references, so one job explodes into many results. The API exposes both levels:

flowchart LR
    JOB["Job"] --> SUM["report.summary<br>one aggregated view<br>counters per state"]
    JOB --> RES["operations<br>one result per entity<br>status, result, steps"]
Endpoint Returns
GET /v80/operation/jobs/{jobId} The job request plus report.summary
GET /v80/operation/jobs/{jobId}/operations Paginated per-entity results
GET /v80/operation/jobs/{jobId}/operations/{id} A single entity’s result

The per-entity list is paginated with start and size parameters β€” necessary when a job targets thousands of entities. Each operation object carries its own status, result, description and steps array.

To be notified when the job starts and when it finishes instead of polling these endpoints, configure a callback.

Updating a job

PUT /v80/operation/jobs/{jobId}

A job can only be modified while active is false and it has not started. What you can change:

  • Request fields: active, notify, callback, userNotes, schedule.start, schedule.stop.
  • The target entity list, by appending or removing entities.

The same JSON size limit as in creation applies. In the last PUT, set active to true to start the execution.

Pause and resume

The same endpoint controls a running job through the active field:

  • Pause: set active to false on a job in IN_PROGRESS. The job moves to PAUSED. While paused, the job’s features cannot be modified.
  • Resume: set active to true on a paused job. The job returns to IN_PROGRESS.

Cancelling a job

DELETE /v80/operation/jobs/{jobId}

The job moves to CANCELLING_BY_USER first β€” or to CANCELLING_BY_ENGINE when the platform itself cancels it β€” and to CANCELLED once all of its operations are cancelled.

Cancellation does not roll back

Cancelling a job does not undo steps that already executed on the devices. A firmware update cancelled halfway leaves the device halfway. Be deliberate.

Searching jobs and operations

Job and operation searches follow the platform’s standard search pattern, with support for filtering, sorting, field selection and summaries:

POST /v80/search/jobs
POST /v80/search/jobs/summary
POST /v80/search/entities/devices/operations
POST /v80/search/entities/operations/history

Equivalent endpoints exist for subscribers and subscriptions. Results are returned as JSON by default, or as CSV through HTTP header options. The full parameter list is in the API reference.

Tasks

A task is a schedule that creates jobs. Where a job 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.

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.

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.

{
  "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"] } }
      }
    }
  }
}
Scheduling the job of a task

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.

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 for the full description of the three modes and their limits.

Modifying a task

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

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

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.

Cancellation does not roll back

As with jobs, cancelling a task does not undo steps already executed on the devices.

Searching tasks

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 for the complete list.

Operation parameters

Parameters are what turn a generic operation type into a concrete instruction: not just reboot, but reboot the hardware; not just update, but install bundle 1.0.

There are two distinct parameter blocks in a job request, and confusing them is a common mistake:

Block Configures Defined by
parameters The operation itself β€” what the device must do The operation type’s JSON schema
operationParameters How the platform manages the execution β€” timeouts, retries The platform, identical for every operation type. See Jobs

Declaring parameters with JSON schema

As an operations administrator you declare an operation’s parameters with JSON Schema when creating or editing an operation type. JSON Schema gives you the whole range from a single enumerated string to nested objects and arrays, with validation and defaults.

Taking REBOOT_EQUIPMENT from the catalog as an example, its parameters are declared as:

{
    "type": "object",
    "properties": {
        "type": {
            "type": "string",
            "title": "Reboot Type",
            "enum": [
                "HARDWARE",
                "SOFTWARE"
            ],
            "default": "HARDWARE"
        }
    },
    "additionalProperties": false
}

Three things this declaration buys you:

  • Validation: a job requesting "type": "WARM" is rejected before reaching any device.
  • Defaults: omitting type yields HARDWARE.
  • A usable interface: title is what the OpenGate web console renders when a user launches the operation by hand, so a well-written schema also produces a well-formed form.

Setting additionalProperties to false, as above, rejects unknown parameters instead of silently ignoring them.

Filling parameters in a north API call

Back-office applications pass parameters as a plain JSON object matching the schema:

{
  "job": {
    "request": {
      "name": "REBOOT_EQUIPMENT",
      "parameters": {
        "type": "HARDWARE"
      },
      "active": true,
      "target": {
        "append": {
          "entities": ["device_1"]
        }
      }
    }
  }
}

If the operation type declares no parameters, the block can be omitted entirely.

How parameters reach the device

The platform does not forward your JSON object verbatim. It translates it into the south API format before delivering it to the device, where each parameter travels as a named, typed value inside the operation request.

The exact format the device receives is described in the device integration section. For a complete payload, including nested array parameters, see the update operation example.

Callbacks

Polling a job to know whether it has finished works, but it does not scale and it wastes time. A callback inverts the flow: OpenGate notifies your application over HTTP as the job progresses.

Enabling callbacks

Set the callback field of the job request to the URI you want to be notified on:

{
  "job": {
    "request": {
      "name": "REBOOT_EQUIPMENT",
      "callback": "http://[your_application_address]/[your_URI]",
      "target": { "append": { "entities": ["device_1"] } }
    }
  }
}
  • The URI follows the RFC 3986 format, and only HTTP transport is supported.
  • OpenGate appends the name of the specific callback to this URI when notifying, so a single base URI serves both notifications.
  • The HTTP method is always POST, with the payload as the request body.
  • An empty value disables callback notification.

Callbacks work for tasks too: configure callback inside task.job.request, and every job the task creates will notify.

The two notifications

sequenceDiagram
    participant App as Your application
    participant OG as OpenGate
    participant Dev as Devices

    App->>OG: POST /v80/operation/jobs
    OG-->>App: 201 Created + location
    Note over OG: target set resolved,<br>operations created,<br>schedule reached
    OG->>App: POST callback β€” job started
    OG->>Dev: operations dispatched
    Dev-->>OG: results per entity
    Note over OG: all operations finished,<br>cancelled or timed out
    OG->>App: POST callback β€” job finished
Callback Fired when Payload carries
Started The job begins executing β€” immediately, or when its schedule says so. id, request, report.execution
Finished The job is over: schedule terminated, job cancelled, or all operations completed. id, request, report.execution, report.summary, result with the first page of per-entity operations

Creating a job is not itself notified: the 201 Created response to your POST already tells you the job exists, and report.summary is available from GET /v80/operation/jobs/{jobId} from that moment on.

Job started callback

Fired when execution actually begins. For a scheduled job this happens when the scheduling parameters say so, which may be long after creation:

{
  "job": {
    "id": "33eb9dfa-7a87-41f7-9bad-7b5a26712fec",
    "request": {
      "name": "REBOOT_EQUIPMENT",
      "parameters": {
        "TYPE": "HARDWARE"
      },
      "notify": true,
      "user": "user@mail.com"
    },
    "report": {
      "execution": {
        "activatedDate": "2010-12-20T10:10:00.00Z",
        "startedDate": "2010-12-20T10:10:00.00Z",
        "finishedDate": ""
      }
    }
  }
}

Job finished callback

The most complete of the three. Besides the summary counters it includes the first page of per-entity results, so a small job needs no follow-up request at all. For larger jobs, page through the remaining results with GET /v80/operation/jobs/{jobId}/operations.

{
  "job": {
    "id": "33eb9dfa-7a87-41f7-9bad-7b5a26712fec",
    "request": {
      "name": "REBOOT_EQUIPMENT",
      "parameters": {
        "TYPE": "HARDWARE"
      },
      "notify": true,
      "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,
        "inProgress": {
          "total": 0,
          "scheduled": 0,
          "pendingExecution": 0,
          "waitingForConnection": 0,
          "started": 0
        },
        "finished": {
          "total": 2,
          "successful": 1,
          "error": 0,
          "cancelled": {
            "total": 1,
            "byEngine": 0,
            "byUser": 0,
            "byTimeout": 1,
            "byExternalTimeout": 0,
            "byExternal": 0
          }
        },
        "finishedOutOfTime": {
          "total": 1,
          "successful": 1,
          "error": 0
        }
      }
    },
    "result": {
      "page": {
        "number": 1,
        "of": 50
      },
      "operations": [
        {
          "operationId": "86dd3409-6fcd-49d4-be6b-b2fa497207ec",
          "entityId": "device_1",
          "resourceType": "entity.device",
          "name": "REBOOT_EQUIPMENT",
          "parameters": {
            "TYPE": "HARDWARE"
          },
          "notify": true,
          "execution": {
            "activatedDate": "2014-10-01T09:03:42Z",
            "startedDate": "2014-10-01T09:03:45Z",
            "finishedDate": "2014-10-01T09:04:45Z"
          },
          "user": "user@mail.com",
          "status": "FINISHED",
          "result": "SUCCESSFUL",
          "description": "successful operation",
          "steps": [
            {
              "name": "RESET",
              "result": "SUCCESSFUL",
              "description": "Reset ok",
              "timestamp": "2012-09-27T16:46:02.10Z"
            }
          ]
        },
        {
          "operationId": "29891afd-5f4f-4b23-800e-586bd4ecb0eb",
          "entityId": "device_2",
          "resourceType": "entity.device",
          "name": "REBOOT_EQUIPMENT",
          "parameters": {
            "TYPE": "HARDWARE"
          },
          "notify": true,
          "execution": {
            "activatedDate": "2014-10-01T09:03:42Z",
            "startedDate": "2014-10-01T09:03:45Z",
            "finishedDate": "2014-10-01T09:04:45Z"
          },
          "user": "user@mail.com",
          "status": "FINISHED",
          "result": "SUCCESSFUL",
          "description": "successful operation",
          "steps": [
            {
              "name": "RESET",
              "result": "SUCCESSFUL",
              "description": "Reset ok",
              "timestamp": "2012-09-27T16:46:02.10Z"
            }
          ]
        }
      ]
    }
  }
}

Note that a job reaching the finished callback is not necessarily a job that succeeded: in this example status is FINISHED, but of the three operations one was cancelled by timeout and one finished out of time. Always read the counters, not just the status. See the status reference for what each value means.

Notifications versus callbacks

callback and notify are different mechanisms and can be used together:

Field Recipient Purpose
callback Your application, over HTTP Machine-to-machine job progress notification
notify The platform’s notification channels (email, trap) Human notification of the operation result

Execution flows

Everything on the jobs and tasks pages describes the north side of the service, the API your back-office application talks to. This page explains what happens on the south side, between OpenGate and the device β€” because that is what determines how long an operation takes, what progress you can observe, and why an operation can sit in WAITING_FOR_CONNECTION for hours.

Every operation has at least a minimum workflow to be fulfilled. Beyond that minimum, the flow depends on what the device is capable of.

Who starts the conversation

Flow Who initiates When it fits
Platform-driven OpenGate contacts the device The device is reachable and exposes an endpoint
Device-driven The device asks OpenGate for pending operations The device sleeps, sits behind NAT, or has no public address

Device-driven operations are why an operation may report WAITING_FOR_CONNECTION: the work is queued and waiting for the device to show up.

Platform-driven flows

Synchronous

The whole operation is resolved in a single HTTP request and response. The device does the work and answers with the final result:

sequenceDiagram
    participant OG as OpenGate
    participant Dev as Device
    OG->>Dev: Operation request (HTTP POST)
    Note over Dev: executes the operation
    Dev-->>OG: Final response with result and steps (HTTP 201)

Simple and cheap, but it holds the connection for the whole execution β€” unsuitable for anything slow, such as a firmware download.

Asynchronous with a simple response

The device acknowledges the request immediately and reports the result later, in a request of its own:

sequenceDiagram
    participant OG as OpenGate
    participant Dev as Device
    OG->>Dev: Operation request (HTTP POST)
    Dev-->>OG: ACK (HTTP response)
    Note over Dev: executes the operation
    Dev->>OG: Response notification with result (HTTP POST)
    OG-->>Dev: ACK (HTTP 200)

Asynchronous with multiple responses

The device reports partial progress as it goes, and closes with a final response. This is what makes a long operation observable:

sequenceDiagram
    participant OG as OpenGate
    participant Dev as Device
    OG->>Dev: Operation request (HTTP POST)
    Dev-->>OG: ACK (HTTP response)
    Dev->>OG: Partial response β€” STEP in progress (HTTP POST)
    OG-->>Dev: ACK (HTTP 200)
    Dev->>OG: Partial response β€” next STEP (HTTP POST)
    OG-->>Dev: ACK (HTTP 200)
    Dev->>OG: Final response β€” last STEP and result (HTTP POST)
    OG-->>Dev: ACK (HTTP 200)

Each partial response updates the operation’s steps array, so a north API client polling the job β€” or receiving callbacks β€” sees the progress accumulate.

Device-driven flow

The device polls OpenGate for work, executes what it gets, and reports back:

sequenceDiagram
    participant Dev as Device
    participant OG as OpenGate
    Dev->>OG: Ask for pending operations (HTTP GET)
    OG-->>Dev: Pending operation request
    Note over Dev: executes the operation
    Dev->>OG: Response notification with result (HTTP POST)
    OG-->>Dev: ACK (HTTP 200)

Single-step versus multi-step operations

The flow strategy above is about transport. Independently of it, an operation is either atomic or composed of steps:

Structure What the device reports Observability
Simple request/response One result, no intermediate stages Success or failure, nothing in between
Multi-step A declared list of steps, each with its own result and timestamp Progress while the operation runs

A multi-step operation can report all its steps in one response, or spread them across partial responses until the final step is reached. The step list belongs to the operation type definition: it is declared once, and every execution reports against it.

Where to go from here

The diagrams above are summaries. The complete south API β€” endpoints, ports, request and response schemas, security requirements and the full flow diagrams β€” lives in the device integration section:

For a real multi-step flow end to end, see the update operation example.

Status reference

Every value OpenGate can report about an operation, in one place. Use this page when you are reading a job report, a per-entity result or a callback payload and need to know what a value means.

Three levels report status independently, and they answer different questions:

flowchart LR
    J["Job status<br>how is the whole execution going?"] --> O["Operation status and result<br>what happened on this entity?"]
    O --> S["Step results<br>which stages ran, and how?"]

Job status

The aggregate state of a job, in report.summary.status. See the job life cycle for the transitions between them.

Value Meaning
IDLE The job has been created but not started, because it is not active.
SCHEDULED The job is active and waiting for its scheduled start.
IN_PROGRESS The job has started.
PAUSED The job has been paused by setting active to false while running.
FINISHED All operations in the job have finished.
FINISHED_WITH_ERRORS The job finished with errors. Some operations may have succeeded while others failed or were cancelled, or all of them may have failed. errorCode and errorDescription are present in the summary.
TIMEOUT_CANCELLED The job was cancelled because the maximum timeout defined expired.
CANCELLING_BY_USER A user cancelled the job, and it is still cancelling its operations.
CANCELLING_BY_ENGINE The job’s timeout was reached, and it is still cancelling its operations.
CANCELLED The job and all of its operations have been cancelled.
Cancellation records who caused it

There is no plain CANCELLING: a job in the middle of cancelling always reports which side started it, CANCELLING_BY_USER or CANCELLING_BY_ENGINE. The two differ in cause, not in mechanics β€” a user asked, or the timeout ran out β€” and the same distinction appears at operation level in the finished.cancelled counters.

Operation status

The state of the operation on one entity, in each element of the operations list.

Value Meaning
PENDING The operation is pending to be started.
QUEUED The operation has been launched but has not reached the device yet.
WAITING_FOR_ACK The operation is waiting for an acknowledgement from the device to be started.
WAITING_FOR_CONNECTION The operation is waiting for the device to connect, when that option is enabled.
IN_PROGRESS The operation has started and is waiting for completion.
FINISHED The operation has been completed.
FINISHED_OUT_OF_TIME The operation finished and its result was collected, but outside the allowed time.
TIMEOUT_CANCELLED The operation was cancelled because the maximum timeout defined expired.
NOT_ALLOWED The operation cannot be executed over this entity.
CANCELLED The operation has been cancelled.

Operation result

Why an operation ended the way it did, in the result field. A FINISHED status with a non-successful result is normal: the execution completed, the outcome was negative.

Value Meaning
SUCCESSFUL The operation completed with success.
PARTIAL_SUCCESS The operation completed with partial success.
OPERATION_PENDING The operation is queued to be executed.
ERROR_IN_PARAM The operation cannot be executed because of an error in the parameters passed.
NOT_ALLOWED The operation execution is not allowed for this entity.
NOT_SUPPORTED The operation is not supported by the entity.
ALREADY_IN_PROGRESS The operation is already being executed.
ERROR_PROCESSING The operation finished with an unknown error.
ERROR_TIMEOUT The operation could not be completed because the device response timed out.
TIMEOUT_CANCELLED The operation was cancelled because the maximum timeout defined expired.
CANCELLED The operation was cancelled by a user or through the API.
CANCELLED_INTERNAL The operation was cancelled by the internal engine. Consult your platform administrator.
UNKNOWN_RESULT The operation returned a result the platform does not recognize. Consult your platform administrator.
Retry policy

Any of these results can be listed in the job’s operationParameters.retryResultList to trigger a retry. ERROR_TIMEOUT is always part of that list, whether you include it or not.

Step result

Each element of an operation’s steps array carries a name, a timestamp, an optional description, an optional response, and one of:

Value Meaning
SUCCESSFUL The step completed successfully.
ERROR The step failed.
SKIPPED The step was skipped.
NOT_EXECUTED The step did not run.

Not every declared step appears in every execution: a device only reports the steps it actually goes through. See execution flows for how steps are reported.

Task state

The state of a task, in its state field.

Value Meaning
ACTIVE The task is launching jobs according to its schedule.
INACTIVE The task exists but launches no jobs, because active is false.
FINISHED The task reached its stop condition β€” its end date or its number of executions.
CANCELLING The task has been cancelled and one of its jobs is still finishing.
CANCELLED The task has been cancelled.

Job summary counters

report.summary counts the operations of a job by state. The counters are what tell you whether a FINISHED job actually did what you wanted.

Counter Contains
total Total operations attempted.
inProgress.total Operations not finished yet.
inProgress.scheduled Operations scheduled but not launched.
inProgress.pendingExecution Operations queued for execution.
inProgress.waitingForConnection Operations waiting for the device to appear.
inProgress.started Operations already started.
finished.total Operations that reached a final state.
finished.successful Operations that finished successfully.
finished.error Operations that finished with an error.
finished.cancelled.total Cancelled operations, broken down by cause below.
finished.cancelled.byUser Cancelled by a user or through the API.
finished.cancelled.byEngine Cancelled by the platform engine.
finished.cancelled.byTimeout Cancelled because the operation timeout expired.
finished.cancelled.byExternalTimeout Cancelled because an external system timed out.
finished.cancelled.byExternal Cancelled by an external system.
finished.cancelled.byAlreadyInProgress Cancelled because the same operation was already running on that entity.
finishedOutOfTime.total Operations whose result arrived outside the allowed time.
finishedOutOfTime.successful Of those, the ones that succeeded.
finishedOutOfTime.error Of those, the ones that failed.
errorCode, errorDescription Present only when the job status is FINISHED_WITH_ERRORS.

Every counter above is also available as a search filter field, prefixed with jobs.report.summary. β€” so you can query, for example, all jobs with jobs.report.summary.finished.cancelled.byTimeout greater than zero. See the API reference for the complete field list.

Operation types

An operation type is the definition of an action: its name, its title and description, the entity types it applies to, its parameter schema and its steps. Nothing can be executed until an operation type for it exists in your organization.

There are two ways to get one:

  • Clone it from the platform catalog, for the operations OpenGate already implements. See the default operations catalog.
  • Create it from scratch, for actions specific to your devices.
Only your organization’s types are executable

Operation types from the platform catalog that have not been cloned into your organization cannot be executed. The catalog is a source to inherit from, not a set of ready-to-run operations.

Resource Contains
/v80/operationTypes/catalog The platform catalog, available to be cloned
/v80/operationTypes/provision/organizations/{organization} Your organization’s own operation types

What the API does

  • Retrieve the list of operations available to be cloned.
  • Create operations for an organization, either by cloning from the catalog or from scratch.
  • Retrieve a single operation from the catalog by name.
  • Update an operation previously created.
  • Delete an operation previously created.
  • Search the operations of an organization using the platform’s filters.
Viewer profile

GET and SEARCH are the only actions available to the viewer profile.

Creating an operation type

The response returns a location header with the URL of the new resource.

When the operation is cloned from the catalog, only name, description and title can be modified β€” the parameter schema, the steps and the applicability of a catalog operation are fixed. When created from scratch, you define all of it, including the parameter schema.

Restricting execution by profile

The optional profiles list names the user profiles authorized to execute the operation. By default, every profile except viewer can execute custom operations.

Available profile names:

  • advanced
  • admin_domain
  • super_admin_domain
  • admin
  • root

The list can be set at creation time or updated later. If omitted, the default access rules apply. Invalid profiles return 400 Bad Request with error detail; viewer is never permitted and also returns 400 if included.

Updating an operation type

For operations derived from the catalog, only name, description and title can be modified.

Searching operation types

Five filter fields are available, all optional:

Filter Selects by
name Operation name
applicableTo Entity type the operation applies to
models Device models the operation supports
fromCatalog Whether the operation was cloned from the platform catalog
profile Profiles authorized to execute it
Extended operation fields

Any parameter of the ExtendedOperation object can also be used as a filter field in operationTypes searches.

Usage examples

Read the operation types catalog:

curl --request GET \
     --header "X-ApiKey: <your-api-key>" \
     https://www.amplia-iiot.com/v80/operationTypes/catalog

Read a single operation type of your organization by its name:

curl --request GET \
     --header "X-ApiKey: <your-api-key>" \
     https://www.amplia-iiot.com/v80/operationTypes/provision/organizations/{organizationName}/REBOOT_EQUIPMENT

API specification

Default operations catalog

OpenGate ships a catalog of operations covering the actions devices commonly implement: reboots, factory resets, firmware and configuration updates, diagnostics, parameter reads and writes, clock setting, communications control. Each entry below is a definition you can clone into your organization as an operation type.

Name Description Applicable to Steps
ADMINISTRATIVE_STATUS_CHANGE Allows to change the administrative status of an entity
  • entity.device
  • entity.subscription
  • entity.subscriber
CONFIGURE_CONSOLE_PARAMETERS Configure the Console Parameters
  • entity.device
CONFIGURE_SECTIONALIZER_PARAMETERS Configure the Sectionalizer Parameters
  • entity.device
CONFIGURE_SECTIONALIZERS Configure a list of Sectionalizers
  • entity.device
EQUIPMENT_DIAGNOSTIC Equipment auodiagnostic
  • entity.device
FACTORY_RESET Remote factory reset
  • entity.device
GET_DEVICE_PARAMETERS Allows obtain values of a list of variables
  • entity.device
IoTAdeunis_set_parameters Set IoTAdeunis parameter
IoTAtimTM_set_parameters Set IoTAtimTM parameters
POWER_OFF_EQUIPMENT Powers offs equipment on target entity
  • entity.device
POWER_ON_EQUIPMENT Remote turn on
  • entity.device
REBOOT_EQUIPMENT Allows remotely reboot CHs
  • entity.device
REFRESH_INFO On demand retrieving the Info
  • entity.device
  • entity.subscription
  • entity.subscriber
REFRESH_LOCATION On demand retrieving the location
  • entity.device
REFRESH_PRESENCE On demand retrieving the Presence
  • entity.device
  • entity.subscription
RESET_COMMUNICATIONS reset a communications channel
  • entity.device
SEND_COMMAND Send a command to an entity
  • entity.device
SET_CLOCK_EQUIPMENT Allows to set to date the device internal clock
  • entity.device
SET_DEVICE_PARAMETERS Allows set values of a list of variables
  • entity.device
SHUT_DOWN_COMMUNICATIONS disable a specific communications channel
  • entity.device
SIM_REPLACEMENT
  • entity.subscription
STATUS_DIAGNOSTIC Remote factory reset
  • entity.device
  • entity.subscription
UPDATE Device Firmware, Software and Configuration Update
  • entity.device
WAKE_UP_COMMUNICATIONS enable a specific communications channel
  • entity.device

Take into consideration that:

  • Catalog entries must be cloned into your organization before they can be executed. See operation types.
  • The operations available in your organization can differ from the list above. OpenGate administrators can enable more operations or disable some of them.
  • The SMS capability is only available for the on-premise solution, and requires integration with an external service provider.

Besides this list, new operation types can be created from scratch to adapt OpenGate to specific solution needs.

Examples

Worked examples of complete operations. Each one shows the JSON documents exchanged through the north API, used by back-office applications, and through the south API, used by devices β€” so you can see how a single job request turns into what the device actually receives.

Subsections of Examples

Update operation

Software and firmware update is the most complete operation OpenGate models: it is long-running, multi-step, and its progress matters as much as its outcome. It is therefore a good example of the asynchronous flow with multiple responses.

Flow diagram

OpenGate suggests a complete flow covering all the possible stages of a device update. In the real world a device may implement only part of these steps β€” any number and kind of steps implemented by your device is supported.

sequenceDiagram
    participant OG as OpenGate connector
    participant Dev as Device

    OG->>Dev: Operation request (HTTP POST)
    Dev-->>OG: Response ACK (HTTP 200 OK)

    Note over OG,Dev: the device reports progress,<br>one notification per step

    Dev->>OG: STEP DOWNLOADFILE (0%)
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP DOWNLOADFILE (x%)
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP DOWNLOADFILE (100%)
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP BEGINPREACTION
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP ENDPREACTION
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP BEGINPOSTACTION
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP ENDPOSTACTION
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP BEGININSTALL
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP ENDINSTALL
    OG-->>Dev: ACK (HTTP 200 OK)
    Dev->>OG: STEP ENDUPDATE
    OG-->>Dev: ACK (HTTP 200 OK)

Each notification is an HTTP POST from the device carrying the operation response, and each ACK is OpenGate’s HTTP 200 reply. Every notification updates the operation’s steps array, so the north API sees the download percentage advance in real time.

The UPDATE operation type declares the following steps: ACCEPTED, BEGINUPDATE, DOWNLOADFILE, BEGINPREACTION, ENDPREACTION, BEGININSTALL, ENDINSTALL, BEGINPOSTACTION, ENDPOSTACTION and ENDUPDATE. See the status reference for the results a step can report.

North API invocation

Back office applications invoke device update operations through the ordinary jobs API β€” everything you know about jobs applies. What is specific to updates is the operation name and its parameters:

Device Update Example

{
    "job" :
    {
        "request" : {
            "name" : "UPDATE",
            "parameters": [
                {
                    "name" : "bundleName",
                    "type":"string",
                    "value" : {
                        "string" : "bundle_1"
                    }
                },
                {
                    "name" : "bundleVersion",
                    "type":"string",
                    "value" : {
                        "string" : "1.0"
                    }
                }
            ],
            "active" : true,
            "notify" : true,
            "callback" : "http://[your_application_address]/[your_URI]",

            "schedule" : {
                "start" : {
                  "date" : "2012-09-10T12:33:43Z"
                },
                "stop" : {
                  "delayed" : 300000
                }
            },
            "operationParameters" : {
                "ackTimeout" : 5000,
                "timeout" : 6000,
                "retries" : 0,
                "retriesDelay" : 1000,
                "retryResultList" : ["ERROR_PROCESSING"]
            },
            "target" : {
                "append" : {
                    "entities" : [ "device_1", "device_2" ]
                }
            }
        }
    }
}

South API invocation

This is the document the device receives from the platform. The deploymentElements array is what makes an update different from any other operation: it tells the device what to download, where to put it, in which order, and how to verify it.

See the device integration section for the endpoints and transport details:

Device Update Example

{
    "operation": {
        "request": {
            "timestamp": 1453822201099,
            "name": "UPDATE",
            "parameters": [
                {
                    "name": "bundleName",
                    "value": {
                        "string": "bundle_1"
                    }
                },
                {
                    "name": "bundleVersion",
                    "value": {
                        "string": "version_1"
                    }
                },
                {
                    "name": "deploymentElements",
                    "value": {
                        "array": [
                            {
                                "type": "FIRMWARE",
                                "downloadUrl": "http://[your_opengate_address]/bundles/74427c0c-a28c-4765-92ef-30010adb733d/1002/firmware-1_1.1.bin",
                                "path": "/home",
                                "order": 1,
                                "operation": "INSTALL",
                                "option": "OPTIONAL",
                                "validators": [
                                    {
                                        "type": "SHA-256",
                                        "value": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
                                    }
                                ],
                                "size": 18
                            }
                        ]
                    }
                }
            ],
            "id": "072b08d1-0fcb-4a0c-a2d8-99773f9b9327"
        }
    }
}

API reference

The complete specification of the operations service: creating, reading, updating and cancelling jobs and tasks, retrieving per-entity operation results, and searching jobs, tasks and operation history.

Endpoint group Purpose
/v80/operation/jobs Create, read, update and cancel jobs
/v80/operation/jobs/{jobId}/operations Per-entity operation results of a job
/v80/operation/tasks Create, read, update and cancel tasks
/v80/operation/tasks/{taskId}/jobs Jobs produced by a task
/v80/search/jobs, /v80/search/tasks Search jobs and tasks, with summary variants
/v80/search/entities/{type}/operations Search operations by entity type
/v80/search/entities/operations/history Search historical operations

Data formats

OpenGate uses JSON as the interchange format in its RESTful interface.

Numbers

A number is an integer or a double-precision float. The property name is a string in double quotes, the value is not quoted:

Example property Value
time 1356695180301
value 299.99
maxValue 1.23e11
minValue -10.5

A number can be prefixed with a minus sign. The exponent portion, denoted by e or E, comes after the value and may carry an optional sign. Leading zeroes, octal and hexadecimal values are not allowed.

Dates

Dates and times follow ISO 8601:2004, and UTC is the time standard for all dates. The full format is YYYY-MM-DDThh:mm:ss.sTZD, for example 2021-07-16T19:20:30.00+01:00, as described in the ISO 8601 standard and in Date and Time Formats of W3C.

Precision Format Example
Year YYYY 2015
Year and month YYYY-MM 2015-10
Complete date YYYY-MM-DD 2015-10-06
Date plus hours and minutes YYYY-MM-DDThh:mm 2015-10-06T17:35
Date plus hours, minutes and seconds YYYY-MM-DDThh:mm:ss 2015-10-06T17:35:21
Date plus fraction of a second YYYY-MM-DDThh:mm:ss.s 2015-10-06T17:35:21.45
  • YYYY β€” four-digit year
  • MM β€” two-digit month, 01 for January
  • DD β€” two-digit day of month, 01 to 31
  • hh β€” two-digit hour, 00 to 23; am/pm is not allowed
  • mm β€” two-digit minute, 00 to 59
  • ss β€” two-digit second, 00 to 59
  • s β€” one or more digits for the decimal fraction of a second

Specification