Skip to content
Join our Slack

Replace a workflow

PUT
/v1/forms/{form_public_id}/workflows/{workflow_public_id}
curl --request PUT \
--url 'https://platform.fomr.io/v1/forms/example/workflows/example?dry_run=true' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "example", "nodes": [ { "public_id": "example", "node_type_key": "form_completed", "position": { "x": 1, "y": 1 }, "config": {} } ], "edges": [ { "public_id": "example", "source_node_public_id": "example", "target_node_public_id": "example", "source_handle": "example", "target_handle": "example" } ] }'

Replaces the name and graph of a workflow with the Workflow Document you send and answers the stored document. Nodes and edges are matched by public ID and kept in place; an item without an ID is created; a stored item you leave out is removed. An enabled workflow can be renamed, but its nodes and edges change only once it is disabled, as in the app. A document identical to the stored one writes nothing. Use dry_run=true to validate without writing. Needs forms:write and workflows:write. Costs 1 API credit.

form_public_id
required
string
>= 10 characters <= 10 characters /^[A-Za-z0-9_-]+$/

The public ID of the form the workflow belongs to.

workflow_public_id
required
string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/

The public ID of the workflow, as listFormWorkflows returns it.

dry_run
string
default: false
Allowed values: true false

Validate the document and resolve every ID without writing anything or creating a spreadsheet. Costs the same as a real write and answers 200 with the document the real call would have stored.

Media typeapplication/json

A Workflow Document to create or replace a workflow with. The read-only fields of a read document are accepted and ignored.

object
name
required

Workflow name, trimmed.

string
>= 1 characters <= 100 characters
nodes
required

Every node the workflow should have. On replace, a stored node whose ID is left out is removed. A runnable workflow has exactly one form_completed trigger.

Array
<= 50 items
One of: discriminator: node_type_key
form_completed

Node type form_completed: New response. Runs when a respondent completes this form. Kind: trigger.

object
public_id

Optional on write. A present ID keeps the node of this workflow with that ID, or creates a node with that ID when the workflow has none; an absent ID creates a node with a server-minted ID. Node IDs are unique across fomr and never reused, so an ID another workflow or a removed node holds is refused. A chosen ID has at least 8 characters.

string
>= 8 characters <= 22 characters /^[A-Za-z0-9_-]+$/
node_type_key
required

Discriminates the node type. A node keeps its type: to change it, replace the node with a new one.

string
Allowed value: form_completed
position
required

Canvas position of the node in the app workflow builder. It has no effect on how the workflow runs.

object
x
required

Horizontal canvas coordinate of the node in the app workflow builder.

number
y
required

Vertical canvas coordinate of the node in the app workflow builder.

number
config

Optional and always empty: the trigger has no settings, and the read document leaves the field out.

object
edges
required

Every edge the workflow should have. On replace, a stored edge that is not sent is removed.

Array<object>
<= 100 items

A connection that runs the target node after the source node.

object
public_id

Optional on write. A present ID keeps the edge of this workflow with that ID, or creates an edge with that ID; an absent ID keeps an existing edge between the same nodes and handles, or creates one with a server-minted ID.

string
>= 8 characters <= 22 characters /^[A-Za-z0-9_-]+$/
source_node_public_id
required

The public ID of the node the edge starts from, in the nodes of the same document. Only the trigger can start edges.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
target_node_public_id
required

The public ID of the node the edge leads to, in the nodes of the same document.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
source_handle
Any of:
string
<= 100 characters
target_handle
Any of:
string
<= 100 characters
public_id

The public ID of the workflow. Ignored on write.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
is_enabled

Whether the workflow runs. Ignored on write; use enable and disable.

boolean
validation_status

The result of the last enable check. Ignored on write.

string
Allowed values: unchecked valid invalid
validation_error_code
Any of:
string
Allowed values: WORKFLOW_VALIDATION_TOO_MANY_WORKFLOWS WORKFLOW_VALIDATION_TOO_MANY_NODES WORKFLOW_VALIDATION_TOO_MANY_EDGES WORKFLOW_VALIDATION_NODE_CONFIG_TOO_LARGE WORKFLOW_VALIDATION_NODE_CONFIG_INVALID WORKFLOW_VALIDATION_MISSING_TRIGGER WORKFLOW_VALIDATION_MULTIPLE_TRIGGERS WORKFLOW_VALIDATION_UNSUPPORTED_NODE_TYPE WORKFLOW_VALIDATION_INTEGRATION_CONNECTION_UNAVAILABLE WORKFLOW_VALIDATION_INVALID_EDGE WORKFLOW_VALIDATION_CYCLE WORKFLOW_VALIDATION_UNREACHABLE_NODE WORKFLOW_VALIDATION_RUNTIME_PHASE_MISMATCH
created_at

When the workflow was created. Ignored on write.

string
updated_at

When the workflow last changed. Ignored on write.

string

The Workflow Document: a workflow of a form with its whole graph. Read it, change it, and send it back to replace it.

Media typeapplication/json

The Workflow Document: a workflow of a form with its whole graph. Read it, change it, and send it back to replace it.

object
public_id
required

The public ID of the workflow. Use it in the other workflow calls.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
name
required

Workflow name shown in the Workflows tab of the form.

string
>= 1 characters <= 100 characters
is_enabled
required

Whether the workflow runs when a respondent completes the form. Change it with enable and disable.

boolean
validation_status
required

Unchecked until the workflow is first enabled, valid once it passed the enable checks, invalid when the last check failed.

string
Allowed values: unchecked valid invalid
validation_error_code
required
Any of:
string
Allowed values: WORKFLOW_VALIDATION_TOO_MANY_WORKFLOWS WORKFLOW_VALIDATION_TOO_MANY_NODES WORKFLOW_VALIDATION_TOO_MANY_EDGES WORKFLOW_VALIDATION_NODE_CONFIG_TOO_LARGE WORKFLOW_VALIDATION_NODE_CONFIG_INVALID WORKFLOW_VALIDATION_MISSING_TRIGGER WORKFLOW_VALIDATION_MULTIPLE_TRIGGERS WORKFLOW_VALIDATION_UNSUPPORTED_NODE_TYPE WORKFLOW_VALIDATION_INTEGRATION_CONNECTION_UNAVAILABLE WORKFLOW_VALIDATION_INVALID_EDGE WORKFLOW_VALIDATION_CYCLE WORKFLOW_VALIDATION_UNREACHABLE_NODE WORKFLOW_VALIDATION_RUNTIME_PHASE_MISMATCH
created_at
required

When the workflow was created.

string format: date-time
/^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$/
updated_at
required

When the workflow last changed.

string format: date-time
/^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$/
nodes
required

The nodes of the workflow graph, oldest first. Issue paths index into this array.

Array
One of: discriminator: node_type_key
form_completed

Node type form_completed: New response. Runs when a respondent completes this form. Kind: trigger.

object
public_id
required

The public ID of the node. Edges name their endpoints with it.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
node_type_key
required

Discriminates the node type. A node keeps its type: to change it, replace the node with a new one.

string
Allowed value: form_completed
position
required

Canvas position of the node in the app workflow builder. It has no effect on how the workflow runs.

object
x
required

Horizontal canvas coordinate of the node in the app workflow builder.

number
y
required

Vertical canvas coordinate of the node in the app workflow builder.

number
edges
required

The edges of the workflow graph, oldest first. Issue paths index into this array.

Array<object>

A connection that runs the target node after the source node.

object
public_id
required

The public ID of the edge.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
source_node_public_id
required

The public ID of the node the edge starts from.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
target_node_public_id
required

The public ID of the node the edge leads to.

string
>= 1 characters <= 22 characters /^[A-Za-z0-9_-]+$/
source_handle
required
Any of:
string
<= 100 characters
target_handle
required
Any of:
string
<= 100 characters

Example

{
"validation_status": "unchecked",
"validation_error_code": "WORKFLOW_VALIDATION_TOO_MANY_WORKFLOWS",
"nodes": [
{
"node_type_key": "form_completed"
}
]
}

Default Response

Media typeapplication/json
object
code
required

The stable code to branch on.

string
Allowed values: INVALID_INPUT UNAUTHORIZED PERSONAL_ACCESS_TOKEN_EXPIRED PERSONAL_ACCESS_TOKEN_REVOKED PLAN_LIMIT_REACHED PRO_FEATURE_REQUIRED FORBIDDEN FORM_PUBLISH_EMAIL_UNVERIFIED ORGANIZATION_MEMBER_BLOCKED PERSONAL_ACCESS_TOKEN_NOT_PERMITTED NOT_FOUND FORM_NOT_PUBLISHED NO_DRAFT_DURING_PUBLISH FORM_ARCHIVED FORM_CONVERSION_BLOCKED FORM_PUBLISH_REVISION_CONFLICT PAYLOAD_TOO_LARGE FORM_PUBLISH_VALIDATION_FAILED FORM_SAFETY_REJECTED TOO_MANY_REQUESTS API_COOLDOWN SERVER AI_SERVICE_UNAVAILABLE SERVICE_UNAVAILABLE
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string
issues
required

Every value the request got wrong.

Array<object>
object
path
required

The path into the request, with property names and numeric array indexes.

Array
message
required

What is wrong with the value at this path.

string
code
required

The stable code for the issue. Branch on it, and use it with params to write your own text.

string
accepted_values

Accepted values when a node type or enum value is rejected.

Array
params

The values the message was built from, keyed by name, for clients that write their own text for each code.

object
key
additional properties
Any of:
string

Example

{
"code": "INVALID_INPUT"
}

Default Response

Media typeapplication/json
object
code
required

The stable code to branch on.

string
Allowed values: INVALID_INPUT UNAUTHORIZED PERSONAL_ACCESS_TOKEN_EXPIRED PERSONAL_ACCESS_TOKEN_REVOKED PLAN_LIMIT_REACHED PRO_FEATURE_REQUIRED FORBIDDEN FORM_PUBLISH_EMAIL_UNVERIFIED ORGANIZATION_MEMBER_BLOCKED PERSONAL_ACCESS_TOKEN_NOT_PERMITTED NOT_FOUND FORM_NOT_PUBLISHED NO_DRAFT_DURING_PUBLISH FORM_ARCHIVED FORM_CONVERSION_BLOCKED FORM_PUBLISH_REVISION_CONFLICT PAYLOAD_TOO_LARGE FORM_PUBLISH_VALIDATION_FAILED FORM_SAFETY_REJECTED TOO_MANY_REQUESTS API_COOLDOWN SERVER AI_SERVICE_UNAVAILABLE SERVICE_UNAVAILABLE
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string

Example

{
"code": "INVALID_INPUT"
}

Default Response

Media typeapplication/json
object
code
required

The stable code to branch on.

string
Allowed values: INVALID_INPUT UNAUTHORIZED PERSONAL_ACCESS_TOKEN_EXPIRED PERSONAL_ACCESS_TOKEN_REVOKED PLAN_LIMIT_REACHED PRO_FEATURE_REQUIRED FORBIDDEN FORM_PUBLISH_EMAIL_UNVERIFIED ORGANIZATION_MEMBER_BLOCKED PERSONAL_ACCESS_TOKEN_NOT_PERMITTED NOT_FOUND FORM_NOT_PUBLISHED NO_DRAFT_DURING_PUBLISH FORM_ARCHIVED FORM_CONVERSION_BLOCKED FORM_PUBLISH_REVISION_CONFLICT PAYLOAD_TOO_LARGE FORM_PUBLISH_VALIDATION_FAILED FORM_SAFETY_REJECTED TOO_MANY_REQUESTS API_COOLDOWN SERVER AI_SERVICE_UNAVAILABLE SERVICE_UNAVAILABLE
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string
required_permission
required
Any of:
string

Example

{
"code": "INVALID_INPUT"
}

Default Response

Media typeapplication/json
object
code
required

Returned for a form or workflow that does not exist, is in Trash or deleted, belongs to another organization, or for a Private Template, which has no workflows. These cases are not told apart.

string
Allowed value: NOT_FOUND
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string

Example

{
"code": "NOT_FOUND"
}

A rejected call. The organization budget names the policy it rejected the call under; the request floor that bounds hammering sends the envelope alone.

Media typeapplication/json
Any of:
object
code
required

The stable code to branch on.

string
Allowed values: INVALID_INPUT UNAUTHORIZED PERSONAL_ACCESS_TOKEN_EXPIRED PERSONAL_ACCESS_TOKEN_REVOKED PLAN_LIMIT_REACHED PRO_FEATURE_REQUIRED FORBIDDEN FORM_PUBLISH_EMAIL_UNVERIFIED ORGANIZATION_MEMBER_BLOCKED PERSONAL_ACCESS_TOKEN_NOT_PERMITTED NOT_FOUND FORM_NOT_PUBLISHED NO_DRAFT_DURING_PUBLISH FORM_ARCHIVED FORM_CONVERSION_BLOCKED FORM_PUBLISH_REVISION_CONFLICT PAYLOAD_TOO_LARGE FORM_PUBLISH_VALIDATION_FAILED FORM_SAFETY_REJECTED TOO_MANY_REQUESTS API_COOLDOWN SERVER AI_SERVICE_UNAVAILABLE SERVICE_UNAVAILABLE
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string
policy
required

The policy that rejected the call.

string
Allowed values: minute burst
plan
required

The plan whose numbers were applied.

string
Allowed values: free pro
limit
required

The policy limit in credits.

integer
>= -9007199254740991 <= 9007199254740991
used
required

Credits already spent in the open window.

integer
>= -9007199254740991 <= 9007199254740991
remaining
required

Credits still available under the policy.

integer
>= -9007199254740991 <= 9007199254740991
cost
required

What the rejected call would have cost.

integer
>= -9007199254740991 <= 9007199254740991
window_seconds
required

How long the policy window lasts.

integer
>= -9007199254740991 <= 9007199254740991
cooldown_until
required
Any of:
string format: date-time
/^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$/
resets_at
required

When the window that rejected the call ends.

string format: date-time
/^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$/
retry_after_seconds
required

Seconds to wait before retrying. Also sent as the Retry-After response header.

integer
>= -9007199254740991 <= 9007199254740991
upgrade_url
required
Any of:
string

Example

{
"code": "INVALID_INPUT",
"policy": "minute",
"plan": "free"
}

Default Response

Media typeapplication/json
object
code
required

The stable code to branch on.

string
Allowed values: INVALID_INPUT UNAUTHORIZED PERSONAL_ACCESS_TOKEN_EXPIRED PERSONAL_ACCESS_TOKEN_REVOKED PLAN_LIMIT_REACHED PRO_FEATURE_REQUIRED FORBIDDEN FORM_PUBLISH_EMAIL_UNVERIFIED ORGANIZATION_MEMBER_BLOCKED PERSONAL_ACCESS_TOKEN_NOT_PERMITTED NOT_FOUND FORM_NOT_PUBLISHED NO_DRAFT_DURING_PUBLISH FORM_ARCHIVED FORM_CONVERSION_BLOCKED FORM_PUBLISH_REVISION_CONFLICT PAYLOAD_TOO_LARGE FORM_PUBLISH_VALIDATION_FAILED FORM_SAFETY_REJECTED TOO_MANY_REQUESTS API_COOLDOWN SERVER AI_SERVICE_UNAVAILABLE SERVICE_UNAVAILABLE
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string

Example

{
"code": "INVALID_INPUT"
}

Default Response

Media typeapplication/json
object
code
required

The requested operation has no available capacity. Retry after the Retry-After header says.

string
Allowed value: SERVICE_UNAVAILABLE
message
required

A human-readable explanation. Not part of the contract; never branch on it.

string
request_id
required

The ID of the failed request, also sent as the X-Request-Id response header.

string
retry_after_seconds
required

Seconds to wait before retrying. Also sent as the Retry-After response header.

integer
>= -9007199254740991 <= 9007199254740991

Example

{
"code": "SERVICE_UNAVAILABLE"
}

Your next form could be the best-looking thing on your site.

Free forever. Unlimited responses. No signup to start.