Skip to main content

Overview

The TierZero API allows you to programmatically ask questions to the TierZero AI agent and receive structured responses. This enables you to integrate TierZero’s intelligent analysis capabilities into your applications, automation workflows, and custom tools. The API uses standard HTTP methods with JSON payloads and requires authentication via organization API keys. All API responses are formatted in JSON and include relevant interaction IDs for tracking and follow-up.

Authentication

All API requests require authentication using an organization API key. Include your API key in the request header:
X-TierZero-Org-Api-Key: your-api-key-here
API keys can be generated from your TierZero dashboard. Each key is associated with a specific organization and has access to that organization’s resources and context.

Resource Identifiers

The TierZero API uses Global IDs to identify resources like digests, alert agents, teams, and notification integrations. Global IDs are opaque string identifiers that you receive in API responses and use in subsequent requests. Example Global IDs:
{
  "digest_id": "R3JhcGhRTEpvYjoxMjM=",
  "alert_id": "R3JhcGhRTEFsZXJ0OjQ1Ng==",
  "notification_integration_id": "R3JhcGhRTE5vdGlmaWNhdGlvbkludGVncmF0aW9uOjEyMzQ="
}

Endpoints

Alert Agent Management

Create Alert Agent (POST /api/v1/alert-responders)

Create a new alert agent that automatically investigates incoming alerts.
Request
Method: POST Path: /api/v1/alert-responders Content-Type: application/json Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Content-Type: application/json
Request Body: For webhook-based alerts (PagerDuty, OpsGenie, FireHydrant, Rootly):
{
  "team_name": "string",              // Required: Team name
  "name": "string",                   // Required: Alert agent name
  "webhook_sources": [                // Required: Webhook sources to monitor (see "List Webhook Subscriptions" below)
    {
      "type": "string",               // Webhook type: PAGERDUTY, OPSGENIE, FIREHYDRANT, or ROOTLY
      "remote_id": "string"           // External webhook ID (use "List Webhook Subscriptions" to find valid remote_id values)
    }
  ],
  "matching_criteria": {              // Required: Criteria for matching alerts
    "text_matches": ["string"]        // Array of text patterns to match
  },
  "runbook": {                        // Optional: Investigation runbook (uses default if not provided)
    "investigation_prompt": "string", // Optional: Main investigation prompt
    "impact_and_severity_prompt": "string" // Optional: Quick triage prompt (typically for impact and severity analysis)
  },
  "notification_integration_ids": [   // Optional: Notification integration Global IDs (use "List Notification Integrations" below)
    "string"
  ]
}
For Slack alerts:
{
  "team_name": "string",              // Required: Team name
  "name": "string",                   // Required: Alert agent name
  "slack_channel_id": "string",       // Required: Slack channel ID (must start with 'C' for public channels or 'G' for private channels)
  "matching_criteria": {              // Required: Criteria for matching alerts
    "text_matches": ["string"],       // Required: Array of text patterns to match
    "slack_bot_app_user_id": "string" // Optional: Filter by specific bot/sender ID (e.g., "B01234567")
  },
  "runbook": {                        // Optional: Investigation runbook (uses default if not provided)
    "investigation_prompt": "string", // Optional: Main investigation prompt
    "impact_and_severity_prompt": "string" // Optional: Quick triage prompt (typically for impact and severity analysis)
  },
  "notification_integration_ids": [   // Optional: Notification integration Global IDs (use "List Notification Integrations" below)
    "string"
  ]
}
Note: If runbook or runbook.investigation_prompt is not provided, a default investigation prompt will be used: “Please investigate the issue and explain the root cause to the best of your abilities!” Idempotency: If an alert agent with the same name exists for the organization and team, returns the existing responder instead of creating a duplicate.
Response
Status Code: 200 OK
{
  "id": "string",      // Alert agent Global ID
  "url": "string",     // Link to alert agent details page
  "name": "string",    // Alert agent name
  "status": "ACTIVE"   // Status (ACTIVE or PAUSED)
}

Get Alert Agent (GET /api/v1/alert-responders/{alert_id})

Retrieve detailed information about a specific alert agent.
Request
Method: GET Path: /api/v1/alert-responders/{alert_id} Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • alert_id (required): Alert agent Global ID
Response
Status Code: 200 OK
{
  "id": "string",                     // Alert agent Global ID
  "organization_name": "string",      // Organization name
  "team_name": "string",              // Team name
  "name": "string",                   // Alert agent name
  "runbook": {                        // Investigation runbook (null if not active)
    "investigation_prompt": "string", // Main investigation prompt
    "impact_and_severity_prompt": "string" // Quick triage prompt
  },
  "matching_criteria": {              // Alert matching criteria
    "text_matches": ["string"],       // Text patterns to match
    "slack_bot_app_user_id": "string" // Optional: Bot/sender ID filter (Slack alerts only)
  },
  "webhook_sources": [                // Configured webhook sources (empty array for Slack alerts)
    {
      "type": "string",               // Webhook type: PAGERDUTY, OPSGENIE, FIREHYDRANT, or ROOTLY
      "remote_id": "string"           // External webhook ID
    }
  ],
  "slack_channel_id": "string",       // Slack channel ID (null for webhook-based alerts)
  "notification_integration_ids": [   // Notification integration Global IDs (only present when configured)
    "string"
  ],
  "status": "ACTIVE",                 // Status (ACTIVE or PAUSED)
  "created_at": "string",             // ISO 8601 timestamp
  "updated_at": "string"              // ISO 8601 timestamp
}

List Alert Agents (GET /api/v1/alert-responders)

List all alert agents for your organization, optionally filtered by team.
Request
Method: GET Path: /api/v1/alert-responders Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Query Parameters:
  • team_name (optional): Filter by team name
Response
Status Code: 200 OK
{
  "alert_responders": [
    {
      "id": "string",       // Alert agent Global ID
      "name": "string",     // Alert agent name
      "team_name": "string",// Team name
      "status": "ACTIVE",   // Status (ACTIVE or PAUSED)
      "url": "string"       // Link to alert agent details page
    }
  ]
}

Update Alert Agent (PUT /api/v1/alert-responders/{alert_id})

Update an existing alert agent’s configuration.
Request
Method: PUT Path: /api/v1/alert-responders/{alert_id} Content-Type: application/json Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Content-Type: application/json
Path Parameters:
  • alert_id (required): Alert agent Global ID
Request Body: For webhook-based alerts:
{
  "name": "string",                   // Optional: New name
  "runbook": {                        // Optional: New runbook
    "investigation_prompt": "string", // Main investigation prompt
    "impact_and_severity_prompt": "string" // Quick triage prompt
  },
  "matching_criteria": {              // Optional: New matching criteria
    "text_matches": ["string"]
  },
  "webhook_sources": [                // Optional: New webhook sources (see "List Webhook Subscriptions" below)
    {
      "type": "string",
      "remote_id": "string"           // External webhook ID (use "List Webhook Subscriptions" to find valid remote_id values)
    }
  ],
  "notification_integration_ids": [   // Optional: New notification integration Global IDs (use "List Notification Integrations" below)
    "string"
  ]
}
For Slack alerts:
{
  "name": "string",                   // Optional: New name
  "runbook": {                        // Optional: New runbook
    "investigation_prompt": "string", // Main investigation prompt
    "impact_and_severity_prompt": "string" // Quick triage prompt
  },
  "matching_criteria": {              // Optional: New matching criteria
    "text_matches": ["string"],       // Array of text patterns to match
    "slack_bot_app_user_id": "string" // Optional: Bot/sender ID filter
  },
  "slack_channel_id": "string",       // Optional: New Slack channel ID (must start with 'C' or 'G')
  "notification_integration_ids": [   // Optional: New notification integration Global IDs (use "List Notification Integrations" below)
    "string"
  ]
}
All fields are optional. Only provided fields will be updated. Note: Cannot mix alert types - don’t specify webhook_sources for Slack alerts or slack_channel_id for webhook-based alerts.
Response
Status Code: 200 OK
{
  "id": "string",      // Alert agent Global ID
  "url": "string",     // Link to alert agent details page
  "name": "string",    // Alert agent name
  "status": "ACTIVE"   // Status (ACTIVE or PAUSED)
}

Delete Alert Agent (DELETE /api/v1/alert-responders/{alert_id})

Delete an alert agent.
Request
Method: DELETE Path: /api/v1/alert-responders/{alert_id} Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • alert_id (required): Alert agent Global ID
Response
Status Code: 200 OK
{
  "success": true
}
Idempotency: Returns success even if the alert agent is already deleted.

Enable Alert Agent (POST /api/v1/alert-responders/{alert_id}/enable)

Enable a paused alert agent to start processing alerts.
Request
Method: POST Path: /api/v1/alert-responders/{alert_id}/enable Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • alert_id (required): Alert agent Global ID
Response
Status Code: 200 OK
{
  "id": "string",      // Alert agent Global ID
  "status": "ACTIVE"   // Updated status
}

Disable Alert Agent (POST /api/v1/alert-responders/{alert_id}/disable)

Disable an alert agent to temporarily stop processing alerts.
Request
Method: POST Path: /api/v1/alert-responders/{alert_id}/disable Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • alert_id (required): Alert agent Global ID
Response
Status Code: 200 OK
{
  "id": "string",      // Alert agent Global ID
  "status": "PAUSED"   // Updated status
}

List Webhook Subscriptions (GET /api/v1/webhook-subscriptions)

Discover available webhook subscriptions for your organization. Use this endpoint to find valid webhook_sources when creating or updating alert agents.
Request
Method: GET Path: /api/v1/webhook-subscriptions Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Response
Status Code: 200 OK
{
  "webhook_subscriptions": [
    {
      "type": "string",      // Webhook type: PAGERDUTY, OPSGENIE, FIREHYDRANT, ROOTLY, or SLACK
      "remote_id": "string", // External webhook ID
      "name": "string"       // Human-readable name
    }
  ]
}

List Notification Integrations (GET /api/v1/notification-integrations)

Discover available notification integrations for your organization. Use this endpoint to find valid notification_integration_ids when creating or updating alert agents.
Request
Method: GET Path: /api/v1/notification-integrations Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Query Parameters:
  • kind (optional): Filter by integration kind. Allowed values:
    • DISCORD_WEBHOOK: Discord webhook integrations
    • SLACK_ALERT: Slack alert integrations (Auto-Detect)
Response
Status Code: 200 OK
{
  "notification_integrations": [
    {
      "id": "string",        // Notification integration Global ID
      "name": "string",      // Human-readable name
      "kind": "string",      // Integration kind (DISCORD_WEBHOOK or SLACK_ALERT)
      "created_at": "string" // ISO 8601 timestamp
    }
  ]
}

Investigation Management

Get Investigation (GET /api/v1/investigations/{investigation_id})

Retrieve details about a completed investigation (alert agent job run).
Request
Method: GET Path: /api/v1/investigations/{investigation_id} Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • investigation_id (required): Investigation Global ID (GraphQL JobRun ID)
Response
Status Code: 200 OK
{
  "organization_name": "string",      // Organization name
  "team_name": "string",              // Team name (null if not assigned)
  "id": "string",                     // Investigation Global ID
  "name": "string",                   // Investigation name
  "status": "string",                 // Status: PENDING, IN_PROGRESS, ERRORED, COMPLETED, or STOPPED
  "started_at": "string",             // ISO 8601 timestamp (null if not started)
  "completed_at": "string",           // ISO 8601 timestamp (null if not completed)
  "prompt": "string",                 // Investigation prompt
  "event_payload": "string",          // Original event/alert payload
  "result": "string"                  // Formatted investigation result with numbered source citations and sources appended
}
Note: The result field contains the investigation analysis with:
  • Source markup (††toolu_...††) replaced with numbered citations ([1], [2], etc.)
  • Timestamp markers (§) removed
  • A “Sources:” section appended at the end with clickable links to data sources
Example Response:
{
  "organization_name": "Acme Corp",
  "team_name": "Production",
  "id": "R3JhcGhRTEpvYlJ1bjoxMjM=",
  "name": "Critical API Error Investigation",
  "status": "COMPLETED",
  "started_at": "2025-01-15T10:30:00+00:00",
  "completed_at": "2025-01-15T10:35:00+00:00",
  "prompt": "Investigate this critical error and provide root cause analysis",
  "event_payload": "{\"alert_id\": \"PD123\", \"service\": \"api-gateway\", \"severity\": \"critical\"}",
  "result": "The investigation shows a spike in 500 errors [1] caused by database connection timeouts [2].\n\nSources:\n- [1]: [service:api-gateway status:500](https://datadog.com/logs/...)\n- [2]: [query:database timeout](https://datadog.com/logs/...)"
}

Digest Agent Management

Create Digest Agent (POST /api/v1/digests)

Create a new scheduled digest agent job that periodically generates reports based on configured sections.
Request
Method: POST Path: /api/v1/digests Content-Type: application/json Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Content-Type: application/json
Request Body:
{
  "team_name": "string",        // Required: Name of the team
  "name": "string",             // Required: Name for the digest agent
  "sections": [                 // Required: Array of digest agent sections
    {
      "section": "string",      // Section name
      "prompt": "string"        // Prompt/query for this section
    }
  ],
  "schedule": "string",         // Required: Cron expression (e.g., "0 9 * * 1-5")
  "slack_channel_id": "string"  // Optional: Slack channel ID for notifications
}
Response
Status Code: 200 OK
{
  "id": "string",    // Digest Agent ID
  "url": "string"    // Link to digest agent details page
}

Get Digest Agent (GET /api/v1/digests/{digest_id})

Retrieve details about a specific digest agent job.
Request
Method: GET Path: /api/v1/digests/{digest_id} Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • digest_id (required): Digest Agent ID returned from create/update operations
Response
Status Code: 200 OK
{
  "organization_name": "string",  // Organization name
  "team_name": "string",          // Team name
  "id": "string",                 // Digest Agent ID
  "name": "string",               // Digest Agent name
  "sections": [                   // Digest Agent sections
    {
      "section": "string",        // Section name
      "prompt": "string"          // Prompt/query for this section
    }
  ],
  "schedule": "string",           // Cron expression
  "slack_channel_id": "string"    // Optional: Slack channel ID if configured
}

Update Digest Agent (PUT /api/v1/digests/{digest_id})

Update an existing digest agent job’s configuration.
Request
Method: PUT Path: /api/v1/digests/{digest_id} Content-Type: application/json Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Content-Type: application/json
Path Parameters:
  • digest_id (required): Digest Agent ID
Request Body:
{
  "name": "string",             // Optional: New name for the digest agent
  "sections": [                 // Optional: Updated sections array
    {
      "section": "string",
      "prompt": "string"
    }
  ],
  "schedule": "string",         // Optional: Updated cron expression
  "slack_channel_id": "string"  // Optional: Updated Slack channel ID
}
All fields are optional. Only provided fields will be updated.
Response
Status Code: 200 OK
{
  "id": "string",    // Digest Agent ID
  "url": "string"    // Link to digest agent details page
}

Delete Digest Agent (DELETE /api/v1/digests/{digest_id})

Delete a digest agent job.
Request
Method: DELETE Path: /api/v1/digests/{digest_id} Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
Path Parameters:
  • digest_id (required): Digest Agent ID
Response
Status Code: 200 OK
{
  "success": true
}

Run Digest Agent (POST /api/v1/digests/{digest_id}/run)

Manually trigger a digest agent job to run immediately or schedule it for later.
Request
Method: POST Path: /api/v1/digests/{digest_id}/run Content-Type: application/json Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Content-Type: application/json
Path Parameters:
  • digest_id (required): Digest Agent ID
Request Body:
{
  "run_sync": false,           // Optional: Wait for completion (default: false)
  "scheduled_runtime": 1735689600  // Optional: Unix timestamp in seconds to schedule the run
}
Field Descriptions:
  • run_sync (optional): If true, runs synchronously and returns results in the response. Default is false.
  • scheduled_runtime (optional): Unix timestamp in seconds. If provided, schedules the digest agent to run at this time instead of running immediately. Must be in the future.
Note: Notifications are always sent to the configured Slack channels and Discord webhooks for the digest agent.
Response (Immediate Run - Async Mode)
Status Code: 200 OK
{
  "id": "string",    // Digest Agent ID
  "url": "string"    // Link to digest agent details page
}
Response (Immediate Run - Sync Mode with run_sync: true)
Status Code: 200 OK
{
  "id": "string",       // Digest Agent ID
  "url": "string",      // Link to digest agent details page
  "results": [          // Array of section results
    {
      "section": "string",   // Section name
      "prompt": "string",    // Section prompt
      "result": "string"     // Generated content
    }
  ]
}
Response (Scheduled Run)
Status Code: 200 OK
{
  "id": "string",              // Digest Agent ID
  "url": "string",             // Link to digest agent details page
  "scheduled_runtime": 1735689600  // Unix timestamp when the digest agent is scheduled to run
}

Cron Expression Reference

Digest Agent schedules use cron expressions with five fields:
* * * * *
│ │ │ │ └─ Day of week (0=Mon, 6=Sun)
│ │ │ └─── Month (1-12)
│ │ └───── Day of month (1-31)
│ └─────── Hour (0-23)
└───────── Minute (0-59)
Note: Day of week starts at 0 for Monday, which differs from standard cron. Common patterns:
  • Weekdays at 9 AM: 0 9 * * 0-4
  • Daily at 9 AM: 0 9 * * *
  • Every Monday at 10 AM: 0 10 * * 0
  • Every 6 hours: 0 */6 * * *
Special characters: * (any), , (list), - (range), / (step)

Interaction Management

Get Interaction Results (GET /api/v1/interactions/{interaction_id})

Retrieve the results of a previous TierZero interaction using its interaction ID. This endpoint allows you to fetch results later, which is useful for polling scheduled actions or accessing historical interactions. For scheduled actions, this endpoint returns the current status and results when complete.
Request
Method: GET Path: /api/v1/interactions/{interaction_id} Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Accept: application/json
Path Parameters:
  • interaction_id (required): The interaction ID returned from a previous POST /api/v1/interactions call
Response
Status Response (for async interactions in progress)
Status Code: 200 OK
{
  "interaction_id": "string",   // The interaction ID for this interaction
  "status": "PENDING|IN_PROGRESS|FAILED",  // Current processing status
  "url": "string"               // Link to interaction details page in TierZero UI
}
Complete Response (for completed interactions)
Status Code: 200 OK
{
  "question": "string",        // The original question that was asked
  "content": "string",         // TierZero's response in formatted markdown
  "sources": [                 // Array of source information that supported the response
    {
      "log_type_name": "string",    // Name of the log type or data source
      "query": "string",            // JSON string containing the query parameters
      "start": "string",            // ISO 8601 timestamp for query start time
      "end": "string",              // ISO 8601 timestamp for query end time
      "link": "string",             // Direct URL to view the data in the source system
      "artifact_id": "string|null", // Associated artifact identifier, if any
      "tool_id": "string",          // Internal tool identifier used for the query
      "type": "string",             // Type of source (e.g., "DatadogLogQuery")
      "source_id": "number",        // Numeric identifier for the source
      "display_text": "string"     // Human-readable description of the query
    }
  ],
  "interaction_id": "string",   // The interaction ID for this interaction
  "status": "COMPLETED",        // Processing status
  "url": "string"               // Link to interaction details page in TierZero UI
}
Status Values:
  • PENDING: Request received and queued for processing
  • IN_PROGRESS: Currently being processed by TierZero
  • COMPLETED: Processing complete, results available
  • FAILED: Processing failed due to an error
Error Responses
401 Unauthorized:
{
  "detail": "Unauthorized"
}
404 Not Found:
{
  "detail": "Interaction not found"
}
500 Internal Server Error:
{
  "detail": "Error message describing the issue"
}

Create Interaction (POST /api/v1/interactions)

Submit a question to the TierZero AI agent and receive an intelligent response based on your organization’s knowledge catalog and observability data.
Request
Method: POST Path: /api/v1/interactions Content-Type: application/json Headers:
  • X-TierZero-Org-Api-Key (required): Your organization API key
  • Content-Type: application/json
  • Accept: application/json
Request Body:
{
  "question": "string",                // Required: The question to ask TierZero (or prompt for scheduled actions)
  "context": [                         // Optional: Previous conversation context
    {
      "interaction_id": "string",      // ID from previous API call
      "content": "string"              // Additional context content
    }
  ],
  "user_id": "string",                 // Optional: User identifier for tracking
  "use_tools": boolean,                // Optional: Enable tool usage (default: true)
  "scheduled_runtimes": [1735689600, 1735776000],  // Optional: List of Unix timestamps for scheduled execution (each must be in the future, max 24 hours)
  "notifications": {                   // Optional: Notification configuration
    "slack": {                         // Optional: Slack notifications
      "slack_channel_ids": ["C01234567"]
    },
    "discord": {                       // Optional: Discord notifications
      "discord_webhook_urls": ["https://discord.com/api/webhooks/123456789/abc..."]
    },
    "web": {                           // Optional: Webhook callback
      "callback_url": "string",
      "custom_headers": {              // Optional: Custom HTTP headers for callback
        "Authorization": "Bearer token",
        "X-Custom-Header": "value"
      }
    }
  }
}
Field Descriptions:
  • question (required): The question or prompt you want TierZero to analyze. For scheduled actions, this becomes the prompt that runs at the scheduled time.
  • context (optional): Array of previous interactions to provide conversation context
  • user_id (optional): Identifier for the user making the request, useful for tracking and analytics
  • use_tools (optional): If false, TierZero will respond without using any tools (no data queries, no integrations). Default is true. Set to false for faster responses when you only need analysis based on existing knowledge
  • scheduled_runtimes (optional): List of Unix timestamps (in seconds) for when to execute. Each timestamp must be in the future (max 24 hours). Maximum of 10 timestamps allowed per request. Returns interaction_id and status SCHEDULED for polling via GET endpoint.
    • Legacy Parameter: scheduled_runtime (singular, integer) is still supported for backwards compatibility but deprecated. When using the legacy parameter, the API returns the old response format with top-level interaction_id, scheduled_runtime, url, and status fields instead of the interactions array. New integrations should use scheduled_runtimes (plural, array).
  • notifications (optional): Nested object containing notification configurations:
    • slack (optional): Slack notification settings
      • slack_channel_ids: Array of Slack channel IDs (e.g., ["C01234567"]). Each ID should start with ‘C’ (public) or ‘G’ (private)
    • discord (optional): Discord notification settings
      • discord_webhook_urls: Array of Discord webhook URLs
    • web (optional): Webhook callback settings for async responses
      • callback_url: URL where results will be sent
      • custom_headers (optional): Dictionary of custom HTTP headers for callbacks (e.g., {"Authorization": "Bearer token"}). If not provided, defaults to {"X-TierZero-Org-Api-Key": "your-api-key"}
Execution Modes:
  • Synchronous (default): Returns result immediately in the response. No scheduled_runtimes or notifications.web.callback_url provided. Status: COMPLETED.
  • Asynchronous with callback: Provide notifications.web.callback_url without scheduled_runtimes. Returns interaction_id immediately, executes in background, sends results to callback URL when done. Status: SCHEDULED.
  • Scheduled: Provide scheduled_runtimes (list of future timestamps). Returns interaction_id immediately, executes at specified times. Poll via GET endpoint or use notification channels. Status: SCHEDULED.
Note for Scheduled Actions:
  • A unique name is automatically generated for each scheduled action
  • Scheduled actions are limited to at most 24 hours in the future
  • Maximum of 10 scheduled runtimes allowed per request
  • Notification targets (via notifications object) are optional - you can query results using GET /api/v1/interactions/{interaction_id}
Response
Synchronous Response (no callback_url, no scheduled_runtime)
Status Code: 200 OK
{
  "question": "string",        // The original question that was asked
  "content": "string",         // TierZero's response in formatted markdown
  "sources": [                 // Array of source information that supported the response
    {
      "log_type_name": "string",    // Name of the log type or data source
      "query": "string",            // JSON string containing the query parameters
      "start": "string",            // ISO 8601 timestamp for query start time
      "end": "string",              // ISO 8601 timestamp for query end time
      "link": "string",             // Direct URL to view the data in the source system
      "artifact_id": "string|null", // Associated artifact identifier, if any
      "tool_id": "string",          // Internal tool identifier used for the query
      "type": "string",             // Type of source (e.g., "DatadogLogQuery")
      "source_id": "number",        // Numeric identifier for the source
      "display_text": "string"     // Human-readable description of the query
    }
  ],
  "interaction_id": "string",  // Unique identifier for this interaction
  "url": "string"              // Link to interaction details page in TierZero UI
}
Asynchronous Response (with callback_url, no scheduled_runtimes)
Status Code: 200 OK
{
  "interactions": [
    {
      "interaction_id": "abc-123",
      "scheduled_runtime": 1735689600,
      "url": "https://app.tierzero.ai/interactions/abc-123"
    }
  ],
  "status": "SCHEDULED"  // Job scheduled for background execution
}
Note: When using only callback_url without scheduled_runtimes, the job executes immediately in the background and results are sent to the callback URL. Status is SCHEDULED.
Scheduled Action Response (with scheduled_runtimes)
Status Code: 200 OK
{
  "interactions": [
    {
      "interaction_id": "abc-123",
      "scheduled_runtime": 1735689600,
      "url": "https://app.tierzero.ai/interactions/abc-123"
    },
    {
      "interaction_id": "def-456",
      "scheduled_runtime": 1735776000,
      "url": "https://app.tierzero.ai/interactions/def-456"
    }
  ],
  "status": "SCHEDULED"  // Jobs scheduled for future execution
}
Note: When using scheduled_runtimes, jobs execute at the specified future times. The callback URL (if provided) will receive results when each scheduled job completes.
Legacy Response Format (DEPRECATED - using scheduled_runtime singular parameter)
Status Code: 200 OK
{
  "interaction_id": "abc-123",
  "scheduled_runtime": 1735689600,
  "url": "https://app.tierzero.ai/interactions/abc-123",
  "status": "SCHEDULED"
}
Note: This format is maintained for backwards compatibility when using the deprecated scheduled_runtime (singular) parameter. New integrations should use scheduled_runtimes (plural, array) which returns the interactions array format shown above. Important Behavioral Notes:
  1. One Interaction Per Scheduled Runtime: When using scheduled_runtimes, each timestamp creates a separate interaction with its own unique interaction_id. This is a 1:1 mapping - one timestamp = one job = one interaction.
  2. Tracking Individual Executions:
    • Poll each interaction independently: GET /api/v1/interactions/{interaction_id}
    • Each interaction has its own lifecycle and status
    • Store ALL returned interaction_ids if you need to track completion
  3. Callback Behavior (when using callback_url):
    • You will receive multiple callbacks - one per scheduled runtime
    • Each callback includes the specific interaction_id for that execution
    • Callback payload structure:
      {
        "interaction_id": "abc-123",
        "question": "your question",
        "content": "response content",
        "sources": []
      }
      
  4. Client Implementation Requirements:
    • MUST store all interaction_ids from the interactions array
    • MUST handle multiple callbacks when using callback_url (one per scheduled runtime)
    • Each callback’s interaction_id corresponds to one of the returned interactions
Context Handling
The context field allows you to provide conversation history for more contextual responses:
  1. Interaction ID Context: If a context item includes an interaction_id from a previous API call, TierZero will retrieve the full conversation history for that interaction
  2. Content-Only Context: If only content is provided, it will be treated as a user message in the conversation context
  3. Mixed Context: You can combine both types of context items in a single request
Error Responses
400 Bad Request:
{
  "detail": "Invalid payload" | "Invalid question" | "Context must be a list" | "Invalid callback_url: {url}"
}
401 Unauthorized:
{
  "detail": "Unauthorized"
}
500 Internal Server Error:
{
  "detail": "Error message describing the issue"
}

Usage Examples

Alert Agent Management Examples

Create an Alert Agent

# First, discover available webhook sources
curl -X GET "https://api.tierzero.ai/api/v1/webhook-subscriptions" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

# Discover available notification integrations
curl -X GET "https://api.tierzero.ai/api/v1/notification-integrations" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

# Create webhook-based alert agent (PagerDuty example)
curl -X POST "https://api.tierzero.ai/api/v1/alert-responders" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "team_name": "Production",
    "name": "Critical Error Alert",
    "matching_criteria": {
      "text_matches": ["critical", "error", "fatal"]
    },
    "webhook_sources": [
      {
        "type": "PAGERDUTY",
        "remote_id": "PXXXXXX"
      }
    ],
    "runbook": {
      "investigation_prompt": "Analyze this alert and provide detailed root cause analysis with remediation steps",
      "impact_and_severity_prompt": "Quick triage: assess severity and impact"
    },
    "notification_integration_ids": ["R3JhcGhRTE5vdGlmaWNhdGlvbkludGVncmF0aW9uOjEyMw=="]
  }'

# Create Slack alert agent
curl -X POST "https://api.tierzero.ai/api/v1/alert-responders" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "team_name": "Production",
    "name": "Database Alerts",
    "slack_channel_id": "C01234567",
    "matching_criteria": {
      "text_matches": ["database", "connection", "timeout"],
      "slack_bot_app_user_id": "B01234567"
    },
    "runbook": {
      "investigation_prompt": "Investigate database issues and provide remediation steps"
    },
    "notification_integration_ids": ["R3JhcGhRTE5vdGlmaWNhdGlvbkludGVncmF0aW9uOjEyMw=="]
  }'

List Alert Agents

# List all alert agents
curl -X GET "https://api.tierzero.ai/api/v1/alert-responders" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

# List alert agents for a specific team
curl -X GET "https://api.tierzero.ai/api/v1/alert-responders?team_name=Production" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

Get Alert Agent Details

curl -X GET "https://api.tierzero.ai/api/v1/alert-responders/{alert_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

Update Alert Agent

curl -X PUT "https://api.tierzero.ai/api/v1/alert-responders/{alert_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Alert Name",
    "matching_criteria": {
      "text_matches": ["critical", "emergency"]
    }
  }'

Enable/Disable Alert Agent

# Enable alert agent
curl -X POST "https://api.tierzero.ai/api/v1/alert-responders/{alert_id}/enable" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

# Disable alert agent
curl -X POST "https://api.tierzero.ai/api/v1/alert-responders/{alert_id}/disable" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

Delete Alert Agent

curl -X DELETE "https://api.tierzero.ai/api/v1/alert-responders/{alert_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

Investigation Management Examples

Get Investigation Details

# Get investigation by Global ID
curl -X GET "https://api.tierzero.ai/api/v1/investigations/{investigation_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key"
Example Response:
{
  "organization_name": "Acme Corp",
  "team_name": "Production",
  "id": "R3JhcGhRTEpvYlJ1bjoxMjM=",
  "name": "Critical API Error Investigation",
  "status": "COMPLETED",
  "started_at": "2025-01-15T10:30:00+00:00",
  "completed_at": "2025-01-15T10:35:00+00:00",
  "prompt": "Investigate this critical error and provide root cause analysis",
  "event_payload": "{\"alert_id\": \"PD123\", \"service\": \"api-gateway\", \"severity\": \"critical\"}",
  "result": "The investigation identified a spike in 500 errors [1] caused by database connection pool exhaustion [2].\n\nRoot Cause:\nThe database connection pool reached its maximum capacity of 50 connections due to a sudden traffic spike.\n\nSources:\n- [1]: [service:api-gateway status:500](https://app.datadoghq.com/logs?query=service:api-gateway+status:500)\n- [2]: [query:connection pool timeout](https://app.datadoghq.com/logs?query=database+connection+pool)"
}

Digest Agent Management Examples

Create a Daily Digest Agent

curl -X POST "https://api.tierzero.ai/api/v1/digests" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "team_name": "Engineering",
    "name": "Daily Production Health",
    "sections": [
      {
        "section": "Error Summary",
        "prompt": "Summarize production errors from the last 24 hours"
      },
      {
        "section": "Performance Metrics",
        "prompt": "Report on API response times and throughput"
      }
    ],
    "schedule": "0 9 * * 1-5",
    "slack_channel_id": "C01234567"
  }'

Get Digest Agent Details

curl -X GET "https://api.tierzero.ai/api/v1/digests/{digest_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

Update a Digest Agent

curl -X PUT "https://api.tierzero.ai/api/v1/digests/{digest_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Daily Report",
    "schedule": "0 10 * * 1-5"
  }'

Run a Digest Agent Immediately

# Run asynchronously (default)
curl -X POST "https://api.tierzero.ai/api/v1/digests/{digest_id}/run" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json"

# Run synchronously and get results immediately
curl -X POST "https://api.tierzero.ai/api/v1/digests/{digest_id}/run" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "run_sync": true
  }'

Schedule a Digest Agent for Later

# Schedule digest agent to run at a specific time (Unix timestamp)
curl -X POST "https://api.tierzero.ai/api/v1/digests/{digest_id}/run" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "scheduled_runtime": 1735689600
  }'

Delete a Digest Agent

curl -X DELETE "https://api.tierzero.ai/api/v1/digests/{digest_id}" \
  -H "X-TierZero-Org-Api-Key: your-api-key"

Scheduled Action Examples

Scheduled actions use the same /api/v1/interactions endpoint with additional parameters.

Create Scheduled Action with Slack Notification

Schedule a TierZero agent to run at specific times and post results to a Slack channel:
curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Analyze system performance metrics from the last 7 days and identify any anomalies",
    "scheduled_runtimes": [1735689600, 1735776000],
    "notifications": {
      "slack": {
        "slack_channel_ids": ["C01234567"]
      }
    }
  }'

Create Scheduled Action with Discord Notification

Schedule an action to send results to a Discord webhook:
curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Review security alerts from the last 24 hours and summarize any critical findings",
    "scheduled_runtimes": [1735776000],
    "notifications": {
      "discord": {
        "discord_webhook_urls": ["https://discord.com/api/webhooks/123456789/abc..."]
      }
    }
  }'

Create Scheduled Action with Multiple Notifications

Send results to both Slack and Discord:
curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Generate a comprehensive report on infrastructure utilization and cost optimization opportunities",
    "scheduled_runtimes": [1736208000],
    "notifications": {
      "slack": {
        "slack_channel_ids": ["C01234567", "C02345678"]
      },
      "discord": {
        "discord_webhook_urls": ["https://discord.com/api/webhooks/123456789/abc...", "https://discord.com/api/webhooks/987654321/def..."]
      }
    }
  }'

Interaction Examples

Basic Question

curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What errors occurred in our application in the last hour?"
  }'

Question with Context

curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Are these errors related to the deployment we discussed?",
    "context": [
      {
        "interaction_id": "123e4567-e89b-12d3-a456-426614174000"
      }
    ],
    "user_id": "user123"
  }'

Asynchronous Request with Callback

curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Analyze the performance impact of our latest deployment",
    "notifications": {
      "web": {
        "callback_url": "https://your-app.com/webhooks/tierzero"
      }
    }
  }'

Scheduled Request with Polling

# Schedule request for future execution
curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Analyze the performance impact of our latest deployment",
    "scheduled_runtimes": [1735689600],
    "notifications": {
      "slack": {
        "slack_channel_ids": ["C01234567"]
      }
    }
  }'

# Response: {"interactions": [{"interaction_id": "123e4567-e89b-12d3-a456-426614174000", "scheduled_runtime": 1735689600, "url": "https://app.tierzero.ai/interactions/123e4567-e89b-12d3-a456-426614174000"}], "status": "SCHEDULED"}

# Poll for results using the interaction_id from the response
curl -X GET "https://api.tierzero.ai/api/v1/interactions/123e4567-e89b-12d3-a456-426614174000" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Accept: application/json"

Request Without Tools (Knowledge-Only Response)

# Request a response based only on existing knowledge, without querying data sources
curl -X POST "https://api.tierzero.ai/api/v1/interactions" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What is our standard deployment process?",
    "use_tools": false
  }'

Retrieve Interaction Results

curl -X GET "https://api.tierzero.ai/api/v1/interactions/123e4567-e89b-12d3-a456-426614174000" \
  -H "X-TierZero-Org-Api-Key: your-api-key" \
  -H "Accept: application/json"

Response Format

TierZero responses are formatted as markdown and may include:
  • Analysis summaries with key findings
  • Relevant log excerpts and error messages
  • Metric trends and performance data
  • Recommendations for investigation or resolution
  • Links to relevant dashboards and tools
The interaction_id can be used in subsequent API calls to maintain conversation context and build upon previous analyses.

Rate Limits

API requests are subject to rate limiting based on your organization’s plan. Rate limit information is included in response headers:
  • X-RateLimit-Limit: Maximum requests per time window
  • X-RateLimit-Remaining: Remaining requests in current window
  • X-RateLimit-Reset: Time when the rate limit resets

Best Practices

  1. Provide Context: Use the context field to maintain conversation history for better responses
  2. Descriptive Questions: Ask specific, detailed questions for more accurate analysis
  3. Choose the Right Mode:
    • Use synchronous mode for immediate responses (no callback_url or scheduled_runtime)
    • Use scheduled mode with polling (scheduled_runtime) for time-based execution when you need full control over result retrieval
    • Use async mode with callbacks (callback_url) for fire-and-forget scenarios with webhook handling
  4. Optimize Tool Usage:
    • Set use_tools: true (default) when you need TierZero to query data sources, run integrations, or perform real-time analysis
    • Set use_tools: false for faster responses when you only need answers based on existing knowledge (e.g., documentation, runbooks, best practices)
  5. Track Interactions: Store interaction IDs to enable follow-up questions and conversation threading
  6. Handle Errors: Implement proper error handling for all HTTP status codes
  7. Respect Rate Limits: Monitor rate limit headers and implement backoff strategies
  8. Poll Efficiently: For scheduled mode, use reasonable polling intervals (2-5 seconds) and implement timeouts
  9. User Tracking: Use the user_id field for analytics, rate limiting, and audit trails

Integration Examples

Python

import requests
import json
import time

# Alert Agent Management Functions

def create_alert_responder(team_name, name, matching_criteria, api_key,
                          webhook_sources=None, slack_channel_id=None,
                          runbook=None, notification_integration_ids=None):
    """
    Create a new alert agent.

    Args:
        team_name: Team name
        name: Alert agent name
        matching_criteria: Matching criteria dict (text_matches, slack_bot_app_user_id)
        api_key: Organization API key
        webhook_sources: Optional list of webhook sources (for webhook-based alerts)
        slack_channel_id: Optional Slack channel ID (for Slack alerts)
        runbook: Optional runbook configuration
        notification_integration_ids: Optional notification integration IDs

    Note: Must specify either webhook_sources OR slack_channel_id (not both)
    """
    url = "https://api.tierzero.ai/api/v1/alert-responders"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {
        "team_name": team_name,
        "name": name,
        "matching_criteria": matching_criteria
    }
    if webhook_sources:
        payload["webhook_sources"] = webhook_sources
    if slack_channel_id:
        payload["slack_channel_id"] = slack_channel_id
    if runbook:
        payload["runbook"] = runbook
    if notification_integration_ids:
        payload["notification_integration_ids"] = notification_integration_ids

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def get_alert_responder(alert_id, api_key):
    """Get alert agent details"""
    url = f"https://api.tierzero.ai/api/v1/alert-responders/{alert_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.get(url, headers=headers)
    response.raise_for_status()

    return response.json()

def list_alert_responders(api_key, team_name=None):
    """List all alert agents, optionally filtered by team"""
    url = "https://api.tierzero.ai/api/v1/alert-responders"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }
    params = {}
    if team_name:
        params["team_name"] = team_name

    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()

    return response.json()

def update_alert_responder(alert_id, api_key, name=None, matching_criteria=None,
                          webhook_sources=None, slack_channel_id=None,
                          runbook=None, notification_integration_ids=None):
    """
    Update an existing alert agent.

    Args:
        alert_id: Alert agent Global ID
        api_key: Organization API key
        name: Optional new name
        matching_criteria: Optional new matching criteria
        webhook_sources: Optional new webhook sources (for webhook-based alerts only)
        slack_channel_id: Optional new Slack channel ID (for Slack alerts only)
        runbook: Optional new runbook
        notification_integration_ids: Optional new notification integration IDs

    Note: Cannot mix alert types - don't specify webhook_sources for Slack alerts
          or slack_channel_id for webhook-based alerts
    """
    url = f"https://api.tierzero.ai/api/v1/alert-responders/{alert_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {}
    if name:
        payload["name"] = name
    if matching_criteria:
        payload["matching_criteria"] = matching_criteria
    if webhook_sources:
        payload["webhook_sources"] = webhook_sources
    if slack_channel_id:
        payload["slack_channel_id"] = slack_channel_id
    if runbook:
        payload["runbook"] = runbook
    if notification_integration_ids:
        payload["notification_integration_ids"] = notification_integration_ids

    response = requests.put(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def enable_alert_responder(alert_id, api_key):
    """Enable an alert agent"""
    url = f"https://api.tierzero.ai/api/v1/alert-responders/{alert_id}/enable"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.post(url, headers=headers)
    response.raise_for_status()

    return response.json()

def disable_alert_responder(alert_id, api_key):
    """Disable an alert agent"""
    url = f"https://api.tierzero.ai/api/v1/alert-responders/{alert_id}/disable"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.post(url, headers=headers)
    response.raise_for_status()

    return response.json()

def delete_alert_responder(alert_id, api_key):
    """Delete an alert agent"""
    url = f"https://api.tierzero.ai/api/v1/alert-responders/{alert_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.delete(url, headers=headers)
    response.raise_for_status()

    return response.json()

def list_webhook_subscriptions(api_key):
    """List available webhook subscriptions"""
    url = "https://api.tierzero.ai/api/v1/webhook-subscriptions"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.get(url, headers=headers)
    response.raise_for_status()

    return response.json()

def list_notification_integrations(api_key, kind=None):
    """
    List available notification integrations.

    Args:
        api_key: Organization API key
        kind: Optional filter by kind. Allowed values: DISCORD_WEBHOOK, SLACK_ALERT
    """
    url = "https://api.tierzero.ai/api/v1/notification-integrations"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }
    params = {}
    if kind:
        params["kind"] = kind

    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()

    return response.json()

# Investigation Management Functions

def get_investigation(investigation_id, api_key):
    """Get investigation details by Global ID"""
    url = f"https://api.tierzero.ai/api/v1/investigations/{investigation_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.get(url, headers=headers)
    response.raise_for_status()

    return response.json()

# Investigation usage example
investigation = get_investigation("R3JhcGhRTEpvYlJ1bjoxMjM=", "your-api-key")
print(f"Investigation: {investigation['name']}")
print(f"Status: {investigation['status']}")
print(f"Result:\n{investigation['result']}")

# Alert agent usage examples

# First, discover available webhook sources
webhook_subs = list_webhook_subscriptions("your-api-key")
print(f"Available webhook subscriptions: {len(webhook_subs['webhook_subscriptions'])}")

# Discover available notification integrations
notification_integrations = list_notification_integrations("your-api-key")
print(f"Available notification integrations: {len(notification_integrations['notification_integrations'])}")

# Create webhook-based alert agent (PagerDuty example)
webhook_alert = create_alert_responder(
    team_name="Production",
    name="Critical Error Alert",
    matching_criteria={"text_matches": ["critical", "error", "fatal"]},
    webhook_sources=[{"type": "PAGERDUTY", "remote_id": "PXXXXXX"}],
    api_key="your-api-key",
    runbook={
        "investigation_prompt": "Analyze this alert and provide detailed root cause analysis with remediation steps",
        "impact_and_severity_prompt": "Quick triage: assess severity and impact"
    },
    notification_integration_ids=["R3JhcGhRTE5vdGlmaWNhdGlvbkludGVncmF0aW9uOjEyMw=="]
)
print(f"Created webhook alert agent: {webhook_alert['url']}")

# Create Slack alert agent
slack_alert = create_alert_responder(
    team_name="Production",
    name="Database Alerts",
    matching_criteria={
        "text_matches": ["database", "connection", "timeout"],
        "slack_bot_app_user_id": "B01234567"  # Optional: filter by bot ID
    },
    slack_channel_id="C01234567",
    api_key="your-api-key",
    runbook={
        "investigation_prompt": "Investigate database issues and provide remediation steps"
    },
    notification_integration_ids=["R3JhcGhRTE5vdGlmaWNhdGlvbkludGVncmF0aW9uOjEyMw=="]
)
print(f"Created Slack alert agent: {slack_alert['url']}")

# Get alert details
alert_details = get_alert_responder(webhook_alert["id"], "your-api-key")
print(f"Alert status: {alert_details['status']}")

# List all alert agents
all_alerts = list_alert_responders("your-api-key")
print(f"Total alert agents: {len(all_alerts['alert_responders'])}")

# Update webhook-based alert agent
updated = update_alert_responder(
    webhook_alert["id"],
    "your-api-key",
    name="Updated Critical Alert",
    matching_criteria={"text_matches": ["critical", "emergency"]}
)
print(f"Updated alert agent: {updated['name']}")

# Update Slack alert agent
updated_slack = update_alert_responder(
    slack_alert["id"],
    "your-api-key",
    slack_channel_id="C98765432",
    matching_criteria={
        "text_matches": ["critical", "database"],
        "slack_bot_app_user_id": "B99999999"
    }
)
print(f"Updated Slack alert agent: {updated_slack['name']}")

# Disable alert agent temporarily
disable_alert_responder(webhook_alert["id"], "your-api-key")
print("Alert agent disabled")

# Re-enable it
enable_alert_responder(webhook_alert["id"], "your-api-key")
print("Alert agent enabled")

# Digest Agent Management Functions

def create_digest(team_name, name, sections, schedule, api_key, slack_channel_id=None):
    """Create a new digest agent job"""
    url = "https://api.tierzero.ai/api/v1/digests"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {
        "team_name": team_name,
        "name": name,
        "sections": sections,
        "schedule": schedule
    }
    if slack_channel_id:
        payload["slack_channel_id"] = slack_channel_id

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def get_digest(digest_id, api_key):
    """Get digest agent details by digest ID"""
    url = f"https://api.tierzero.ai/api/v1/digests/{digest_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.get(url, headers=headers)
    response.raise_for_status()

    return response.json()

def update_digest(digest_id, api_key, name=None, sections=None, schedule=None, slack_channel_id=None):
    """Update an existing digest agent"""
    url = f"https://api.tierzero.ai/api/v1/digests/{digest_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {}
    if name:
        payload["name"] = name
    if sections:
        payload["sections"] = sections
    if schedule:
        payload["schedule"] = schedule
    if slack_channel_id:
        payload["slack_channel_id"] = slack_channel_id

    response = requests.put(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def run_digest(digest_id, api_key, run_sync=False, scheduled_runtime=None):
    """
    Manually run a digest agent job immediately or schedule it for later.

    Args:
        digest_id: Digest Agent ID
        api_key: Organization API key
        run_sync: If True, runs synchronously and returns results
        scheduled_runtime: Optional Unix timestamp (seconds) to schedule the run

    Note: Notifications are always sent to configured channels/webhooks
    """
    url = f"https://api.tierzero.ai/api/v1/digests/{digest_id}/run"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {}
    if run_sync:
        payload["run_sync"] = run_sync
    if scheduled_runtime:
        payload["scheduled_runtime"] = scheduled_runtime

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def delete_digest(digest_id, api_key):
    """Delete a digest agent job"""
    url = f"https://api.tierzero.ai/api/v1/digests/{digest_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key
    }

    response = requests.delete(url, headers=headers)
    response.raise_for_status()

    return response.json()

# Scheduled Actions Functions

def create_scheduled_action(
    question,
    scheduled_runtimes,
    api_key,
    slack_channel_ids=None,
    discord_webhook_urls=None
):
    """
    Create a scheduled action that runs a TierZero agent at specific times.

    Args:
        question: Question/prompt to send to TierZero agent
        scheduled_runtimes: List of Unix timestamps (seconds) when action should run
        api_key: Organization API key
        slack_channel_ids: Optional list of Slack channel IDs for notifications
        discord_webhook_urls: Optional list of Discord webhook URLs for notifications

    Note:
        Notification targets are optional. If not provided, query results using GET /api/v1/interactions/{interaction_id}.

    Returns:
        Dictionary with:
        - interactions (list of dicts): One entry per scheduled runtime
        - status (str): SCHEDULED or ACCEPTED

        Each interaction dict contains: interaction_id, scheduled_runtime, and url.
    """
    url = "https://api.tierzero.ai/api/v1/interactions"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {
        "question": question,
        "scheduled_runtimes": scheduled_runtimes
    }

    # Build nested notifications structure
    notifications = {}
    if slack_channel_ids:
        notifications["slack"] = {"slack_channel_ids": slack_channel_ids}
    if discord_webhook_urls:
        notifications["discord"] = {"discord_webhook_urls": discord_webhook_urls}
    if notifications:
        payload["notifications"] = notifications

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

# Scheduled Action usage example
scheduled_action_result = create_scheduled_action(
    question="Analyze system performance metrics from the last 7 days and identify any anomalies or trends",
    scheduled_runtimes=[1735689600, 1735776000],  # Unix timestamps for when to run
    api_key="your-api-key",
    slack_channel_ids=["C01234567"]
)
print(f"Status: {scheduled_action_result['status']}")  # "SCHEDULED"
print(f"Created {len(scheduled_action_result['interactions'])} scheduled interactions:")
for interaction in scheduled_action_result['interactions']:
    print(f"  - ID: {interaction['interaction_id']}")
    print(f"    Scheduled at: {interaction['scheduled_runtime']}")
    print(f"    URL: {interaction['url']}")

# Store all interaction_ids for tracking individual executions
interaction_ids = [i['interaction_id'] for i in scheduled_action_result['interactions']]

# Digest Agent usage example
digest_result = create_digest(
    team_name="Engineering",
    name="Daily Production Health",
    sections=[
        {
            "section": "Error Summary",
            "prompt": "Summarize production errors from the last 24 hours"
        },
        {
            "section": "Performance Metrics",
            "prompt": "Report on API response times and throughput"
        }
    ],
    schedule="0 9 * * 1-5",
    api_key="your-api-key",
    slack_channel_id="C01234567"
)
print(f"Created digest: {digest_result['url']}")

# Run the digest immediately and asynchronously
run_digest(digest_result["id"], "your-api-key")

# Run the digest synchronously to get immediate results
run_result = run_digest(
    digest_result["id"],
    "your-api-key",
    run_sync=True
)
for section_result in run_result.get("results", []):
    print(f"\n{section_result['section']}:")
    print(section_result['result'])

# Schedule the digest to run at a specific time (e.g., tomorrow at 9 AM)
import time
from datetime import datetime, timedelta
tomorrow_9am = datetime.now() + timedelta(days=1)
tomorrow_9am = tomorrow_9am.replace(hour=9, minute=0, second=0, microsecond=0)
scheduled_result = run_digest(
    digest_result["id"],
    "your-api-key",
    scheduled_runtime=int(tomorrow_9am.timestamp())
)
print(f"Digest Agent scheduled for: {datetime.fromtimestamp(scheduled_result['scheduled_runtime'])}")

# Interaction Management Functions

def create_interaction_sync(question, api_key, context=None, user_id=None, use_tools=True):
    """Create a synchronous interaction"""
    url = "https://api.tierzero.ai/api/v1/interactions"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {"question": question, "use_tools": use_tools}
    if context:
        payload["context"] = context
    if user_id:
        payload["user_id"] = user_id

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def create_interaction_async(question, api_key, context=None, user_id=None, use_tools=True):
    """Create an asynchronous interaction"""
    url = "https://api.tierzero.ai/api/v1/interactions"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Content-Type": "application/json"
    }

    payload = {"question": question, "async": True, "use_tools": use_tools}
    if context:
        payload["context"] = context
    if user_id:
        payload["user_id"] = user_id

    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()

    return response.json()

def get_interaction_results(interaction_id, api_key):
    """Get interaction results by ID"""
    url = f"https://api.tierzero.ai/api/v1/interactions/{interaction_id}"
    headers = {
        "X-TierZero-Org-Api-Key": api_key,
        "Accept": "application/json"
    }

    response = requests.get(url, headers=headers)
    response.raise_for_status()

    return response.json()

def wait_for_completion(interaction_id, api_key, timeout=60, poll_interval=2):
    """Poll for interaction completion"""
    start_time = time.time()
    
    while time.time() - start_time < timeout:
        result = get_interaction_results(interaction_id, api_key)
        
        if result.get("status") == "COMPLETED":
            return result
        elif result.get("status") == "FAILED":
            raise Exception(f"Interaction failed: {interaction_id}")
        
        print(f"Status: {result.get('status')}, waiting...")
        time.sleep(poll_interval)
    
    raise TimeoutError(f"Interaction {interaction_id} did not complete within {timeout} seconds")

# Synchronous usage
result = create_interaction_sync(
    "What are the top error patterns in production today?",
    "your-api-key",
    user_id="analyst123"
)
print(result["content"])

# Asynchronous usage
async_result = create_interaction_async(
    "Analyze the performance impact of our latest deployment",
    "your-api-key",
    user_id="analyst123"
)
print(f"Started async interaction: {async_result['interaction_id']}")

# Wait for completion
final_result = wait_for_completion(async_result["interaction_id"], "your-api-key")
print(final_result["content"])

# Request without tools (knowledge-only response)
knowledge_result = create_interaction_sync(
    "What is our standard deployment process?",
    "your-api-key",
    use_tools=False
)
print(knowledge_result["content"])

Node.js

const axios = require('axios');

async function createInteraction(question, apiKey, options = {}) {
  const url = 'https://api.tierzero.ai/api/v1/interactions';

  const payload = {
    question,
    ...options
  };

  try {
    const response = await axios.post(url, payload, {
      headers: {
        'X-TierZero-Org-Api-Key': apiKey,
        'Content-Type': 'application/json'
      }
    });

    return response.data;
  } catch (error) {
    console.error('TierZero API Error:', error.response?.data || error.message);
    throw error;
  }
}

async function getInteractionResults(interactionId, apiKey) {
  const url = `https://api.tierzero.ai/api/v1/interactions/${interactionId}`;

  try {
    const response = await axios.get(url, {
      headers: {
        'X-TierZero-Org-Api-Key': apiKey,
        'Accept': 'application/json'
      }
    });

    return response.data;
  } catch (error) {
    console.error('TierZero API Error:', error.response?.data || error.message);
    throw error;
  }
}

// Usage
createInteraction(
  "Show me recent deployment failures",
  "your-api-key",
  { user_id: "devops-team" }
).then(result => {
  console.log(result.content);
  
  // Later, retrieve the same results using the interaction ID
  return getInteractionResults(result.interaction_id, "your-api-key");
}).then(retrievedResult => {
  console.log(retrievedResult.content);
});