By Nisha Choudhary, Arshnoor Kaur
1. The Challenge & Solution
Let’s start with a scenario where your enterprise needs to add 300 databases to Db2 Genius Hub for centralized monitoring. Manual addition through the web console requires 5-10 minutes per database which adds up to over 25 hours of repetitive work. This approach of manually adding each database connection introduces configuration drift, connection string errors, and diverts skilled resources from critical tasks.
Db2 Genius Hub's REST API eliminates this bottleneck. A Python script can onboard all 300 databases in minutes with consistent configuration and zero manual errors.
In this guide, we'll explore how to leverage the Db2 Genius Hub REST API to authenticate, add databases programmatically, retrieve alerts across multiple databases, and build complete automation scripts that transform database management from a manual chore into an efficient, repeatable process.
2. Introducing the Db2 Genius Hub REST API
The Db2 Genius Hub REST API provides programmatic access to database management and monitoring capabilities. Operations available in the web console are accessible programmatically, enabling integration with existing automation frameworks, CI/CD pipelines, and infrastructure-as-code workflows.
Understanding REST:
REST (Representational State Transfer) uses standard HTTP methods as actions - GET (retrieve data), POST (create new items), PUT (update existing items), and DELETE (remove items). All data exchanges use JSON format, which every programming language can easily read and write.
Key Capabilities:
-
Authentication & Security: Token-based login which requires you to authenticate once and then receiving a temporary digital key for all subsequent API calls
-
Database Connection Operations: Add, update, remove, and configure database connections programmatically
-
Monitoring Configuration: Set up event monitors, define tablespaces, and schedule blackout periods (maintenance windows)
-
Alert Management: Retrieve and analyze alerts across all monitored databases in a single API call
-
Audit & Compliance: Enable audit logging and retrieve audit records for compliance reporting
-
Data Management: Configure automatic pruning of historical report data to manage storage
Operational Benefits:
Instead of manually adding 300 databases (25+ hours), you can write a script that completes the task in minutes with a consistent, error-free configuration. You can also include this automation whenever a new database is created and with this, automatically added to the IBM Db2 Genius Hub Instance.
Use the IBM Db2 Genius Hub documentation to start working with the API at https://www.ibm.com/docs/en/db2-genius-hub/1.1.x?topic=working-apis.
To access the full documentation and explore interactively at, you find the link to the full documentaion in the left lower section in the Genius Hub GUI. Alternatively, use the following URL where “you-server” is the machine, running the Genius Hub Instance: http[s]://<your-server>/dbapi/api/index_enterprise.html.



3. API Exploration Tools
Before diving into automation scripts, it's essential to familiarize yourself with the available endpoints and understand how they work. Several tools exist for API exploration, including Swagger UI, Postman, and others. In this guide, we'll use Swagger UI as an example to demonstrate how to set up an interactive API testing environment.
Swagger UI: Your Interactive API Playground
Swagger UI is a powerful open-source tool that transforms API documentation into an interactive testing environment. While Genius Hub provides API documentation in ReDoc format, you can set up Swagger UI separately to get hands-on experience with the APIs before writing automation scripts.
What is Swagger UI?
Swagger UI creates an interactive web interface from an OpenAPI specification file. It allows you to test API endpoints directly in your browser with a "Try it out" button with no coding required.
Setting Up Swagger UI for Genius Hub APIs:
Step 1: Download the OpenAPI Specification
-
Access your Genius Hub API documentation at http[s]://<your-server>/dbapi/api/index_enterprise.html
-
Click the "Download" button at the top of the page (labeled "Download OpenAPI specification")
-
Save the file - it will be named dbAPI_enterprise.inc.redoc.yaml
Step 2: Set Up Swagger UI Locally
-
Download Swagger UI from GitHub
-
Download the Source code (zip) file (easier to extract on Windows/Mac)
-
Alternatively, download Source code (tar.gz) if you prefer (common on Linux)
-
Extract the downloaded file to a local directory on your computer
-
Navigate to the dist folder within the extracted files
-
Copy your downloaded dbAPI_enterprise.inc.redoc.yaml file into the dist folder
-
Edit the swagger-initializer.js file to point to your spec file:
- Save the file
- Start a local web server (required due to browser security restrictions):
Step 3: Configure Authentication
-
In Swagger UI, click the "Authorize" button at the top
-
First, get your access token by testing the authentication endpoint:
-
Expand POST /dbapi/v4/auth/tokens
-
Click "Try it out"
-
Enter your userid and password
-
Click "Execute" and copy the token from the response
-
Return to "Authorize", paste your token as Bearer <your-token>, and click "Authorize"
What You Can Do with Swagger UI:
Once Swagger UI loads with your Genius Hub API specification, you can:
-
Browse all available API endpoints organized by category
-
View detailed parameter requirements for each endpoint
-
Understand request/response schemas and data structures
-
See example values and descriptions for each API operation
Best Practices:
-
Always authenticate first using the "Authorize" button
-
Start with GET requests before trying POST/PUT/DELETE
-
Test in development environments first
-
Save successful examples for automation scripts
4. The sample Python Application
The following sections walk through a Python script that reads database connection details from a CSV file and registers them with Db2 Genius Hub via the REST API. The script covers two main steps: first, obtaining an authentication token; second, iterating over each row in the CSV file and calling the database profile endpoint to register each database in bulk.
4.1 Generating an Authentication Token
NOTE: Before any of the automation in this guide can run, onboarding databases or pulling alerts, you need one thing first: a valid token.
Every Genius Hub API call requires authentication via a valid bearer token. You can generate a token using your Genius Hub credentials. The response provides a short-lived JWT token, which can be passed in the Authorization header of every subsequent API request. In case of long running automation scripts, token refresh needs to be handled. This has been covered in the full script in Section 6.
The endpoint:
POST /dbapi/v4/auth/tokens
Request body:
{
"userid": "your_username",
"password": "your_password"
}
Successful response (HTTP 200):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Full Python Code
import requests
GENIUS_HUB_URL = "http://your-server:11100/dbapi/v4"
def get_token(userid: str, password: str) -> str:
"""Authenticate with Genius Hub and return a bearer token."""
response = requests.post(
f"{GENIUS_HUB_URL}/auth/tokens",
json={"userid": userid, "password": password},
verify=False # Set to True and provide cert path in production
)
if response.status_code == 200:
token = response.json()["token"]
print("Authentication successful.")
return token
else:
raise RuntimeError(
f"Authentication failed: HTTP {response.status_code} — {response.text}"
)
# Usage
token = get_token("your_username", "your_password")
print(f"Token: {token[:40]}...") # Print first 40 chars only
Security note: Never hardcode credentials in your scripts. Use environment variables (os.environ["GH_PASSWORD"]) or a secrets manager such as HashiCorp Vault to supply them at runtime.
4.2 Adding a Database Connection via API
A connection profile in Db2 holds the JDBC connection details for the target database, the credentials Genius Hub uses to collect monitoring data, and any additional settings for the connection itself. Once a profile exists, Genius Hub starts monitoring that database automatically.
The endpoint:
POST /dbapi/v4/dbprofiles
|
|
|
|
name
|
Unique profile name shown in the console — choose a consistent naming convention
|
|
host
|
Hostname or IP of the Db2 server
|
|
port
|
Db2 TCP port (default 50000)
|
|
databaseName
|
The Db2 database name
|
|
dataServerType
|
DB2LUW for Linux/Unix/Windows, DB2Z for z/OS
|
|
collectionCred
|
Credentials used by Genius Hub to collect monitoring data — a read-only monitoring user is sufficient
|
|
operationCred
|
Credentials used for operational actions such as running SQL or jobs — can be the same user or a more privileged one depending on your security policy
|
|
sslConnection
|
Set to "true" and provide sslTrustStoreLocation and sslTrustStorePassword if your Db2 server requires an encrypted connection
|
|
comment
|
Optional free-text description — useful for tracking how and when profiles were created
|
A successful response returns HTTP 201 Created with an empty body. There might be other return codes. For example the return code “409 Conflict” means a profile with that name already exists.
Full Python Code
import requests
GENIUS_HUB_URL = "http://your-server:11100/dbapi/v4"
def add_database_profile(token: str, profile: dict) -> bool:
"""Add a single database connection profile to Genius Hub.
Returns True on success, False if the profile already exists.
Raises RuntimeError on unexpected errors.
"""
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
response = requests.post(
f"{GENIUS_HUB_URL}/dbprofiles",
json=profile,
headers=headers,
verify=False
)
if response.status_code == 201:
print(f" ✓ Added: {profile['name']}")
return True
elif response.status_code == 409:
print(f" ⚠ Already exists: {profile['name']} — skipping")
return False
else:
raise RuntimeError(
f" ✗ Failed to add {profile['name']}: "
f"HTTP {response.status_code} — {response.text}"
)
# Usage
profile = {
"name": "PROD_DB2_001",
"host": "db2-host-01.example.com",
"port": 50000,
"databaseName": "MYDB",
"dataServerType": "DB2LUW",
"collectionCred": {
"user": "db2inst1",
"password": "monitor_password",
"securityMechanism": "3",
"encryptionAlgorithm": "1",
"kerberosUseCachedTGT": "false"
},
"operationCred": {
"user": "db2inst1",
"password": "monitor_password",
"securityMechanism": "3",
"encryptionAlgorithm": "1",
"kerberosUseCachedTGT": "false",
"saveOperationCred": "false"
},
"sslConnection": "false",
"comment": "Onboarded via REST API"
}
added = add_database_profile(token, profile)
4.3. Adding Databases in Bulk
In order to solve the original problem of onboarding hundreds of databases, we now discuss a complete automated flow. For the example used in this documentation, we use a list of database in a CSV file that should be added to Db2 Genius Hub. So for setup discussed in this section, you need a CSV file with configuration details of all the databases that you want to monitor with Genius Hub.
The script reads database definitions from this CSV file, authenticates, and loops through every entry.
Sample input CSV file (databases.csv):
name,host,port,databaseName,userid,password,dataServerType
PROD_DB2_001,db2-host-01.example.com,50000,MYDB,db2monitor,monpass,DB2LUW
PROD_DB2_002,db2-host-02.example.com,50000,SALESDB,db2monitor,monpass,DB2LUW
DEV_DB2_001,dev-host-01.example.com,50000,DEVDB,db2monitor,devpass,DB2LUW
The complete automation script:
import csv
import os
import requests
import urllib3
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# ── Configuration ──────────────────────────────────────────────────────────────
GENIUS_HUB_URL = os.environ.get("GH_URL", "http://your-server:11100/dbapi/v4")
GH_USER = os.environ.get("GH_USER", "admin")
GH_PASSWORD = os.environ.get("GH_PASSWORD") # Always from environment
CSV_FILE = "databases.csv"
# ── Create a session with retry logic ─────────────────────────────────────────
def create_session():
"""Create a requests session with retry logic and proper configuration."""
session = requests.Session()
# Configure retry strategy
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS", "TRACE"]
)
adapter = HTTPAdapter(max_retries=retry_strategy, pool_connections=10, pool_maxsize=10)
session.mount("http://", adapter)
session.mount("https://", adapter)
return session
# ── Authentication ─────────────────────────────────────────────────────────────
def get_token(session: requests.Session, userid: str, password: str) -> str:
response = session.post(
f"{GENIUS_HUB_URL}/auth/tokens",
json={"userid": userid, "password": password},
verify=False,
timeout=30
)
if response.status_code == 200:
return response.json()["token"]
raise RuntimeError(f"Authentication failed: HTTP {response.status_code}")
# ── Build profile payload from CSV row ────────────────────────────────────────
def build_payload(row: dict) -> dict:
# Support both 'userid'/'password' and 'collectionUser'/'collectionPassword' column names
user = row.get("collectionUser") or row.get("userid", "")
password = row.get("collectionPassword") or row.get("password", "")
cred = {
"user": user,
"password": password,
"securityMechanism": "3",
"encryptionAlgorithm": "1",
"kerberosUseCachedTGT": "false"
}
return {
"name": row["name"],
"host": row["host"],
"port": str(row["port"]), # Send port as string
"databaseName": row["databaseName"],
"dataServerType": row.get("dataServerType", "DB2LUW"),
"collectionCred": cred,
"operationCred": {**cred, "saveOperationCred": "false"},
"sslConnection": row.get("ssl", "false"),
"comment": "Onboarded via REST API"
}
# ── Add a single database profile ──────────────────────────────────────────────
def add_profile(session: requests.Session, token: str, row: dict) -> str:
"""Returns 'added', 'exists', or 'error:<message>'."""
headers = {"Authorization": f"Bearer {token}"}
r = session.post(
f"{GENIUS_HUB_URL}/dbprofiles",
json=build_payload(row), headers=headers, verify=False, timeout=30
)
if r.status_code == 201:
return "added"
elif r.status_code == 409:
return "exists"
else:
return f"error:HTTP {r.status_code} — {r.text[:120]}"
# ── Main onboarding loop ───────────────────────────────────────────────────────
def main():
if not GH_PASSWORD:
raise EnvironmentError("Set the GH_PASSWORD environment variable before running.")
print(f"Connecting to Genius Hub: {GENIUS_HUB_URL}")
# Create session for connection pooling
session = create_session()
try:
token = get_token(session, GH_USER, GH_PASSWORD)
print("Authentication successful.\n")
except Exception as e:
print(f"ERROR: Failed to authenticate: {e}")
return
counts = {"added": 0, "exists": 0, "error": 0}
errors = []
with open(CSV_FILE, newline="") as f:
reader = csv.DictReader(f)
rows = list(reader)
print(f"Processing {len(rows)} databases from {CSV_FILE}...\n")
for i, row in enumerate(rows, 1):
name = row.get("name", f"row_{i}")
result = add_profile(session, token, row)
if result == "added":
counts["added"] += 1
print(f" [{i:>4}/{len(rows)}] ✓ Added : {name}")
elif result == "exists":
counts["exists"] += 1
print(f" [{i:>4}/{len(rows)}] ⚠ Skipped : {name} (already registered)")
else:
counts["error"] += 1
errors.append((name, result))
print(f" [{i:>4}/{len(rows)}] ✗ Failed : {name} — {result}")
# ── Summary ────────────────────────────────────────────────────────────────
print("\n" + "="*60)
print(" Onboarding Complete")
print("="*60)
print(f" Total processed : {len(rows)}")
print(f" Added : {counts['added']}")
print(f" Already existed : {counts['exists']}")
print(f" Errors : {counts['error']}")
if errors:
print("\n Failed profiles:")
for name, reason in errors:
print(f" • {name}: {reason}")
print("="*60)
if __name__ == "__main__":
main()
Running the script:
# Set credentials as environment variables — never in the script
export GH_URL="http://your-genius-hub-server:11100/dbapi/v4"
export GH_USER="admin"
export GH_PASSWORD="your_password"
python3 onboard_databases.py
What to customise before running:
-
CSV_FILE: Point to your actual CSV file path, or extend the script to accept it as a command-line argument.
-
DRIVER_TYPE: Set to "2" for Type-2 (local client) connections if required by your environment.
-
verify=False: Replace with verify="/path/to/ca-bundle.crt" once your Genius Hub server uses a trusted TLS certificate.
For very large onboarding batches (1000+ databases): Consider splitting your CSV into chunks and running in parallel with Python's concurrent.futures.ThreadPoolExecutor. The Genius Hub API supports concurrent requests, so this can reduce a 1000-database onboarding from minutes to seconds.
5. What Else Can You Automate?
Onboarding databases is just the beginning, the same API setup can give you programmatic access to everything Genius Hub monitors. The /alerts endpoint is a good illustration of this. It gets open alerts from every registered database in a single response, each tagged with its connection profile.
The endpoint:
GET /dbapi/v4/alerts
Required headers:
|
|
|
|
|
Authorization
|
Bearer <token>
|
Your authentication token
|
|
x-db-profile
|
*all*
|
Returns alerts across all registered databases
|
Sample Success response (HTTP 200):
{
"warningAlertCount": <warning_count>,
"criticalAlertCount": <critical_count>,
"count": <total_alerts>,
"infoAlertCount": <info_count>,
"resources": [
{
"severity": "<alert_severity>",
"notification_type": "alert",
"alertAnalysisDesc": "<alert_analysis_description>",
"read": false,
"start_timestamp": <alert_start_timestamp>,
"type": "<alert_type>",
"end_timestamp": <alert_end_timestamp>,
"name": "<connection_profile_name>",
"id": "<alert_id>",
"category": "<alert_category>",
"actions": [
{
"actionDescription": "<alert_action_description>",
"actionLabel": ""
}
],
"entity": "0",
"alertDetails": {},
"group": "<alert_group>"
}
]
}
The API returns a JSON array of alert objects. Each entry includes the name field, so alert can be associated with its origin database connection profile. The response has a breakdown of alert counts by severity at the top level, namely, criticalAlertCount, warningAlertCount, infoAlertCount. Each alert in resources also carries its category, group, and a detailed alertAnalysisDesc along with recommended actions, which means the data is actionable straight out of the API response with no need for an additional lookup.
Full Python Code
In a large environment with hundreds of databases, the total number of alerts can be substantial. So, rather than fetching all alerts and then filtering, Genius Hub gives you a dedicated /alerts/filter endpoint that does the heavy lifting at the server-side. You can pass severity, group, filter, and sort as query parameters and get back exactly what you need.
The example below pulls only open critical alerts across all databases, sorted with the most recent first.
import requests
from datetime import datetime
GENIUS_HUB_URL = "http://your-server:11100/dbapi/v4"
def get_critical_alerts(token: str) -> list:
"""Fetch open critical alerts across all databases using server-side filtering."""
headers = {
"Authorization": f"Bearer {token}",
"x-db-profile": "*all*"
}
params = {
"severity": "critical",
"filter": "isOpen",
"sort": "-severity,+started", # Most severe first, then oldest first
"limit": 1000
}
response = requests.get(
f"{GENIUS_HUB_URL}/alerts/filter",
headers=headers,
params=params,
verify=False
)
if response.status_code == 200:
alerts = response.json()
if isinstance(alerts, list):
return alerts
return alerts.get("resources", [])
else:
raise RuntimeError(
f"Failed to retrieve alerts: HTTP {response.status_code} — {response.text}"
)
def print_critical_alerts(alerts: list):
"""Print critical alerts grouped by database."""
if not alerts:
print("No critical alerts across any monitored database.")
return
print(f"\nCritical Alerts — {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("="*60)
print(f"{len(alerts)} critical alert(s) found\n")
by_profile = {}
for alert in alerts:
profile = alert.get("profile_name", "unknown")
by_profile.setdefault(profile, []).append(alert)
for profile, db_alerts in sorted(by_profile.items()):
print(f" {profile} ({len(db_alerts)} critical alert(s))")
for a in db_alerts:
name = a.get("alert_name", a.get("name", "—"))
message = a.get("message", "")[:80]
print(f" [CRITICAL] {name}: {message}")
print("="*60)
# Usage
alerts = get_critical_alerts(token)
print_critical_alerts(alerts)
Taking the Data Further
Genius Hub already gives you this consolidated view out of the box through its console, however if your operations team wants to integrate Db2 alerts into their existing observability tool, the API makes it just as easy.
Whether that's a Datadog event, a Splunk HEC endpoint, or a webhook into ServiceNow, a POST request to your platform’s ingestion API, piped with the alert data, is all it takes to bring Db2 alert visibility.
6. Final Thought
The Genius Hub REST API surface goes well beyond what we have covered here. The intention of this Blog is to introduce the basic workflow, consisting of authentication, setting the right headers and parsing the JSON response.
This main steps can be used as a base for further enhancements in the uses and as a starting point for all use cases you may have in mind.