Flows and deployments
A flow describes the tasks and dependencies in a workflow. A flow version identifies a registered revision. A deployment gives one version a reusable name, an environment, and execution settings. Your application normally starts a deployment by name; promotion or rollback changes which version that name uses.
On this page
Operations and permissionsRegister a flow specificationUpload an executable artifactCreate and update deploymentsChange versions and roll backWorking copies and editingCommon problemsUse Deploy and release a flow for the CLI workflow. This page describes the REST contract for custom tooling. Request and response fields are defined in the OpenAPI reference.
Operations and permissions
| Operation | Permission | Purpose |
|---|---|---|
GET /flows | flows.read | List flows with limit, next_token, and optional environment. |
GET /flows/{flow_name}/latest | flows.read | Latest registered version, including its specification. |
GET /flows/{flow_name}/versions | flows.read | Version history in descending deployment-version order. |
GET /flows/{flow_name}/{flow_version} | flows.read | A specific version and specification. |
POST /flows | flows.write | Register a specification and metadata. |
DELETE /flows/{flow_name} | flows.write | Delete the flow's versions, deployments, schedules, run history, and associated artifacts/logs. |
POST /artifacts/initiate, /complete, /abort | flows.write | Upload an executable artifact and register a deployment. |
GET /deployments, GET /deployments/{name} | flows.read | List or inspect deployments. |
POST /deployments | flows.write | Create or replace a named deployment. |
PATCH /deployments/{name} | flows.write | Change its active version. |
PUT /deployments/{name}/settings | flows.write | Update execution and scheduling settings. |
POST /deployments/{name}/rollback | flows.write | Point back to a selected version. |
DELETE /deployments/{name} | flows.write | Remove the deployment. |
Flow deletion is broad and cannot be used to remove just one version. Stop active runs and save needed evidence before deleting. If you only want to stop scheduled execution, pause its schedule.
Register a flow specification
POST /flows accepts flow_spec with required name and version; it can include tasks, task_runs, edges, parameters, and outputs. Additional specification fields are accepted. Prefer the SDK's generated specification to constructing task graphs manually.
{
"flow_spec": {
"name": "orders_daily",
"version": "1",
"tasks": {},
"task_runs": [],
"edges": [],
"parameters": []
},
"status": "ACTIVE",
"tags": {"team": "data", "domain": "commerce"},
"namespace": "analytics"
}This example registers an empty specification for illustration; it does not upload executable Python code. Registering a specification alone is not the deployment path for a Python application. Use artifact upload or dagy deploy for execution.
Optional registration fields include artifact_s3_uri, schedule, timezone, deployment_name, default_executor, status, tags, and namespace. An artifact locator must refer to the corresponding executable artifact. Treat returned locator fields as opaque identifiers, and do not invent storage locations.
Upload an executable artifact
Build the ZIP with dagy build. Custom upload clients use a three-step protocol:
- Initiate the upload.
- Upload each returned part to its signed URL, retaining its
ETagresponse header. - Complete the upload using the original identifiers and collected part results.
Initiate:
POST /artifacts/initiate
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN{
"flow_name": "orders_daily",
"flow_version": "1",
"deployment_name": "orders-develop",
"file_size": 1048576,
"part_size": 8388608
}Use the actual ZIP size in bytes. The response contains upload_id, artifact_key, expires_at, and parts, each with part_number, url, and size. Send raw binary bytes with HTTP PUT to each signed URL. Do not attach your Dagy bearer token to the signed URL request. URLs expire after one hour; split the file using the returned part sizes.
Complete:
{
"upload_id": "RETURNED_UPLOAD_ID",
"artifact_key": "RETURNED_ARTIFACT_KEY",
"parts": [{"part_number": 1, "etag": "RETURNED_ETAG"}],
"deployment_name": "orders-develop",
"flow_name": "orders_daily",
"flow_version": "1",
"environment": "develop",
"execution_mode": "nano",
"status": "ACTIVE"
}Send that body to POST /artifacts/complete. Include the full generated flow_spec from the artifact when implementing your own client so graph and parameter inspection remain available. Optional fields include schedule/timezone, tags, namespace, dependency package slugs, and code_hash.
Completion returns flow_name, flow_version, deployment_name, deployment_version, environment, code_hash, and an artifact locator. It registers the executable flow and updates the named deployment. Names and versions must match those used at initiation. Do not reuse someone else's upload identifiers.
For an abandoned upload, POST /artifacts/abort with upload_id and artifact_key returns 204. Default upload limits are 5 GiB per file, 5–512 MiB effective part size, and at most 10,000 parts. The default requested part size is 8 MiB. A larger artifact does not imply every runtime can execute it.
Create and update deployments
For an already registered version:
{
"name": "orders-develop",
"flow_name": "orders_daily",
"flow_version": "1",
"environment": "develop",
"execution_mode": "nano",
"tags": {"team": "data"},
"dep_package_slugs": []
}Send this to POST /deployments. environment defaults to develop and execution_mode defaults to nano. Keep a stable deployment name for callers and use a different name for each environment. Do not assume create rejects an existing name; it can replace that deployment.
Read details with GET /deployments/orders-develop. The list endpoint accepts environment and a positive limit, default 100 and capped at 500. It has no continuation token.
Change only execution settings with PUT /deployments/orders-develop/settings:
{
"execution_mode": "micro",
"tags": {"team": "data", "release": "2026-09"},
"dep_package_slugs": ["YOUR_PACKAGE_SLUG"]
}Use slugs from dependency packages. Supported settings are execution_mode, default_executor, schedule, tags, and dep_package_slugs. Send at least one non-null field; an empty update returns 400. Collection values replace the existing collection; use [] to remove dependency package attachments. Null does not clear a setting.
Prefer execution_mode for runtime selection: nano, micro, small, medium, large, or xlarge. GET /backends reports configured runtime capabilities. For sizing and availability, see Execution.
Change versions and roll back
Select a registered version using GET /flows/orders_daily/versions, then send:
PATCH /deployments/orders-develop{"flow_version":"2"}To record a rollback explicitly:
POST /deployments/orders-develop/rollback{"target_flow_version":"1"}Rollback returns deployment_name, previous_flow_version, new_flow_version, and rolled_back_at. It changes the deployment pointer; it does not undo data written by past runs or restore old environment variables or secrets. Confirm the selected version exists before changing it, then inspect the deployment and start a validation run.
For a new environment, use promotion. Promotion has settings-copy limitations, so inspect the target before production use.
Working copies and editing
The flow editor uses POST /flows/{flow_name}/draft, then GET and PUT /flows/{flow_name}/draft/source. Editing a working copy does not deploy it. The flow builder guide explains visual drafts, Python editing, and publishing.
Common problems
| Problem | Resolution |
|---|---|
403 on upload or registration | Use a key/session with flows.write; default UI keys only read. |
400 during upload completion | Keep initiation identifiers unchanged; supply the correct part ETags, name, and version. |
| Signed upload URL expired | Abort the abandoned upload and initiate another. |
| Deployment points to an unavailable version | Register/deploy that version before changing the deployment. |
| Code was registered but cannot execute | Upload the executable artifact and required dependencies. |
| CLI skips unchanged code | Use --force when deliberately creating a deployment despite the unchanged code hash. |
| Schedule text exists but no run occurs | Inspect the actual schedule resource, enabled state, timezone, and next run. |