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 responders, 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 Responder Management

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

Create a new alert responder 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 responder 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 responder 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 responder 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 responder Global ID
  "url": "string",     // Link to alert responder details page
  "name": "string",    // Alert responder name
  "status": "ACTIVE"   // Status (ACTIVE or PAUSED)
}

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

Retrieve detailed information about a specific alert responder.
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 responder Global ID
Response
Status Code: 200 OK
{
  "id": "string",                     // Alert responder Global ID
  "organization_name": "string",      // Organization name
  "team_name": "string",              // Team name
  "name": "string",                   // Alert responder 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 Responders (GET /api/v1/alert-responders)

List all alert responders 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 responder Global ID
      "name": "string",     // Alert responder name
      "team_name": "string",// Team name
      "status": "ACTIVE",   // Status (ACTIVE or PAUSED)
      "url": "string"       // Link to alert responder details page
    }
  ]
}

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

Update an existing alert responder’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 responder 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 responder Global ID
  "url": "string",     // Link to alert responder details page
  "name": "string",    // Alert responder name
  "status": "ACTIVE"   // Status (ACTIVE or PAUSED)
}

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

Delete an alert responder.
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 responder Global ID
Response
Status Code: 200 OK
{
  "success": true
}
Idempotency: Returns success even if the alert responder is already deleted.

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

Enable a paused alert responder 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 responder Global ID
Response
Status Code: 200 OK
{
  "id": "string",      // Alert responder Global ID
  "status": "ACTIVE"   // Updated status
}

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

Disable an alert responder 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 responder Global ID
Response
Status Code: 200 OK
{
  "id": "string",      // Alert responder 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 responders.
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 responders.
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
    }
  ]
}

Digest Management

Create Digest (POST /api/v1/digests)

Create a new scheduled digest 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
  "sections": [                 // Required: Array of digest 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 ID
  "url": "string"    // Link to digest details page
}

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

Retrieve details about a specific digest 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 ID returned from create/update operations
Response
Status Code: 200 OK
{
  "organization_name": "string",  // Organization name
  "team_name": "string",          // Team name
  "id": "string",                 // Digest ID
  "name": "string",               // Digest name
  "sections": [                   // Digest 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 (PUT /api/v1/digests/{digest_id})

Update an existing digest 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 ID
Request Body:
{
  "name": "string",             // Optional: New name for the digest
  "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 ID
  "url": "string"    // Link to digest details page
}

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

Delete a digest 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 ID
Response
Status Code: 200 OK
{
  "success": true
}

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

Manually trigger a digest 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 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 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.
Response (Immediate Run - Async Mode)
Status Code: 200 OK
{
  "id": "string",    // Digest ID
  "url": "string"    // Link to digest details page
}
Response (Immediate Run - Sync Mode with run_sync: true)
Status Code: 200 OK
{
  "id": "string",       // Digest ID
  "url": "string",      // Link to digest 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 ID
  "url": "string",             // Link to digest details page
  "scheduled_runtime": 1735689600  // Unix timestamp when the digest is scheduled to run
}

Cron Expression Reference

Digest 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 Responder Management Examples

Create an Alert Responder

# 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 responder (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 responder
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 Responders

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

# List alert responders 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 Responder 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 Responder

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 Responder

# Enable alert responder
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 responder
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 Responder

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

Digest Management Examples

Create a Daily Digest

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 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

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 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 for Later

# Schedule digest 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

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 Responder 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 responder.

    Args:
        team_name: Team name
        name: Alert responder 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 responder 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 responders, 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 responder.

    Args:
        alert_id: Alert responder 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 responder"""
    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 responder"""
    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 responder"""
    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()

# Alert responder 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 responder (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 responder: {webhook_alert['url']}")

# Create Slack alert responder
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 responder: {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 responders
all_alerts = list_alert_responders("your-api-key")
print(f"Total alert responders: {len(all_alerts['alert_responders'])}")

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

# Update Slack alert responder
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 responder: {updated_slack['name']}")

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

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

# Digest Management Functions

def create_digest(team_name, name, sections, schedule, api_key, slack_channel_id=None):
    """Create a new digest 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 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"""
    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 job immediately or schedule it for later.

    Args:
        digest_id: Digest 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 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 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 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);
});