Replace Workflow State
Replace a workflow’s editable draft graph wholesale. loops and parallels are accepted but ignored — both are recomputed from blocks. Omitting variables leaves the stored variables untouched.
Last write wins: concurrent writers are serialized by a row lock, so each lands a complete self-consistent graph and the later one replaces the earlier entirely. There is no partially-written state and no conflict detection.
This does not change what the deployed endpoint serves. Deployments are immutable versioned snapshots, and no schedule or webhook registration is touched. The only visible consequence is that needsRedeployment becomes true; POST /workflows/{workflowId}/deploy publishes the draft.
lint is advisory and never blocks the write. lint.fieldIssues is the most actionable part for a headless builder — it names blocks missing a required field, which fail at run time — and lint.unresolvedReferences names credential, resource, tool, and skill values that do not resolve. A workspace API key is rejected with 403; use a personal API key.
Set ?dryRun=true to validate and lint without persisting: nothing is written, no audit entry is recorded, and collaborators are not notified. The response carries the same shape and the same validation and lint findings the committed write would, with dryRun: true — but needsRedeployment describes the state before the write, and warnings raised by persistence itself are necessarily absent.
/api/v2/workflows/{workflowId}/stateAuthorization
apiKey Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description.
In: header
Path Parameters
Unique workflow identifier.
1 <= lengthQuery Parameters
Validate and lint without persisting. The response is identical to the committed write of the same body, so a caller can inspect lint and then re-send the request for real. Nothing is written, no audit entry is recorded, and collaborators are not notified.
Request Body
application/json
A complete replacement draft graph for a workflow.
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://www.sim.ai/api/v2/workflows/3b1f7c92-8d4e-4a6b-9c0d-5e2f8a714b36/state" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "blocks": {}, "edges": [] }'{
"data": {
"id": "3b1f7c92-8d4e-4a6b-9c0d-5e2f8a714b36",
"warnings": [],
"needsRedeployment": true,
"dryRun": false,
"lint": {
"sources": [],
"sinks": [],
"orphanBlocks": [],
"emptyOutgoingPorts": [],
"invalidBranchPorts": [],
"invalidConnectionTargets": [],
"fieldIssues": [],
"unresolvedReferences": [],
"notes": []
}
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "Invalid request"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "API key required"
}
}{
"error": {
"code": "FORBIDDEN",
"message": "Insufficient workspace permissions",
"details": {
"code": "INSUFFICIENT_WORKSPACE_ROLE"
}
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Not found"
}
}{
"error": {
"code": "CONFLICT",
"message": "Webhook path already in use"
}
}{
"error": {
"code": "PAYLOAD_TOO_LARGE",
"message": "Request body is too large"
}
}{
"error": {
"code": "UNSUPPORTED_MEDIA_TYPE",
"message": "Request body must be sent as application/json"
}
}{
"error": {
"code": "LOCKED",
"message": "Workflow is locked"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "API rate limit exceeded",
"details": {
"retryAfter": "2026-01-01T00:00:30.000Z"
}
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error"
}
}{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Service temporarily unavailable"
}
}