The Airflow REST API
Everything the UI Does, Callable From Outside
The Case Studies section's event-driven pipeline already uses one REST API call — triggering a DAG run from a Lambda function. That's one endpoint out of a full, stable API surface covering essentially everything the Airflow UI itself can do: trigger runs, inspect state, manage Connections and Variables, even manage users.
Authentication
curl -X POST "https://airflow.company.com/auth/token" \
-H "Content-Type: application/json" \
-d '{"username": "api_user", "password": "..."}'
# Returns a JWT access token, used as a Bearer token on every subsequent call
Triggering a DAG Run
The exact call the Case Study's Lambda function makes:
curl -X POST "https://airflow.company.com/api/v1/dags/sales_etl/dagRuns" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"conf": {"triggered_by": "lambda"}}'
Checking Run Status
curl "https://airflow.company.com/api/v1/dags/sales_etl/dagRuns/manual__2026-09-05T06:00:00" \
-H "Authorization: Bearer $TOKEN"
Returns the same state field (queued, running, success, failed) shown in every Graph View screenshot throughout this course — this is the programmatic equivalent of looking at the UI.
Managing Connections and Variables Programmatically
# Create a Connection via API instead of the UI
curl -X POST "https://airflow.company.com/api/v1/connections" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"connection_id": "warehouse", "conn_type": "postgres", "host": "warehouse.internal"}'
This is how infrastructure-as-code tooling (Terraform providers for Airflow, custom bootstrap scripts) manages Connections without a human clicking through the UI — the exact same operation, just scripted.
The Python Client
For calling the API from Python rather than raw curl, the official client wraps every endpoint:
from airflow_client.client import ApiClient, Configuration
from airflow_client.client.api import dag_run_api
config = Configuration(host="https://airflow.company.com/api/v1", username="api_user", password="...")
with ApiClient(config) as api_client:
api = dag_run_api.DAGRunApi(api_client)
run = api.post_dag_run(dag_id="sales_etl", dag_run=...)
Any admin panel or internal tool that needs to show live DAG status or let non-technical users trigger a known pipeline is almost always built as a thin wrapper around this exact REST API - not by embedding the Airflow UI itself.
An API user/token used for one specific integration (like the Case Study's Lambda trigger) should have a Role (see the RBAC page) scoped to only what that integration needs - typically just "can create on DAG Runs" for a single DAG, not a blanket Admin token.