Update Definition
curl --request POST \
--url https://api.velt.dev/v2/workflow/definitions/update \
--header 'Content-Type: application/json' \
--header 'x-velt-api-key: <x-velt-api-key>' \
--header 'x-velt-auth-token: <x-velt-auth-token>' \
--data '
{
"data": {
"definitionId": "<string>",
"ifVersion": 123,
"name": "<string>",
"description": "<string>",
"scope": {},
"nodes": [
{}
],
"edges": [
{}
],
"groups": [
{}
],
"triggers": [
{}
],
"webhookConfig": {},
"tags": [
"<string>"
],
"custom": {},
"organizationId": "<string>",
"documentId": "<string>"
}
}
'import requests
url = "https://api.velt.dev/v2/workflow/definitions/update"
payload = { "data": {
"definitionId": "<string>",
"ifVersion": 123,
"name": "<string>",
"description": "<string>",
"scope": {},
"nodes": [{}],
"edges": [{}],
"groups": [{}],
"triggers": [{}],
"webhookConfig": {},
"tags": ["<string>"],
"custom": {},
"organizationId": "<string>",
"documentId": "<string>"
} }
headers = {
"x-velt-api-key": "<x-velt-api-key>",
"x-velt-auth-token": "<x-velt-auth-token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-velt-api-key': '<x-velt-api-key>',
'x-velt-auth-token': '<x-velt-auth-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: {
definitionId: '<string>',
ifVersion: 123,
name: '<string>',
description: '<string>',
scope: {},
nodes: [{}],
edges: [{}],
groups: [{}],
triggers: [{}],
webhookConfig: {},
tags: ['<string>'],
custom: {},
organizationId: '<string>',
documentId: '<string>'
}
})
};
fetch('https://api.velt.dev/v2/workflow/definitions/update', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.velt.dev/v2/workflow/definitions/update",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
'definitionId' => '<string>',
'ifVersion' => 123,
'name' => '<string>',
'description' => '<string>',
'scope' => [
],
'nodes' => [
[
]
],
'edges' => [
[
]
],
'groups' => [
[
]
],
'triggers' => [
[
]
],
'webhookConfig' => [
],
'tags' => [
'<string>'
],
'custom' => [
],
'organizationId' => '<string>',
'documentId' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-velt-api-key: <x-velt-api-key>",
"x-velt-auth-token: <x-velt-auth-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.velt.dev/v2/workflow/definitions/update"
payload := strings.NewReader("{\n \"data\": {\n \"definitionId\": \"<string>\",\n \"ifVersion\": 123,\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"scope\": {},\n \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\n \"webhookConfig\": {},\n \"tags\": [\n \"<string>\"\n ],\n \"custom\": {},\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-velt-api-key", "<x-velt-api-key>")
req.Header.Add("x-velt-auth-token", "<x-velt-auth-token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.velt.dev/v2/workflow/definitions/update")
.header("x-velt-api-key", "<x-velt-api-key>")
.header("x-velt-auth-token", "<x-velt-auth-token>")
.header("Content-Type", "application/json")
.body("{\n \"data\": {\n \"definitionId\": \"<string>\",\n \"ifVersion\": 123,\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"scope\": {},\n \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\n \"webhookConfig\": {},\n \"tags\": [\n \"<string>\"\n ],\n \"custom\": {},\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.velt.dev/v2/workflow/definitions/update")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-velt-api-key"] = '<x-velt-api-key>'
request["x-velt-auth-token"] = '<x-velt-auth-token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": {\n \"definitionId\": \"<string>\",\n \"ifVersion\": 123,\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"scope\": {},\n \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\n \"webhookConfig\": {},\n \"tags\": [\n \"<string>\"\n ],\n \"custom\": {},\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"result": {
"definitionId": "marketing-copy-approval",
"name": "Marketing copy approval (Q2 revision)",
"description": null,
"version": 2,
"scope": { "level": "apiKey", "organizationId": null, "documentId": null },
"nodes": [
{ "nodeId": "agent-draft", "type": "agent", "config": { "agentId": "copy-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "human-review", "type": "human", "config": { "reviewers": [{ "userId": "u_reviewer_01", "mandatory": true }] } },
{ "nodeId": "agent-publish", "type": "agent", "config": { "agentId": "publish-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "agent-rework", "type": "agent", "config": { "agentId": "rework-agent-v1", "urlPath": "documentUrl" } }
],
"edges": [
{ "from": "agent-draft", "to": "human-review" },
{ "from": "human-review", "to": "agent-publish", "on": "approve" },
{ "from": "human-review", "to": "agent-rework", "on": "reject" }
],
"groups": null,
"compiled": {
"forwardEdges": [
{ "from": "agent-draft", "to": "human-review", "role": "always", "when": null },
{ "from": "human-review", "to": "agent-publish", "role": "approve", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "approve"] } },
{ "from": "human-review", "to": "agent-rework", "role": "reject", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "reject"] } }
],
"loops": []
},
"triggers": null,
"tags": null,
"custom": null,
"createdAt": 1731432000000,
"updatedAt": 1731518400000,
"status": "active"
}
}
Definitions
Update Definition
POST
/
v2
/
workflow
/
definitions
/
update
Update Definition
curl --request POST \
--url https://api.velt.dev/v2/workflow/definitions/update \
--header 'Content-Type: application/json' \
--header 'x-velt-api-key: <x-velt-api-key>' \
--header 'x-velt-auth-token: <x-velt-auth-token>' \
--data '
{
"data": {
"definitionId": "<string>",
"ifVersion": 123,
"name": "<string>",
"description": "<string>",
"scope": {},
"nodes": [
{}
],
"edges": [
{}
],
"groups": [
{}
],
"triggers": [
{}
],
"webhookConfig": {},
"tags": [
"<string>"
],
"custom": {},
"organizationId": "<string>",
"documentId": "<string>"
}
}
'import requests
url = "https://api.velt.dev/v2/workflow/definitions/update"
payload = { "data": {
"definitionId": "<string>",
"ifVersion": 123,
"name": "<string>",
"description": "<string>",
"scope": {},
"nodes": [{}],
"edges": [{}],
"groups": [{}],
"triggers": [{}],
"webhookConfig": {},
"tags": ["<string>"],
"custom": {},
"organizationId": "<string>",
"documentId": "<string>"
} }
headers = {
"x-velt-api-key": "<x-velt-api-key>",
"x-velt-auth-token": "<x-velt-auth-token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-velt-api-key': '<x-velt-api-key>',
'x-velt-auth-token': '<x-velt-auth-token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: {
definitionId: '<string>',
ifVersion: 123,
name: '<string>',
description: '<string>',
scope: {},
nodes: [{}],
edges: [{}],
groups: [{}],
triggers: [{}],
webhookConfig: {},
tags: ['<string>'],
custom: {},
organizationId: '<string>',
documentId: '<string>'
}
})
};
fetch('https://api.velt.dev/v2/workflow/definitions/update', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.velt.dev/v2/workflow/definitions/update",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
'definitionId' => '<string>',
'ifVersion' => 123,
'name' => '<string>',
'description' => '<string>',
'scope' => [
],
'nodes' => [
[
]
],
'edges' => [
[
]
],
'groups' => [
[
]
],
'triggers' => [
[
]
],
'webhookConfig' => [
],
'tags' => [
'<string>'
],
'custom' => [
],
'organizationId' => '<string>',
'documentId' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-velt-api-key: <x-velt-api-key>",
"x-velt-auth-token: <x-velt-auth-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.velt.dev/v2/workflow/definitions/update"
payload := strings.NewReader("{\n \"data\": {\n \"definitionId\": \"<string>\",\n \"ifVersion\": 123,\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"scope\": {},\n \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\n \"webhookConfig\": {},\n \"tags\": [\n \"<string>\"\n ],\n \"custom\": {},\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-velt-api-key", "<x-velt-api-key>")
req.Header.Add("x-velt-auth-token", "<x-velt-auth-token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.velt.dev/v2/workflow/definitions/update")
.header("x-velt-api-key", "<x-velt-api-key>")
.header("x-velt-auth-token", "<x-velt-auth-token>")
.header("Content-Type", "application/json")
.body("{\n \"data\": {\n \"definitionId\": \"<string>\",\n \"ifVersion\": 123,\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"scope\": {},\n \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\n \"webhookConfig\": {},\n \"tags\": [\n \"<string>\"\n ],\n \"custom\": {},\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.velt.dev/v2/workflow/definitions/update")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-velt-api-key"] = '<x-velt-api-key>'
request["x-velt-auth-token"] = '<x-velt-auth-token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": {\n \"definitionId\": \"<string>\",\n \"ifVersion\": 123,\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"scope\": {},\n \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\n \"webhookConfig\": {},\n \"tags\": [\n \"<string>\"\n ],\n \"custom\": {},\n \"organizationId\": \"<string>\",\n \"documentId\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"result": {
"definitionId": "marketing-copy-approval",
"name": "Marketing copy approval (Q2 revision)",
"description": null,
"version": 2,
"scope": { "level": "apiKey", "organizationId": null, "documentId": null },
"nodes": [
{ "nodeId": "agent-draft", "type": "agent", "config": { "agentId": "copy-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "human-review", "type": "human", "config": { "reviewers": [{ "userId": "u_reviewer_01", "mandatory": true }] } },
{ "nodeId": "agent-publish", "type": "agent", "config": { "agentId": "publish-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "agent-rework", "type": "agent", "config": { "agentId": "rework-agent-v1", "urlPath": "documentUrl" } }
],
"edges": [
{ "from": "agent-draft", "to": "human-review" },
{ "from": "human-review", "to": "agent-publish", "on": "approve" },
{ "from": "human-review", "to": "agent-rework", "on": "reject" }
],
"groups": null,
"compiled": {
"forwardEdges": [
{ "from": "agent-draft", "to": "human-review", "role": "always", "when": null },
{ "from": "human-review", "to": "agent-publish", "role": "approve", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "approve"] } },
{ "from": "human-review", "to": "agent-rework", "role": "reject", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "reject"] } }
],
"loops": []
},
"triggers": null,
"tags": null,
"custom": null,
"createdAt": 1731432000000,
"updatedAt": 1731518400000,
"status": "active"
}
}
Use this API to update an existing workflow definition. Atomically increments the version, snapshots the prior content, and rejects if the stored version mismatches
Errors:
ifVersion. In-flight executions keep running on the version they started with.
Endpoint
POST https://api.velt.dev/v2/workflow/definitions/update
Headers
string
required
Your API key.
string
required
Your Auth Token.
Body
Params
Accepts every field from Create Definition plus:Update replaces the definition; it is not a partial patch. Send the complete
name, nodes, and edges on every call. Any field you omit is not preserved from the stored definition.Read the current definition with Get Definition, change what you need, then send the whole object back with ifVersion. A read response is not accepted verbatim: strip the server-owned version, createdAt, updatedAt, status, and compiled fields first. Strip the explicit nulls too. Every optional field you never set comes back as null: description, groups, triggers, tags, custom, and organizationId / documentId inside scope. Update takes those fields as absent or as real values, never as null, so a leftover null or a leftover server-owned field fails the request with INVALID_ARGUMENT.object
required
Show properties
Show properties
string
required
The definition to update.
integer
required
Optimistic-locking version. Must equal the stored definition’s current
version. If someone else updated the definition since you read it, the request is rejected with FAILED_PRECONDITION and a message like Version conflict: expected 4, current 5, so a concurrent edit is never silently overwritten.string
required
1–200 chars.
string
0–2000 chars.
object
Defaults to
{ level: "apiKey" }. Options:{ level: "apiKey" }: workspace-wide.{ level: "organization", organizationId: "<id>" }: bound to one organization.organizationIdis required (returnsINVALID_ARGUMENTif omitted).{ level: "document", organizationId: "<id>", documentId: "<id>" }: bound to one document under an organization. Both fields required.
scope like every other field. Omit it and level resets to apiKey, silently demoting an organization-scoped or document-scoped definition to workspace scope. Resend the scope you read from Get Definition on every update.array
required
1–100 nodes of type
agent, human, notification, or webhook. Each node accepts an optional slaMs (up to 7 days) and optional cosmetic name (1–200 chars) and description (≤ 2000 chars) labels. See Node configuration and the Create Definition type table.array
required
0–500 edges, unified
EdgeSchema: { from, to, on?, when?, loop? }. from / to are EdgeEndpoints (bare node-id string, { kind: "node", nodeId }, or { kind: "group", groupId }); on ∈ approve / reject / always (default) / exhausted / custom; when is valid only on on:"custom"; loop { maxIterations: 1–20 } only on an on:"reject" back-edge. A human node must have an outgoing on:"reject" edge. See the edge model for full semantics and the Create Definition field table.array
0–100 parallel-group definitions. A
waitAll or cancelOnQuorum group can be an edge source (from: { kind: "group", groupId }); group-to-node fan-out (to: { kind: "group", groupId }) is accepted for all policies. A forward on:"reject" from a joinOnQuorum / cancelOnQuorum group is rejected as a dead edge. See parallel groups and quorum policies.array
0–50 trigger declarations:
{ triggerId, eventName?, filters?, inboundWebhook?, schedule?, appTrigger? }. A trigger starts executions for you, with no dispatch call. The three mechanisms are mutually exclusive on a single entry. See the Create Definition field table and Triggers.Updating triggers replaces the stored array. Removing a schedule entry, or setting its enabled to false, stops that schedule from firing.object
Default webhook receiver for every execution of this definition:
{ url, secret, eventTypes? }. See Webhook delivery.string[]
0–20 tags, each ≤ 64 chars.
object
Free-form metadata.
string
Required when scoped to an organization or document.
string
Required when scoped to a document.
Every successful update increments
version and snapshots the prior content. In-flight executions are immune to updates: they keep running on the pinned definitionVersion from their dispatch.Snapshots are kept for audit and recovery only. There is no endpoint to read an old version and no rollback, so keep your own copy of anything you may want to restore. See Versioning.Example Requests
Update a definition
Onlyname changes here, so the request resends the unchanged nodes and edges verbatim.
{
"data": {
"definitionId": "marketing-copy-approval",
"ifVersion": 1,
"name": "Marketing copy approval (Q2 revision)",
"scope": { "level": "apiKey" },
"nodes": [
{ "nodeId": "agent-draft", "type": "agent", "config": { "agentId": "copy-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "human-review", "type": "human", "config": { "reviewers": [{ "userId": "u_reviewer_01", "mandatory": true }] } },
{ "nodeId": "agent-publish", "type": "agent", "config": { "agentId": "publish-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "agent-rework", "type": "agent", "config": { "agentId": "rework-agent-v1", "urlPath": "documentUrl" } }
],
"edges": [
{ "from": "agent-draft", "to": "human-review" },
{ "from": "human-review", "to": "agent-publish", "on": "approve" },
{ "from": "human-review", "to": "agent-rework", "on": "reject" }
]
}
}
Response
Success Response
{
"result": {
"definitionId": "marketing-copy-approval",
"name": "Marketing copy approval (Q2 revision)",
"description": null,
"version": 2,
"scope": { "level": "apiKey", "organizationId": null, "documentId": null },
"nodes": [
{ "nodeId": "agent-draft", "type": "agent", "config": { "agentId": "copy-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "human-review", "type": "human", "config": { "reviewers": [{ "userId": "u_reviewer_01", "mandatory": true }] } },
{ "nodeId": "agent-publish", "type": "agent", "config": { "agentId": "publish-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "agent-rework", "type": "agent", "config": { "agentId": "rework-agent-v1", "urlPath": "documentUrl" } }
],
"edges": [
{ "from": "agent-draft", "to": "human-review" },
{ "from": "human-review", "to": "agent-publish", "on": "approve" },
{ "from": "human-review", "to": "agent-rework", "on": "reject" }
],
"groups": null,
"compiled": {
"forwardEdges": [
{ "from": "agent-draft", "to": "human-review", "role": "always", "when": null },
{ "from": "human-review", "to": "agent-publish", "role": "approve", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "approve"] } },
{ "from": "human-review", "to": "agent-rework", "role": "reject", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "reject"] } }
],
"loops": []
},
"triggers": null,
"tags": null,
"custom": null,
"createdAt": 1731432000000,
"updatedAt": 1731518400000,
"status": "active"
}
}
Failure Response
{
"error": {
"message": "ERROR_MESSAGE",
"status": "FAILED_PRECONDITION"
}
}
NOT_FOUND (definition does not exist) / FAILED_PRECONDITION (ifVersion mismatch) / INVALID_ARGUMENT (schema, compileGraph, or linter failure).
{
"result": {
"definitionId": "marketing-copy-approval",
"name": "Marketing copy approval (Q2 revision)",
"description": null,
"version": 2,
"scope": { "level": "apiKey", "organizationId": null, "documentId": null },
"nodes": [
{ "nodeId": "agent-draft", "type": "agent", "config": { "agentId": "copy-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "human-review", "type": "human", "config": { "reviewers": [{ "userId": "u_reviewer_01", "mandatory": true }] } },
{ "nodeId": "agent-publish", "type": "agent", "config": { "agentId": "publish-agent-v1", "urlPath": "documentUrl" } },
{ "nodeId": "agent-rework", "type": "agent", "config": { "agentId": "rework-agent-v1", "urlPath": "documentUrl" } }
],
"edges": [
{ "from": "agent-draft", "to": "human-review" },
{ "from": "human-review", "to": "agent-publish", "on": "approve" },
{ "from": "human-review", "to": "agent-rework", "on": "reject" }
],
"groups": null,
"compiled": {
"forwardEdges": [
{ "from": "agent-draft", "to": "human-review", "role": "always", "when": null },
{ "from": "human-review", "to": "agent-publish", "role": "approve", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "approve"] } },
{ "from": "human-review", "to": "agent-rework", "role": "reject", "when": { "op": "eq", "args": [{ "var": "output.decision" }, "reject"] } }
],
"loops": []
},
"triggers": null,
"tags": null,
"custom": null,
"createdAt": 1731432000000,
"updatedAt": 1731518400000,
"status": "active"
}
}
Was this page helpful?
⌘I

