Change many workflows at once
POST/
Does one thing to up to 200 workflows: put them live, pause, delete, tag or move them.
Needs an API token with the Write permission for workflows (workflow:write), and each op its own: Delete for delete, Publish for activate and pause.
Parameters
Body
idsRequired · array of UUIDsUp to 200 workflow IDs. One that isn’t a UUID fails on its own.
opRequired · stringactivate,pause,delete,addTagsormove.tagsOptional · array of stringsWith
addTags: at least one tag to add.folderIdOptional · UUID or nullWith
move: the folder, ornullfor none.
What each op does
activate- Publishes each, with the same checks as Publish a workflow. One that fails names its
step. pause- Takes each live workflow offline. A workflow that isn’t live fails that ID.
delete- Deletes each for good, with its runs.
addTags- Adds the tags to each one’s own, up to 50 in all.
move- Files each in
folderId. A folder in another workspace fails that ID.
It takes no Idempotency-Key. Sending it again is safe for activate, addTags and move. A second delete or pause fails those IDs: they are gone, or no longer live.
Responses
- 200OK
Each ID is in
succeededor infailed, with its reason. Readfailed: a 200 doesn’t mean all worked. The body isn’t JSON, there are no IDs or more than 200,
opis unknown, oraddTagshas no tag, over 50 tags, or a tag over 50 characters.- 403
FORBIDDENThe token lacks Write, which every
opneeds, or the one itsopadds: Delete fordelete, Publish foractivateandpause. - 403
FEATURE_OFFA token made inside a partner’s product sent
movewhile folders are switched off there.
Any call can also answer: 401 UNAUTHORIZED · 401 TOKEN_ENDED · 403 TOKEN_SURFACE_OFF · 403 EMBED_NOT_ALLOWED · 403 EMBED_NOT_AVAILABLE · 403 ACCOUNT_SUSPENDED · 413 PAYLOAD_TOO_LARGE · 415 INVALID_CONTENT_TYPE · 429 RATE_LIMITED · 503 BUSY · 503 PAUSED · 503 SERVICE_UNAVAILABLE. See Errors.
Request
GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…" # needs Write for workflows
curl -X POST "$GORUNNER/api/workflows/bulk" \
-H "Authorization: Bearer $GORUNNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"op": "addTags",
"ids": [
"3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
"6e9a1c3f-8b2d-4a57-9e0c-3f7b5d1a8c42"
],
"tags": [
"prod"
]
}'const GORUNNER = "https://api.gorunner.io";
const TOKEN = process.env.GORUNNER_TOKEN;
const res = await fetch(
`${GORUNNER}/api/workflows/bulk`,
{
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
op: "addTags",
ids: [
"3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
"6e9a1c3f-8b2d-4a57-9e0c-3f7b5d1a8c42",
],
tags: ["prod"],
}),
},
);
const { data } = await res.json();import os, requests
GORUNNER = "https://api.gorunner.io"
TOKEN = os.environ["GORUNNER_TOKEN"]
res = requests.post(
f"{GORUNNER}/api/workflows/bulk",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"op": "addTags",
"ids": [
"3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
"6e9a1c3f-8b2d-4a57-9e0c-3f7b5d1a8c42",
],
"tags": ["prod"],
},
)
data = res.json()["data"]Response · 200 OK
{
"data": {
"op": "addTags",
"succeeded": [
"3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31"
],
"failed": [
{
"id": "6e9a1c3f-8b2d-4a57-9e0c-3f7b5d1a8c42",
"error": "workflow not found"
}
]
}
}Every field
Body
idsRequired · array of UUIDsWorkflow ids. An entry that is not a UUID is reported in
failed, not rejected outright.opRequired · stringOne of
activate,pause,delete,addTags,move.tagsOptional · array of stringsRequired (and only read) when
opisaddTags. Must contain at least one non-blank tag or the whole request is a 400, and so must at most 50 distinct tags of at most 50 characters each.folderIdOptional · UUID or nullOnly read when
opismove.nullmoves the workflows out of any folder. A folder from another workspace fails per id.
Response · 200 OK
dataobjectPer-id outcome of a bulk operation. A 200 says the request was well formed, NOT that every workflow succeeded — always inspect
failed.opstringOne of
activate,pause,delete,addTags,move.succeededarray of UUIDsAlways present, possibly empty.
failedarray of objectsAlways present, possibly empty. One entry per id that did not apply, each with its own reason.
idstringThe id as sent — not necessarily a valid UUID.
errorstringWhy this one failed, e.g. "Workflow not found.", "too many tags (max 50)", or a publish refusal’s sentence.
stepstringAn
activaterefused for one step: that step’s display name.