Programmatically interact with Domino using python-domino SDK and REST APIs. Covers authentication, running jobs, managing projects, file operations, model deployment, and automation. Use when automating Domino workflows, integrating with CI/CD, or building custom tooling around Domino.
This skill helps users work with the Domino Python SDK (python-domino) and REST APIs to programmatically interact with Domino.
Activate this skill when users want to:
Domino provides two main programmatic interfaces:
# Install from PyPI
pip install dominodatalab
# Or install with extras
pip install "dominodatalab[data]"Add to requirements.txt:
dominodatalab>=1.4.0Or Dockerfile:
RUN pip install dominodatalabCanonical guide: https://docs.domino.ai/cloud/reference/api/domino-api-authentication
Do not use API keys (X-Domino-Api-Key, DOMINO_USER_API_KEY, api_key=). Use PAT or service account tokens only when calling from outside a run.
Domino injects DOMINO_USER_HOST / DOMINO_API_HOST (same base; prefer DOMINO_USER_HOST). When JWT credential propagation is enabled, DOMINO_API_PROXY is the forwarded platform API base (not the same as http://localhost:8899/access-token).
| Pattern | When | Code |
|---|---|---|
| API proxy (preferred) | DOMINO_API_PROXY is set (Domino 5.4.0+ in runs with JWT credential propagation configured) | Call {DOMINO_API_PROXY}{path} with no Authorization header. The JWT sidecar adds the starting user access JWT on the forwarded request. |
| Access token + platform host | Older deployments, or you intentionally call DOMINO_USER_HOST / DOMINO_API_HOST instead of the proxy URL | Fetch a short-lived JWT, then Bearer on the platform base. |
API proxy (preferred on 5.4.0+):
import os
import requests
base_url = os.environ["DOMINO_API_PROXY"].rstrip("/")
headers = {}
response = requests.get(f"{base_url}/v4/users/self")curl "$DOMINO_API_PROXY/v4/users/self"The proxy is not guaranteed on every deployment or run type. If DOMINO_API_PROXY is missing, use the access-token pattern or PAT from outside the cluster.
Access token + DOMINO_USER_HOST (legacy-friendly in-run): use the In-run setup block below; it covers both proxy and access-token paths.
Before Domino 5.4.0: JWT file propagation (DOMINO_TOKEN_FILE) was used before the API proxy; legacy behavior may still exist if admins enable EnableLegacyJwtTooling. Prefer migrating to the proxy pattern on supported versions.
Your code is not executing inside a Domino workspace, job, or app container. Domino does not inject DOMINO_API_PROXY, DOMINO_USER_HOST, or an access-token sidecar. You must supply both:
https://yourcompany.engineering.domino.tech. Not http://127.0.0.1:8763 and not values copied from an in-run environment.Authorization: Bearer with a token you store securely (secret manager, CI variable, not committed to git):
POST /api/pat/v1/tokens while already authenticated.import requests
deployment_url = "https://yourcompany.engineering.domino.tech"
pat = "..." # from your secret store; never hardcode in shared repos
response = requests.get(
f"{deployment_url.rstrip('/')}/v4/users/self",
headers={"Authorization": f"Bearer {pat}"},
)See https://docs.domino.ai/cloud/reference/api/domino-api-authentication .
Use inside a workspace, job, or app only:
import os
import requests
if os.environ.get("DOMINO_API_PROXY"):
base_url = os.environ["DOMINO_API_PROXY"].rstrip("/")
headers = {}
else:
base_url = (os.environ.get("DOMINO_USER_HOST") or os.environ.get("DOMINO_API_HOST") or "").rstrip("/")
token = requests.get("http://localhost:8899/access-token").text.strip()
headers = {"Authorization": f"Bearer {token}"}from domino import Domino
domino = Domino("owner/project-name")Configure the SDK with host + Bearer token per the product auth page. Never pass api_key=.
from domino import Domino
domino = Domino()
# Create project
project = domino.project_create(
project_name="my-new-project",
owner_name="username"
)
# Get project info
info = domino.project_info()
print(f"Project: {info['name']}")
print(f"ID: {info['id']}")# Start a job
run = domino.runs_start(
command="python train.py --epochs 100",
hardware_tier_name="medium",
environment_id="env-id"
)
print(f"Run ID: {run['runId']}")
# Start job with different commit
run = domino.runs_start(
command="python train.py",
commit_id="abc123"
)
# Check status
status = domino.runs_status(run['runId'])
print(f"Status: {status['status']}")
# Wait for completion
domino.runs_wait(run['runId'])
# Get logs
logs = domino.runs_get_logs(run['runId'])
print(logs)
# Stop a run
domino.runs_stop(run['runId'])# Start workspace
workspace = domino.workspace_start(
hardware_tier_name="medium",
environment_id="env-id",
workspace_type="JupyterLab"
)
print(f"Workspace ID: {workspace['workspaceId']}")
# Stop workspace
domino.workspace_stop(workspace['workspaceId'])# Upload file
domino.files_upload(
path="local/file.csv",
dest_path="/mnt/code/data/"
)
# Download file
domino.files_download(
path="/mnt/code/results/output.csv",
dest_path="local/output.csv"
)
# List files
files = domino.files_list("/mnt/code/")
for f in files:
print(f['path'])# Create dataset
dataset = domino.datasets_create(
name="training-data",
description="Training dataset"
)
# List datasets
datasets = domino.datasets_list()
# Create snapshot
snapshot = domino.datasets_snapshot(
dataset_name="training-data",
tag="v1.0"
)# List environments
environments = domino.environments_list()
for env in environments:
print(f"{env['name']}: {env['id']}")
# Get environment details
env = domino.environment_get("env-id")# Publish model
model = domino.model_publish(
file="model.py",
function="predict",
environment_id="env-id",
name="my-classifier",
description="Classification model"
)
print(f"Model ID: {model['id']}")
# List models
models = domino.models_list()
# Get model info
model_info = domino.model_get("model-id")Use the Authentication setup (base_url, headers) for examples below.
response = requests.get(f"{base_url}/api/projects/beta/projects", headers=headers or None)
projects = response.json()| Endpoint | Method | Description |
|---|---|---|
/v4/projects | GET | List projects |
/v4/projects/{id}/runs | POST | Start a run |
/v4/projects/{id}/runs/{runId} | GET | Get run status |
/v4/projects/{id}/files | GET | List files |
/v4/gateway/runs/{runId}/logs | GET | Get run logs |
/v4/models | GET | List models |
/v4/models/{id}/latest/model | POST | Call model |
Separate SDK for data access:
from domino_data.data_sources import DataSourceClient
# Initialize client
client = DataSourceClient()
# List data sources
sources = client.list_data_sources()
# Query data source
df = client.get_datasource("my-datasource").query(
"SELECT * FROM customers WHERE region = 'US'"
)# trigger_training.py - Call from CI/CD pipeline
from domino import Domino
import sys
domino = Domino("team/ml-project")
# Start training job
run = domino.runs_start(
command="python train.py",
hardware_tier_name="gpu-large"
)
# Wait for completion
result = domino.runs_wait(run['runId'])
if result['status'] != 'Succeeded':
print(f"Training failed: {result['status']}")
sys.exit(1)
print("Training completed successfully!")# Run multiple experiments
from domino import Domino
import itertools
domino = Domino("team/experiments")
# Parameter grid
params = {
"learning_rate": [0.01, 0.001, 0.0001],
"batch_size": [32, 64, 128]
}
# Generate combinations
combinations = list(itertools.product(*params.values()))
param_names = list(params.keys())
# Submit all experiments
runs = []
for combo in combinations:
param_str = " ".join(
f"--{name}={value}"
for name, value in zip(param_names, combo)
)
run = domino.runs_start(
command=f"python experiment.py {param_str}",
hardware_tier_name="gpu-small"
)
runs.append(run['runId'])
print(f"Started run {run['runId']} with {param_str}")
# Wait for all to complete
for run_id in runs:
result = domino.runs_wait(run_id)
print(f"Run {run_id}: {result['status']}")from domino import Domino
domino = Domino("team/model-deployment")
# 1. Train model
train_run = domino.runs_start(command="python train.py")
domino.runs_wait(train_run['runId'])
# 2. Evaluate model
eval_run = domino.runs_start(command="python evaluate.py")
domino.runs_wait(eval_run['runId'])
# 3. Deploy if evaluation passes
# (Check evaluation results first)
model = domino.model_publish(
file="serve.py",
function="predict",
name="production-model"
)
print(f"Model deployed: {model['id']}")from domino import Domino
from domino.exceptions import DominoException
try:
domino = Domino("team/project")
run = domino.runs_start(command="python train.py")
except DominoException as e:
print(f"Domino error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")Proxy without a header when DOMINO_API_PROXY is set; otherwise access-token + platform host; PAT/SA only outside a run.
import time
from domino.exceptions import DominoException
def api_call_with_retry(func, max_retries=3):
for attempt in range(max_retries):
try:
return func()
except DominoException as e:
if "rate limit" in str(e).lower():
time.sleep(2 ** attempt)
else:
raise
raise Exception("Max retries exceeded")import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def start_run(command):
logger.info(f"Starting run: {command}")
run = domino.runs_start(command=command)
logger.info(f"Run ID: {run['runId']}")
return runFor comprehensive REST API documentation, see these specialized guides:
| Guide | Description |
|---|---|
| API-PROJECTS.md | Projects, collaborators, Git repos, goals |
| API-JOBS.md | Jobs, scheduled jobs, logs, tags |
| API-DATASETS.md | Datasets, snapshots, tags, grants |
| API-MODELS.md | Model APIs, deployments, registry |
| API-MODEL-SERVING.md | Lifecycle, v1/v2 registry split, invoke vs management |
| API-ENVIRONMENTS.md | Environments, revisions, Dockerfile |
| API-APPS.md | Apps endpoint catalog (see apps/API-APPS.md for v1 automation) |
| API-ADMIN.md | Users, orgs, hardware tiers, data sources |
| API-REFERENCE.md | Complete endpoint reference |
OpenAPI and route discovery: API-SPECS.md.
Product docs:
92a240b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.