Skip to content

Batch Operations

The /operations endpoint applies many changes in a single request instead of one API call per change. It follows the JSON:API atomic operations style, letting you add, update, or remove several domains, environment variables, process scales, buildpacks, or HTTP basic-auth entries at once.

Batching also lets Dokku Pro coalesce the work. Changes to the same app and resource are collapsed into a single dokku command where the CLI supports it (for example, one config:set for many environment variables, or one ps:scale for several process types), and each affected app is rebuilt at most once. So importing ten environment variables runs one config:set and queues one rebuild rather than ten of each.

Authentication is the same Bearer token used by the rest of the API; see the API overview for how to obtain one.

Request format

POST to /@api/operations with either a linear:operations or a parallel:operations array. Only one of the two may be present in a request. Both are currently processed sequentially, in order.

Each operation object has:

  • op: one of add, update, or remove.
  • data: the JSON:API primary data for add and update. It carries a type, an optional id, and an attributes object with the same fields the equivalent single-resource endpoint accepts.
  • ref: identifies the target of a remove (a type and an id).

Supported resources

type operations attributes rebuild
envs add/update (set), remove app_id, key, value yes
domains add, update, remove app_id, domain no
formations add/update (scale), remove (scale to 0) app_id, process_type, quantity yes
buildpacks add, remove app_id, buildpack, position yes
httpAuthIPs add, remove app_id, ip_address no
httpAuthUsers add/update, remove app_id, username, password no

add acts as an upsert for the resources whose dokku command is create-or-overwrite (envs, formations, httpAuthUsers), so you do not need to know whether a record already exists.

Example

Set several environment variables and add a domain in one request:

jwt_token="$(cat token.json | jq -r '.data.id')"

curl -H "Authorization: Bearer ${jwt_token}" \
     -H "Content-Type: application/json" \
     -d '{
       "linear:operations": [
         { "op": "add", "data": { "type": "envs", "attributes": { "app_id": "node-js-app", "key": "PORT", "value": "5000" } } },
         { "op": "add", "data": { "type": "envs", "attributes": { "app_id": "node-js-app", "key": "DEBUG", "value": "true" } } },
         { "op": "add", "data": { "type": "domains", "attributes": { "app_id": "node-js-app", "domain": "node-js-app.example.com" } } }
       ]
     }' \
     "https://admin.dokku.me/@api/operations"

Responses

  • 200: operations processed, no rebuild queued (for example a domains-only batch).
  • 202: operations processed and a rebuild was queued. The Content-Location header points at the queued job (/@api/queueJobs/{id}), which you can poll for completion.
  • 400: the request could not be parsed, both operation lists were provided, or an operation was invalid. The body names the offending operation index.
  • 422: an operation failed while being applied. Earlier operations in the batch are not rolled back; the body reports the failing operation index and the results of the operations that did succeed.

Skipping the rebuild

Send the Skip-Rebuild: true header to apply the changes without queuing a rebuild, for example when you will deploy separately afterward. The response is 200 with no Content-Location.

Replacing an entire collection

To replace all of an app's domains at once, send an update targeting the domains relationship with the full list as an array data:

{
  "linear:operations": [
    {
      "op": "update",
      "ref": { "type": "apps", "id": "node-js-app", "relationship": "domains" },
      "data": [
        { "type": "domains", "attributes": { "domain": "node-js-app.example.com" } },
        { "type": "domains", "attributes": { "domain": "www.example.com" } }
      ]
    }
  ]
}

The app's domains become exactly the provided list.

The same shape replaces all of an app's environment variables at once - target the envs relationship with the full desired set as the array data:

{
  "linear:operations": [
    {
      "op": "update",
      "ref": { "type": "apps", "id": "node-js-app", "relationship": "envs" },
      "data": [
        { "type": "envs", "attributes": { "key": "PORT", "value": "5000" } },
        { "type": "envs", "attributes": { "key": "DEBUG", "value": "true" } }
      ]
    }
  ]
}

The app's config becomes exactly the provided set: keys in the payload are set (only the new or changed ones are written), and any current variable not in the payload is unset - including an empty data array, which clears all config. Because there is no native "replace all config" command, Dokku Pro reconciles the desired set against config:export and applies one config:set plus one config:unset. You must therefore supply the complete desired set: any dokku-managed variable you want to keep (for example DOKKU_* or GIT_REV) must be included. Unlike a domains replacement, an envs replacement changes config and so queues a rebuild, returning 202 with a Content-Location (a domains replacement returns 200).

Collection replacement is currently supported for domains and envs.