API Endpoints
Full reference for the daggle REST API. Base URL: http://localhost:{port}/api/v1.
System
GET /api/v1/health
Health check.
Response:
{
"status": "ok",
"version": "0.5.0",
"uptime_seconds": 3621
}curl -s http://localhost:8787/api/v1/health | jq .DAGs
GET /api/v1/dags
List all DAGs.
Response: flat array.
[
{
"name": "etl-daily",
"steps": 4,
"schedule": "0 3 * * *",
"last_status": "success",
"last_run": "2025-01-15T03:00:12Z"
}
]curl -s http://localhost:8787/api/v1/dags | jq .GET /api/v1/dags/{name}
Get details for a single DAG.
Response:
{
"name": "etl-daily",
"steps": 4,
"step_ids": ["fetch", "transform", "validate", "load"],
"schedule": "0 3 * * *",
"workdir": "/home/user/etl",
"r_version": "4.4.1",
"last_status": "success",
"last_run_id": "20250115T030012-abc12",
"last_run": "2025-01-15T03:00:12Z"
}curl -s http://localhost:8787/api/v1/dags/etl-daily | jq .POST /api/v1/dags/{name}/run
Trigger a new run. Returns immediately; poll status via the runs endpoint.
Request body (optional):
{
"params": {
"date": "2025-01-15",
"mode": "full"
}
}Response (201):
{
"run_id": "20250115T103000-abc12",
"status": "running"
}curl -s -X POST http://localhost:8787/api/v1/dags/etl-daily/run \
-H "Content-Type: application/json" \
-d '{"params": {"date": "2025-01-15"}}' | jq .POST /api/v1/dags/{name}/validate
Validate a DAG definition without running it.
Response (200):
{
"valid": true,
"warnings": []
}curl -s -X POST http://localhost:8787/api/v1/dags/etl-daily/validate | jq .Runs
GET /api/v1/dags/{name}/runs
List all runs for a DAG.
Response: flat array.
[
{
"run_id": "20250115T030012-abc12",
"started": "2025-01-15T03:00:12Z",
"status": "success",
"duration_seconds": 47,
"dag_hash": "a1b2c3d4"
}
]curl -s http://localhost:8787/api/v1/dags/etl-daily/runs | jq .GET /api/v1/dags/{name}/runs/{run_id}
Get full detail for a single run, including step statuses.
Use latest as run_id to get the most recent run.
Response:
{
"run_id": "20250115T030012-abc12",
"started": "2025-01-15T03:00:12Z",
"status": "success",
"duration_seconds": 47,
"dag_hash": "a1b2c3d4",
"steps": [
{"step_id": "fetch", "status": "success", "duration_seconds": 12},
{"step_id": "transform", "status": "success", "duration_seconds": 20},
{"step_id": "validate", "status": "success", "duration_seconds": 5},
{"step_id": "load", "status": "success", "duration_seconds": 10}
]
}curl -s http://localhost:8787/api/v1/dags/etl-daily/runs/latest | jq .POST /api/v1/dags/{name}/runs/{run_id}/cancel
Cancel a running run.
Response (200):
{
"run_id": "20250115T103000-abc12",
"status": "cancelled"
}curl -s -X POST http://localhost:8787/api/v1/dags/etl-daily/runs/20250115T103000-abc12/cancel | jq .Steps
GET /api/v1/dags/{name}/runs/{run_id}/steps
List step statuses for a run.
Response: flat array.
[
{"step_id": "fetch", "status": "success", "duration_seconds": 12},
{"step_id": "transform", "status": "running", "duration_seconds": null},
{"step_id": "validate", "status": "pending", "duration_seconds": null}
]curl -s http://localhost:8787/api/v1/dags/etl-daily/runs/latest/steps | jq .GET /api/v1/dags/{name}/runs/{run_id}/steps/{step_id}/log
Get stdout and stderr for a step.
Response:
{
"step_id": "fetch",
"stdout": "Fetching data from API...\nReceived 1432 rows.\n",
"stderr": ""
}curl -s http://localhost:8787/api/v1/dags/etl-daily/runs/latest/steps/fetch/log | jq .POST /api/v1/dags/{name}/runs/{run_id}/steps/{step_id}/approve
Approve a step that is waiting for approval.
Response (200):
{
"step_id": "load",
"status": "approved"
}curl -s -X POST http://localhost:8787/api/v1/dags/etl-daily/runs/latest/steps/load/approve | jq .POST /api/v1/dags/{name}/runs/{run_id}/steps/{step_id}/reject
Reject a step that is waiting for approval.
Response (200):
{
"step_id": "load",
"status": "rejected"
}curl -s -X POST http://localhost:8787/api/v1/dags/etl-daily/runs/latest/steps/load/reject | jq .Outputs
GET /api/v1/dags/{name}/runs/{run_id}/outputs
Get all outputs for a run.
Response: flat array.
[
{"step_id": "fetch", "key": "row_count", "value": "1432"},
{"step_id": "transform", "key": "output_path", "value": "/tmp/transformed.parquet"},
{"step_id": "validate", "key": "passed", "value": "true"}
]curl -s http://localhost:8787/api/v1/dags/etl-daily/runs/latest/outputs | jq .Maintenance
POST /api/v1/runs/cleanup
Remove old run data.
Request body:
{
"older_than": "30d"
}Response (200):
{
"removed": 42,
"freed_bytes": 10485760,
"freed": "10.0 MB"
}curl -s -X POST http://localhost:8787/api/v1/runs/cleanup \
-H "Content-Type: application/json" \
-d '{"older_than": "30d"}' | jq .Error responses
All errors return a JSON object with an error field:
{
"error": "DAG 'foo' not found"
}Status codes:
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (new run triggered) |
| 400 | Bad request (invalid params, malformed body) |
| 404 | Resource not found |
| 409 | Conflict (e.g., cancelling an already-finished run) |
| 500 | Internal server error |