Skip to content
Docs/API reference

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 pageOperations and permissionsRegister a flow specificationUpload an executable artifactCreate and update deploymentsChange versions and roll backWorking copies and editingCommon problems

Use 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

OperationPermissionPurpose
GET /flowsflows.readList flows with limit, next_token, and optional environment.
GET /flows/{flow_name}/latestflows.readLatest registered version, including its specification.
GET /flows/{flow_name}/versionsflows.readVersion history in descending deployment-version order.
GET /flows/{flow_name}/{flow_version}flows.readA specific version and specification.
POST /flowsflows.writeRegister a specification and metadata.
DELETE /flows/{flow_name}flows.writeDelete the flow's versions, deployments, schedules, run history, and associated artifacts/logs.
POST /artifacts/initiate, /complete, /abortflows.writeUpload an executable artifact and register a deployment.
GET /deployments, GET /deployments/{name}flows.readList or inspect deployments.
POST /deploymentsflows.writeCreate or replace a named deployment.
PATCH /deployments/{name}flows.writeChange its active version.
PUT /deployments/{name}/settingsflows.writeUpdate execution and scheduling settings.
POST /deployments/{name}/rollbackflows.writePoint back to a selected version.
DELETE /deployments/{name}flows.writeRemove 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.

JSON
{
  "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:

  1. Initiate the upload.
  2. Upload each returned part to its signed URL, retaining its ETag response header.
  3. Complete the upload using the original identifiers and collected part results.

Initiate:

HTTP
POST /artifacts/initiate
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

HTTP
PATCH /deployments/orders-develop
JSON
{"flow_version":"2"}

To record a rollback explicitly:

HTTP
POST /deployments/orders-develop/rollback
JSON
{"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

ProblemResolution
403 on upload or registrationUse a key/session with flows.write; default UI keys only read.
400 during upload completionKeep initiation identifiers unchanged; supply the correct part ETags, name, and version.
Signed upload URL expiredAbort the abandoned upload and initiate another.
Deployment points to an unavailable versionRegister/deploy that version before changing the deployment.
Code was registered but cannot executeUpload the executable artifact and required dependencies.
CLI skips unchanged codeUse --force when deliberately creating a deployment despite the unchanged code hash.
Schedule text exists but no run occursInspect the actual schedule resource, enabled state, timezone, and next run.