A command-line tool for interacting with Apache Airflow 3.x via its REST API.
Install with the extra matching your Airflow server's major version:
# Airflow 3.x
pip install airflow-api-client[airflow3]Or install from source:
git clone https://github.com/rackerlabs/airflow-api-client.git
cd airflow-api-client
uv sync --extra airflow3All required inputs can be supplied on the command line. However, for convenience, you can also create profiles in a config file to avoid having to specify common parameters repeatedly.
Create a config file at ~/.config/airflow-api-client/config.ini:
[default]
endpoint = https://airflow.example.com
username = your_username
password = your_password
verbose = 0
[production]
endpoint = https://airflow.prod.example.com
username = prod_userUse profiles with -P:
airflow-api-client -P production list dagsYou may also specify a custom config file location with -C or --config-file:
airflow-api-client -C /path/to/config.ini list dagsProfiles can be created using the profile create command:
# Create a profile (password stored securely in system keyring if available)
airflow-api-client profile create -e https://airflow.prod.example.com -u my_user
# Create a named profile
airflow-api-client profile create --profile-name production -e https://airflow.prod.example.com -u my_user
# Force plaintext password storage (not recommended)
airflow-api-client profile create -e https://airflow.prod.example.com -u my_user --no-keyring-password
# Pipe password from another source
echo "my_password" | airflow-api-client profile create -e https://airflow.prod.example.com -u my_user
# Use AIRFLOW_API_CLIENT_PASSWORD environment variable
AIRFLOW_API_CLIENT_PASSWORD=secret airflow-api-client profile create -e https://airflow.prod.example.com -u my_userWhen run interactively, the command will prompt for any missing fields (endpoint, username, password) with hidden input for the password.
Passwords can be stored securely in the system keyring (e.g. GNOME Keyring, macOS Keychain) instead of plaintext in the config file. Install with:
pip install airflow-api-client[airflow3,keyring]When keyring is installed, profile create will automatically store passwords in the system
keyring. Use --no-keyring-password to force plaintext storage in the config file instead.
When authenticating, if no password is provided via --password, environment variable, or config
file, the client will automatically check the system keyring as a fallback.
If no configuration file is used, the default required inputs are:
--endpoint, --username, and --password. (You can also set these via environment variables as
described below.)
# List all DAGs
airflow-api-client list dags
# List DAG runs for a specific DAG
airflow-api-client list dag-runs my_dag
# Get details about a specific DAG
airflow-api-client get dag my_dag
# Get logs for a DAG run
airflow-api-client get log my_dag/run_id
# Run a DAG
airflow-api-client run my_dag --conf '{"key": "value"}'
# Pause / unpause a DAG
airflow-api-client pause my_dag
airflow-api-client unpause my_dag
# Get XCom results
airflow-api-client xcom my_dag/run_id/task_id/return_value
# Create a payload template
airflow-api-client create-payload my_dag
# Make a raw API request
airflow-api-client raw GET /api/v2/dagsThe default authentication provider uses username/password to obtain JWT tokens through the standard /auth/token endpoint.
See below for custom authentication providers if you need to support other auth mechanisms.
Certain environment variables are supported for fallback configuration.
export AIRFLOW_API_CLIENT_ENDPOINT=https://airflow.example.com
export AIRFLOW_API_CLIENT_PASSWORD=your_password
export AIRFLOW_API_CLIENT_USERNAME=your_username
export AIRFLOW_API_CLIENT_TOKEN=your_jwt_tokenThe order of precedence for configuration is:
- Command-line arguments
- Environment variables
- Profile from config file
Additionally, the output format for the human readable output can be configured using
AIRFLOW_API_CLIENT_TABLE_FORMAT which must be one of the formats supported by the tabulate
library (e.g. github, grid, fancy_grid, etc.). If not set, it defaults to grid.
airflow-api-client -e https://airflow.example.com -u username -p password list dagsList Airflow resources. Supports subcommands for different resource types.
# List all DAGs
airflow-api-client list dags
# List DAG runs for a specific DAG (most recent first, default limit: 10)
airflow-api-client list dag-runs my_dag
airflow-api-client list dag-runs my_dag --limit 20
# List task instances for a DAG run
airflow-api-client list task-instances my_dag/run_idAll list subcommands support filtering with --filter:
airflow-api-client list dags --filter "is_paused == true"
airflow-api-client list dag-runs my_dag --filter "state == success"Get detailed information about a specific resource.
# Get DAG details
airflow-api-client get dag my_dag
# Get DAG run details
airflow-api-client get dag-run my_dag/run_id
# Get task instance details
airflow-api-client get task-instance my_dag/run_id/task_id
# Get logs for all tasks in a DAG run
airflow-api-client get log my_dag/run_id
# Get log for a specific task
airflow-api-client get log my_dag/run_id/task_id
# Get log for a specific try number
airflow-api-client get log my_dag/run_id/task_id --try-number 2
# Custom timestamp format for human output
airflow-api-client get log my_dag/run_id --time-format "%H:%M:%S"Trigger a DAG run:
# Interactive mode (prompts for parameters, if any are required)
airflow-api-client run my_dag
# With configuration
airflow-api-client run my_dag --conf '{"param": "value"}'
# From file
airflow-api-client run my_dag --conf @config.json
# With a custom run ID
airflow-api-client run my_dag --run-id my_custom_run_id
# Trigger without waiting for completion
airflow-api-client run my_dag --no-waitPause or unpause a DAG:
airflow-api-client pause my_dag
airflow-api-client unpause my_dagRetrieve XCom entries:
# All XComs for a DAG run
airflow-api-client xcom my_dag/run_id
# All XComs for a specific task
airflow-api-client xcom my_dag/run_id/my_task
# Specific XCom key
airflow-api-client xcom my_dag/run_id/my_task/return_valueThe positional argument for the xcom command is in the format dag_id/run_id/task_id/key, where
task_id and key are optional. If only dag_id and run_id are provided, it will list all
XComs for that DAG run. If dag_id, run_id, and task_id are provided, it will list all XComs
for that task. If all four components are provided, it will retrieve the specific XCom value.
Generate a payload template for a DAG:
airflow-api-client create-payload my_dag > payload.jsonThe run sub-command accepts payloads in files containing JSON. This command can generate a payload
based on the DAG's parameters, which can then be supplied to the run command by prefixing the
--conf argument with @:
airflow-api-client create-payload my_dag --output-file payload.json
airflow-api-client run my_dag --conf @payload.jsonMake raw API requests directly to Airflow. This is a power-user command that gives full control
over the API interaction. The URL must include the full API path (e.g. /api/v2/dags).
# GET request
airflow-api-client raw GET /api/v2/dags
# POST with payload
airflow-api-client raw POST /api/v2/dags/my_dag/dagRuns --payload '{"dag_run_id": "test", "conf": {}}'
# With custom headers
airflow-api-client raw GET /api/v2/dags --header "X-Custom=value"
# PATCH request
airflow-api-client raw PATCH /api/v2/dags/my_dag --payload '{"is_paused": true}'Supported methods: GET, POST, PUT, PATCH, DELETE. Output defaults to JSON.
Control output format with -f:
# Human-readable (default)
airflow-api-client list dags
# JSON
airflow-api-client -f json list dags
# YAML (available if PyYAML is installed)
airflow-api-client -f yaml list dagsThe human-readable table format can be customised by setting the AIRFLOW_API_CLIENT_TABLE_FORMAT
environment variable to any format supported by the
tabulate library (e.g. simple, github,
fancy_grid, psql, orgtbl, etc.). Defaults to grid.
Control logging verbosity:
# Default (info and above)
airflow-api-client list dags
# Debug level
airflow-api-client -v list dags
# Debug with HTTP traffic
airflow-api-client -vv list dagsDo note that all logging takes place on stderr by default, so that the output can be easily piped to other tools without mixing with logs.
Create a custom auth provider by subclassing AirflowAPIClientAuthProvider:
If, for example, you have an external system to obtain tokens from, you can implement a custom auth provider like this:
# my_auth.py
from airflow_api_client.auth import AirflowAPIClientAuthProvider
class MyAuthProvider(AirflowAPIClientAuthProvider):
@property
def client_token(self):
# Your custom token logic
return self.get_token_from_somewhere()Or if you want to implement a provider that obtains the password from a secret manager:
# my_auth.py
from airflow_api_client.auth import AirflowAPIClientAuthProvider
class MyAuthProvider(AirflowAPIClientAuthProvider):
@property
def password(self):
# Your custom password retrieval logic
return self.get_password_from_secret_manager()Any arguments your custom auth provider needs can be added to the parser by overriding the
add_arguments class method:
# my_auth.py
from airflow_api_client.auth import AirflowAPIClientAuthProvider
class MyAuthProvider(AirflowAPIClientAuthProvider):
@classmethod
def add_arguments(cls, profile: str, parser: "ArgumentParser", config: "RawConfigParser"):
# Add custom arguments to the parser
parser.add_argument("--my-arg", help="An argument for my auth provider")
@property
def client_token(self):
# Your custom token logic that can use self.args.my_arg
return self.get_token_using_arg(self.args.my_arg)Register it via entry points in pyproject.toml:
[project.entry-points."airflow_api_client.auth"]
myauth = "my_package.my_auth:MyAuthProvider"Use it:
airflow-api-client --auth-provider myauth list dagsAdd custom commands by creating a plugin:
# my_commands.py
from airflow_api_client.commands import Command
class MyCommand(Command):
name = "mycommand"
help = "My custom command"
@classmethod
def add_arguments(cls, parser):
parser.add_argument("--option", help="An option")
def execute(self, app):
print("Executing my command")Here parser is a command-specific argument parser that you can add arguments to, and app is the
main application instance which has a reference to the API client client and the parsed CLI args.
See typedefs.py for details.
Register via entry points:
[project.entry-points."airflow_api_client.commands"]
mycommand = "my_package.my_commands:MyCommand"# Clone and install
git clone https://github.com/rackerlabs/airflow-api-client.git
cd airflow-api-client
uv sync --extra dev --extra airflow3
# Run linters
uv run black airflow_api_client/
uv run isort airflow_api_client/
uv run pylint airflow_api_client/
uv run flake8 airflow_api_client/
# Run tests
uv run pytest
# Run the CLI
uv run airflow-api-client --helpThe Apache Airflow project maintains a separate CLI tool,
airflowctl (pip install apache-airflow-ctl), which is auto-generated from the Airflow OpenAPI spec. It provides
comprehensive coverage of the REST API but requires familiarity with the API endpoints and their
parameters.
This tool takes a different approach — it's a workflow-oriented tool designed for day-to-day operations without needing intimate knowledge of the Airflow API:
run my_daginteractively prompts for parameters based on the DAG's schemacreate-payloadintrospects DAG parameters and generates a payload templatexcom my_dag/run_id/task_iduses natural path-style identifiers instead of API query parametersrunpolls for completion and displays logs and XCom results automatically- Config file profiles let you switch between environments with
-P production - Pluggable auth providers and custom commands via entry points
- Human-readable output with filtering (
--filter "state == success")
In short: airflowctl is a CLI skin over the REST API, this tool is a workflow tool that
use the REST API.
Apache-2.0
- Python 3.10+
- Apache Airflow 3.1+ (install with
[airflow3]extra)