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>",
"nodes": [
{}
],
"edges": [
{}
],
"groups": [
{}
],
"triggers": [
{}
],
"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>",
"nodes": [{}],
"edges": [{}],
"groups": [{}],
"triggers": [{}],
"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>',
nodes: [{}],
edges: [{}],
groups: [{}],
triggers: [{}],
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>',
'nodes' => [
[
]
],
'edges' => [
[
]
],
'groups' => [
[
]
],
'triggers' => [
[
]
],
'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 \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\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 \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\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 \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\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" } }
],
"edges": [],
"groups": null,
"compiled": { "forwardEdges": [], "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>",
"nodes": [
{}
],
"edges": [
{}
],
"groups": [
{}
],
"triggers": [
{}
],
"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>",
"nodes": [{}],
"edges": [{}],
"groups": [{}],
"triggers": [{}],
"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>',
nodes: [{}],
edges: [{}],
groups: [{}],
triggers: [{}],
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>',
'nodes' => [
[
]
],
'edges' => [
[
]
],
'groups' => [
[
]
],
'triggers' => [
[
]
],
'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 \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\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 \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\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 \"nodes\": [\n {}\n ],\n \"edges\": [\n {}\n ],\n \"groups\": [\n {}\n ],\n \"triggers\": [\n {}\n ],\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" } }
],
"edges": [],
"groups": null,
"compiled": { "forwardEdges": [], "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
Your API key.
Your Auth Token.
Body
Params
Accepts every field from Create Definition plus:Show properties
Show properties
The definition to update.
Optimistic-locking version. Must equal the stored definition’s current
version. The update is rejected if the stored version has advanced since you last read it.1–200 chars.
0–2000 chars.
1–100 nodes. Each node accepts optional cosmetic
name (1–200 chars) and description (≤ 2000 chars) labels.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.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.0–50 trigger declarations. Each trigger has the shape
Triggers are descriptive metadata in v1 — the engine does not auto-dispatch from them. Use them to label which definition belongs to which application event so your own dispatcher can resolve
{ triggerId, eventName?, filters? }:| Field | Type | Required | Description |
|---|---|---|---|
triggerId | string | yes | 1–128 chars. Stable identifier for this trigger. |
eventName | string | no | ≤ 128 chars. The event name your application emits when the workflow should dispatch. |
filters | object | no | Free-form filter map; consumed by your dispatch wrapper to decide whether to fire this trigger. |
eventName → definitionId.0–20 tags, each ≤ 64 chars.
Free-form metadata.
Required when scoped to an organization or document.
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.Example Requests
Rename a definition
{
"data": {
"definitionId": "marketing-copy-approval",
"ifVersion": 1,
"name": "Marketing copy approval (Q2 revision)"
}
}
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" } },
{ "nodeId": "human-review", "type": "human", "config": { "reviewers": [{ "userId": "u_reviewer_01", "mandatory": true }] } },
{ "nodeId": "agent-publish", "type": "agent", "config": { "agentId": "publish-agent-v1" } },
{ "nodeId": "agent-rework", "type": "agent", "config": { "agentId": "rework-agent-v1" } }
],
"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" } }
],
"edges": [],
"groups": null,
"compiled": { "forwardEdges": [], "loops": [] },
"triggers": null,
"tags": null,
"custom": null,
"createdAt": 1731432000000,
"updatedAt": 1731518400000,
"status": "active"
}
}
Was this page helpful?
⌘I

