> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abv.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks & Slack Integration

> Get real-time notifications when prompts change via Slack, custom webhooks, or CI/CD integrations for team coordination and production monitoring.

# How Webhooks Work

<Steps>
  <Step title="Configure webhook endpoint in ABV" icon="webhook">
    Create a webhook in the ABV dashboard specifying where to send prompt change notifications.

    **Navigate to Prompts → Webhooks:**

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-b1738512.png" alt="Webhooks page" />

    **Click Create Webhook:**

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-ae31bcf6.png" alt="Create webhook button" />

    **Choose integration type:**

    * **Slack Message:** OAuth-based Slack integration (zero infrastructure required)
    * **Webhook Call:** Custom HTTPS endpoint for any system integration

    You configure the endpoint URL, headers, event filters, and prompt filters.
  </Step>

  <Step title="ABV sends POST requests on prompt events" icon="paper-plane">
    When a selected event occurs (prompt created, updated, or deleted), ABV sends an HTTP POST request to your endpoint with full prompt data.

    **Event types:**

    * **Created:** New prompt version is created
    * **Updated:** Prompt labels or tags change (two events: one for version gaining label, one for version losing it)
    * **Deleted:** Prompt version is removed

    ABV automatically handles retries with exponential backoff if your endpoint returns non-2xx status codes.
  </Step>

  <Step title="Receive and validate payload" icon="shield-check">
    Your endpoint receives a JSON payload containing event metadata and complete prompt data.

    **Sample payload:**

    ```json theme={null}
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "timestamp": "2024-07-10T10:30:00Z",
      "type": "prompt-version",
      "apiVersion": "v1",
      "action": "created",
      "prompt": {
        "id": "prompt_abc123",
        "name": "movie-critic",
        "version": 3,
        "projectId": "xyz789",
        "labels": ["production", "latest"],
        "prompt": "As a {{criticLevel}} movie critic, rate {{movie}} out of 10.",
        "type": "text",
        "config": {},
        "commitMessage": "Improved critic persona",
        "tags": ["entertainment"],
        "createdAt": "2024-07-10T10:30:00Z",
        "updatedAt": "2024-07-10T10:30:00Z"
      }
    }
    ```

    **Verify authenticity** using the HMAC SHA-256 signature in the `x-abv-signature` header to ensure the request actually came from ABV.
  </Step>

  <Step title="Process events and trigger actions" icon="gears">
    Based on the payload, perform actions like:

    * Send Slack notifications to relevant channels
    * Trigger CI/CD pipelines (GitHub Actions, Jenkins, etc.)
    * Update external documentation systems
    * Sync prompt catalogs to databases or search indices
    * Alert monitoring systems (PagerDuty, Datadog, etc.)
    * Log changes to audit systems

    **Example: Slack notification**

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-d19ce833.png" alt="Slack message" />

    Teams see prompt changes in real-time without leaving their communication tools.
  </Step>
</Steps>

# Integration Patterns

<AccordionGroup>
  <Accordion title="Slack Integration (Zero Infrastructure)" icon="slack">
    The simplest integration: send notifications directly to Slack channels via OAuth, with no custom code or infrastructure required.

    **How it works:**

    1. ABV connects to your Slack workspace via OAuth
    2. You select target channels for notifications
    3. ABV sends formatted messages when prompts change
    4. Team sees updates in real-time

    **Benefits:**

    * No infrastructure to host or maintain
    * No code to write
    * OAuth-secured connection
    * Rich message formatting with prompt details

    **Best for:** Teams using Slack who want immediate visibility into prompt changes without technical overhead.

    **Setup:** See [Slack Integration Setup](#slack-integration-setup) below.
  </Accordion>

  <Accordion title="Custom Webhook Endpoints (Maximum Flexibility)" icon="code">
    Send webhook payloads to any HTTPS endpoint for custom integrations with your existing tools and workflows.

    **How it works:**

    1. Deploy a webhook receiver (FastAPI, Express, Cloudflare Workers, etc.)
    2. Configure ABV to POST to your endpoint
    3. Process payloads and trigger custom logic
    4. Return 2xx status to acknowledge receipt

    **Use cases:**

    * Sync prompts to external databases or search indices
    * Trigger CI/CD pipelines (GitHub Actions, Jenkins, GitLab CI)
    * Send notifications to Microsoft Teams, Discord, or custom chat platforms
    * Update documentation systems (Notion, Confluence, internal wikis)
    * Log changes to audit systems for compliance
    * Alert monitoring tools (PagerDuty, Datadog, New Relic)

    **Best for:** Teams needing custom integrations beyond Slack, or requiring complex processing logic.

    **Setup:** See [Custom Webhook Setup](#custom-webhook-setup) below.
  </Accordion>

  <Accordion title="Signature Verification (Security Best Practice)" icon="lock">
    Verify that webhook requests actually come from ABV and haven't been tampered with using HMAC SHA-256 signatures.

    **Why verify signatures:**

    * Prevent unauthorized requests from malicious actors
    * Ensure payload integrity (data not modified in transit)
    * Production security requirement for sensitive systems

    **How it works:**

    1. ABV generates a signing secret when you create the webhook
    2. ABV signs each request with HMAC SHA-256 using the secret
    3. Signature included in `x-abv-signature` header (format: `t=timestamp,s=signature`)
    4. Your endpoint recreates the signature and compares

    **Signature format:**

    ```
    x-abv-signature: t=1720701136,s=0123abcdef...
    ```

    **Security tip:** Use constant-time comparison (`hmac.compare_digest` in Python, `crypto.timingSafeEqual` in Node.js) to prevent timing attacks.

    **Implementation:** See [Signature Verification Code](#signature-verification) below.
  </Accordion>

  <Accordion title="Event and Prompt Filtering" icon="filter">
    Reduce noise by filtering which events trigger webhooks and which prompts are monitored.

    **Event filtering:**
    Select which actions trigger webhooks:

    * **Created:** Only fire when new prompt versions are created
    * **Updated:** Only fire when labels or tags change
    * **Deleted:** Only fire when prompt versions are deleted

    Default: all events selected.

    **Prompt filtering:**
    Optionally filter to specific prompts by:

    * Prompt name patterns (e.g., only `production/*` prompts)
    * Tags (e.g., only prompts tagged `critical`)
    * Labels (e.g., only prompts with `production` label)

    **Example use case:**

    * Production monitoring: Filter to only `production`-labeled prompts for critical alerts
    * Team-specific notifications: Filter by tags to route notifications to relevant Slack channels
    * Reduce noise: Only notify on `created` events, ignore label changes

    **Configuration:** Set filters when creating or editing webhooks in the ABV UI.
  </Accordion>

  <Accordion title="Idempotent Handling (Reliability)" icon="arrows-rotate">
    Design webhook handlers to be idempotent, as ABV retries failed webhook deliveries.

    **Retry behavior:**

    * ABV retries webhooks that return non-2xx status codes
    * Exponential backoff strategy (retries with increasing delays)
    * Continues until successful delivery or maximum retry limit

    **Idempotent handler design:**

    ```python theme={null}
    # Example: Use event ID to deduplicate
    processed_events = set()  # In production, use Redis or database

    def handle_webhook(event):
        event_id = event["id"]

        # Skip if already processed
        if event_id in processed_events:
            return {"status": "already_processed"}

        # Process event
        send_slack_notification(event)

        # Mark as processed
        processed_events.add(event_id)

        return {"status": "success"}
    ```

    **Best practices:**

    * Use event `id` for deduplication
    * Store processed event IDs in Redis, database, or cache
    * Always return 2xx on success to stop retries
    * Design operations to be safely repeatable (e.g., upsert instead of insert)
  </Accordion>
</AccordionGroup>

# Slack Integration Setup

<AccordionGroup>
  <Accordion title="Step 1: Authenticate Slack with ABV" icon="key">
    Connect your Slack workspace to ABV via OAuth.

    **Steps:**

    1. In ABV dashboard, navigate to **Prompts** → **Webhooks**

    2. Click **Create Webhook**

    3. Select **Slack Message** tab

    4. Click **Authenticate with Slack**

           <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-5581b1f7.png" alt="Slack OAuth" />

    5. Slack OAuth flow opens in new window

    6. Select your Slack workspace

    7. Authorize ABV to post messages

    **Permissions requested:**

    * `chat:write`: Post messages to channels
    * `channels:read`: List public channels

    **Security:** ABV stores Slack OAuth tokens encrypted in the database. You can revoke access anytime via Slack's App Management.
  </Accordion>

  <Accordion title="Step 2: Select Target Channels" icon="hashtag">
    Choose which Slack channels receive prompt change notifications.

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-31f847c6.png" alt="Channel selection" />

    **Steps:**

    1. After OAuth completes, you'll see a dropdown of available channels
    2. Select one or more channels (you can create multiple webhooks for different channels)
    3. **(Optional)** Run a dry run to test the integration

    **Dry run:**

    * Sends a test notification to the selected channel
    * Verifies OAuth permissions and channel access
    * Helps you preview message formatting before going live

    **Channel requirements:**

    * ABV must be invited to private channels before they appear in the dropdown
    * Public channels appear automatically after OAuth
  </Accordion>

  <Accordion title="Step 3: Configure Event Filters" icon="sliders">
    Select which prompt events trigger Slack notifications.

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-af4c3e75.png" alt="Event selection" />

    **Event types:**

    * **Created:** New prompt version is created
    * **Updated:** Labels or tags change on existing version
    * **Deleted:** Prompt version is removed

    **Filtering options:**

    * **(Optional)** Filter to specific prompts by name pattern
    * **(Optional)** Filter to specific tags
    * **(Optional)** Filter to specific labels (e.g., only `production`)

    **Example configurations:**

    * **Production monitoring:** Only `created` events on `production`-labeled prompts
    * **All changes:** All events, all prompts (high-volume notifications)
    * **Team-specific:** Only prompts tagged with `customer-support` team tag
  </Accordion>

  <Accordion title="Step 4: View Messages in Slack" icon="comment">
    See prompt change notifications in your Slack channel.

    <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-d19ce833.png" alt="Slack notification" />

    **Message includes:**

    * Prompt name and version
    * Action performed (created, updated, deleted)
    * Labels and tags
    * Commit message (if provided)
    * Timestamp
    * Link back to ABV for full details

    **Message format example:**

    ```
    🔔 Prompt Updated

    Name: movie-critic
    Version: 3
    Action: created
    Labels: production, latest
    Tags: entertainment

    Commit message: "Improved critic persona"

    View in ABV →
    ```

    Team members can click through to ABV for full prompt content and history.
  </Accordion>
</AccordionGroup>

# Custom Webhook Setup

<AccordionGroup>
  <Accordion title="Step 1: Configure Webhook Endpoint" icon="link">
    Set up a custom HTTPS endpoint to receive webhook POST requests.

    **Steps:**

    1. In ABV dashboard, navigate to **Prompts** → **Webhooks**
    2. Click **Create Webhook**
    3. Select **Webhook Call** tab
    4. Configure request details:

           <img src="https://mintlify.s3.us-west-1.amazonaws.com/abv-2be93c70/images/prompt-management-webhooks-slack-integration-bb7eea47.png" alt="Webhook configuration" />

    **URL:** HTTPS endpoint that accepts POST requests

    ```
    https://your-domain.com/api/webhooks/abv-prompts
    ```

    **Headers:** Default headers are automatically included:

    * `Content-Type: application/json`
    * `User-Agent: ABV/1.0`
    * `x-abv-signature: <signature>` (HMAC SHA-256)

    **Custom headers:** Add any additional headers your endpoint requires (e.g., API keys, auth tokens)

    ```
    X-API-Key: your-api-key
    Authorization: Bearer your-token
    ```

    **Event selection:** Choose which events trigger the webhook (created, updated, deleted)

    **Prompt filters:** Optionally filter to specific prompts or tags
  </Accordion>

  <Accordion title="Step 2: Implement Webhook Handler" icon="code">
    Create an endpoint that receives and processes webhook payloads.

    **Minimal webhook handler (Python/FastAPI):**

    ```python theme={null}
    from fastapi import FastAPI, Request, HTTPException
    from pydantic import BaseModel
    from typing import Dict, Any

    app = FastAPI()

    class WebhookPayload(BaseModel):
        id: str
        timestamp: str
        type: str
        action: str
        prompt: Dict[str, Any]

    @app.post("/api/webhooks/abv-prompts")
    async def handle_abv_webhook(payload: WebhookPayload):
        """Process ABV prompt webhook."""
        print(f"Received {payload.action} event for prompt {payload.prompt['name']} v{payload.prompt['version']}")

        # Your custom logic here:
        # - Send notification to Microsoft Teams
        # - Trigger CI/CD pipeline
        # - Update documentation
        # - Log to audit system
        # etc.

        # Return 2xx to acknowledge receipt
        return {"status": "received", "event_id": payload.id}
    ```

    **Minimal webhook handler (Node.js/Express):**

    ```typescript theme={null}
    import express from 'express';

    const app = express();
    app.use(express.json());

    app.post('/api/webhooks/abv-prompts', (req, res) => {
      const { id, action, prompt } = req.body;

      console.log(`Received ${action} event for prompt ${prompt.name} v${prompt.version}`);

      // Your custom logic here

      res.status(200).json({ status: 'received', event_id: id });
    });

    app.listen(3000, () => console.log('Webhook handler listening on port 3000'));
    ```

    **Important:** Always return 2xx status codes on successful processing to prevent ABV from retrying.
  </Accordion>

  <Accordion title="Step 3: Inspect Webhook Payload" icon="file-code">
    Understand the structure of webhook payloads to extract relevant data.

    **Full payload structure:**

    ```json theme={null}
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "timestamp": "2024-07-10T10:30:00Z",
      "type": "prompt-version",
      "apiVersion": "v1",
      "action": "created",
      "prompt": {
        "id": "prompt_abc123",
        "name": "movie-critic",
        "version": 3,
        "projectId": "xyz789",
        "labels": ["production", "latest"],
        "prompt": "As a {{criticLevel}} movie critic, rate {{movie}} out of 10.",
        "type": "text",
        "config": { "model": "gpt-4o", "temperature": 0.7 },
        "commitMessage": "Improved critic persona",
        "tags": ["entertainment"],
        "createdAt": "2024-07-10T10:30:00Z",
        "updatedAt": "2024-07-10T10:30:00Z"
      }
    }
    ```

    **Key fields:**

    * `id`: Unique event identifier (use for deduplication)
    * `timestamp`: ISO 8601 timestamp of when event occurred
    * `action`: Event type (`created`, `updated`, `deleted`)
    * `prompt.name`: Prompt name (may include folder path like `customer-support/billing`)
    * `prompt.version`: Version number
    * `prompt.labels`: Array of labels (e.g., `["production", "staging"]`)
    * `prompt.tags`: Array of tags for categorization
    * `prompt.commitMessage`: Optional message describing the change
    * `prompt.prompt`: Actual prompt content (text or chat messages array)
    * `prompt.config`: Model configuration (model name, temperature, etc.)

    **Use cases by field:**

    * `action == "created" && "production" in labels`: Alert team of production deployment
    * `tags`: Route notifications to team-specific channels
    * `commitMessage`: Include in Slack notification for context
    * `version`: Track version history in external systems
  </Accordion>

  <Accordion title="Step 4: Deploy Webhook Handler" icon="cloud-arrow-up">
    Deploy your webhook handler to a publicly accessible HTTPS endpoint.

    **Deployment options:**

    **Option 1: Serverless (Vercel, Netlify, Cloudflare Workers)**

    * Zero infrastructure management
    * Automatic scaling
    * Pay-per-request pricing
    * Example: Deploy Express handler to Vercel

    **Option 2: Cloud Functions (AWS Lambda, Google Cloud Functions, Azure Functions)**

    * Event-driven execution
    * Integrates with cloud services
    * Example: Lambda function triggered by API Gateway

    **Option 3: Traditional Hosting (Render, Fly.io, Heroku)**

    * Full control over runtime environment
    * Persistent state (if needed)
    * Example: FastAPI app on Render.com

    **Requirements:**

    * HTTPS endpoint (TLS/SSL required)
    * Accepts HTTP POST requests
    * Returns 2xx status on success
    * Responds within reasonable timeout (\< 30 seconds recommended)

    **After deployment:**

    1. Note your public HTTPS URL
    2. Update ABV webhook configuration with the URL
    3. Test by triggering a prompt event in ABV
    4. Check webhook handler logs for incoming requests
  </Accordion>
</AccordionGroup>

# Signature Verification

<AccordionGroup>
  <Accordion title="Why Verify Signatures" icon="shield-halved">
    Webhook signature verification ensures requests actually come from ABV and haven't been tampered with.

    **Security benefits:**

    * **Authentication:** Confirm request originated from ABV, not a malicious actor
    * **Integrity:** Verify payload wasn't modified in transit
    * **Non-repudiation:** Prove ABV sent the specific payload

    **When verification is critical:**

    * Production deployments triggered by webhooks
    * Webhooks that modify databases or external systems
    * Compliance requirements (audit trails, data integrity)
    * Public endpoints accessible from the internet

    **How it works:**

    1. ABV generates a signing secret when you create the webhook (copy and store securely)
    2. For each request, ABV computes HMAC SHA-256 of `timestamp.payload` using the secret
    3. Signature included in `x-abv-signature` header: `t=<timestamp>,s=<signature>`
    4. Your handler recreates the signature and compares

    **Signature format:**

    ```
    x-abv-signature: t=1720701136,s=a1b2c3d4e5f6...
    ```

    * `t`: Unix timestamp when signature was generated
    * `s`: HMAC SHA-256 hex digest
  </Accordion>

  <Accordion title="Python Implementation" icon="python">
    Verify webhook signatures in Python using the `hmac` module.

    **Implementation:**

    ```python theme={null}
    import hmac
    import hashlib
    from typing import Optional


    def verify_abv_signature(
        raw_body: str,
        signature_header: str,
        secret: str,
    ) -> bool:
        """
        Validate a ABV webhook/event signature.

        Parameters
        ----------
        raw_body : str
            The request body exactly as received (no decoding or reformatting).
        signature_header : str
            The value of the `x-abv-signature` header, e.g. "t=1720701136,s=0123abcd...".
        secret : str
            Your ABV signing secret.

        Returns
        -------
        bool
            True if the signature is valid, otherwise False.
        """
        # Split "t=timestamp,s=signature" into the two expected key/value chunks
        try:
            ts_pair, sig_pair = signature_header.split(",", 1)
        except ValueError:  # wrong format / missing comma
            return False

        # Extract values (everything after the first "=")
        if "=" not in ts_pair or "=" not in sig_pair:
            return False
        timestamp = ts_pair.split("=", 1)[1]
        received_sig_hex = sig_pair.split("=", 1)[1]

        # Recreate the message and compute the expected HMAC-SHA256 hex digest
        message = f"{timestamp}.{raw_body}".encode("utf-8")
        expected_sig_hex = hmac.new(
            secret.encode("utf-8"), message, hashlib.sha256
        ).hexdigest()

        # Use constant-time comparison on the *decoded* byte strings
        try:
            return hmac.compare_digest(
                bytes.fromhex(received_sig_hex), bytes.fromhex(expected_sig_hex)
            )
        except ValueError:  # received_sig_hex isn't valid hex
            return False
    ```

    **Usage in FastAPI:**

    ```python theme={null}
    from fastapi import FastAPI, Request, HTTPException, Header

    WEBHOOK_SECRET = "your-signing-secret-from-abv"

    @app.post("/api/webhooks/abv-prompts")
    async def handle_webhook(
        request: Request,
        x_abv_signature: str = Header(...)
    ):
        # Read raw body (important: don't decode or parse yet)
        raw_body = await request.body()

        # Verify signature
        if not verify_abv_signature(raw_body.decode(), x_abv_signature, WEBHOOK_SECRET):
            raise HTTPException(status_code=401, detail="Invalid signature")

        # Parse JSON after verification
        payload = await request.json()

        # Process webhook...
        return {"status": "received"}
    ```

    **Security notes:**

    * Use `hmac.compare_digest()` for constant-time comparison (prevents timing attacks)
    * Verify signature *before* parsing or processing payload
    * Store signing secret in environment variables, not code
  </Accordion>

  <Accordion title="JavaScript/TypeScript Implementation" icon="js">
    Verify webhook signatures in Node.js using the `crypto` module.

    **Implementation:**

    ```typescript theme={null}
    import crypto from "crypto";

    export function verifyABVSignature(
      rawBody: string,
      signatureHeader: string,
      secret: string
    ): boolean {
      // Parse header: "t=timestamp,s=signature"
      const [tsPair, sigPair] = signatureHeader.split(",");
      if (!tsPair || !sigPair) return false;

      const timestamp = tsPair.split("=")[1];
      const receivedSig = sigPair.split("=")[1];

      // Recreate signature
      const expectedSig = crypto
        .createHmac("sha256", secret)
        .update(`${timestamp}.${rawBody}`, "utf8")
        .digest("hex");

      // Constant-time comparison
      try {
        return crypto.timingSafeEqual(
          Buffer.from(receivedSig, "hex"),
          Buffer.from(expectedSig, "hex")
        );
      } catch {
        return false;  // receivedSig not valid hex
      }
    }
    ```

    **Usage in Express:**

    ```typescript theme={null}
    import express from 'express';
    import { verifyABVSignature } from './verify-signature';

    const WEBHOOK_SECRET = process.env.ABV_WEBHOOK_SECRET!;

    const app = express();

    // Use express.text() to get raw body as string
    app.post('/api/webhooks/abv-prompts',
      express.text({ type: 'application/json' }),
      (req, res) => {
        const signature = req.headers['x-abv-signature'] as string;

        // Verify signature
        if (!verifyABVSignature(req.body, signature, WEBHOOK_SECRET)) {
          return res.status(401).json({ error: 'Invalid signature' });
        }

        // Parse JSON after verification
        const payload = JSON.parse(req.body);

        // Process webhook...
        res.json({ status: 'received', event_id: payload.id });
      }
    );
    ```

    **Security notes:**

    * Use `crypto.timingSafeEqual()` for constant-time comparison
    * Parse `rawBody` to string before passing to verification function
    * Verify *before* parsing JSON to prevent processing malicious payloads
  </Accordion>

  <Accordion title="Troubleshooting Signature Verification" icon="wrench">
    Common issues when implementing signature verification.

    **Issue: Signature always fails**

    **Causes and solutions:**

    1. **Wrong secret:** Verify you copied the signing secret correctly from ABV
       * Regenerate secret in ABV and update your code
       * Check for extra whitespace or newlines

    2. **Body modified before verification:** Raw body must be exactly as received
       ```python theme={null}
       # Wrong: body already parsed
       payload = await request.json()
       verify_signature(json.dumps(payload), sig, secret)  # FAILS

       # Correct: use raw body
       raw_body = await request.body()
       verify_signature(raw_body.decode(), sig, secret)  # WORKS
       payload = json.loads(raw_body)
       ```

    3. **Encoding issues:** Ensure consistent UTF-8 encoding
       ```python theme={null}
       message = f"{timestamp}.{raw_body}".encode("utf-8")  # Explicit UTF-8
       ```

    4. **Header parsing error:** Verify header format is `t=...,s=...`
       ```python theme={null}
       # Debug: print header value
       print(f"Signature header: {signature_header}")
       ```

    **Issue: Occasional signature failures**

    **Cause:** Clock skew between ABV servers and your server

    **Solution:** Add timestamp validation with tolerance window

    ```python theme={null}
    import time

    def verify_abv_signature_with_timestamp(raw_body, signature_header, secret, tolerance=300):
        # ... existing verification code ...

        # After signature verification passes, check timestamp
        current_time = int(time.time())
        timestamp_int = int(timestamp)

        if abs(current_time - timestamp_int) > tolerance:
            # Reject if timestamp is > 5 minutes old (replay attack protection)
            return False

        return True
    ```

    **Issue: Constant-time comparison fails**

    **Cause:** Hex strings not properly converted to bytes

    **Solution:** Use `bytes.fromhex()` or `Buffer.from(sig, 'hex')`

    ```python theme={null}
    # Correct: convert hex to bytes before comparison
    return hmac.compare_digest(
        bytes.fromhex(received_sig_hex),
        bytes.fromhex(expected_sig_hex)
    )
    ```
  </Accordion>
</AccordionGroup>

# Common Use Cases

<AccordionGroup>
  <Accordion title="Production Monitoring" icon="bell">
    Get alerted immediately when production prompts are updated to coordinate deployments and monitor for unexpected changes.

    **Setup:**

    * Create Slack webhook filtered to `production` label
    * Subscribe `#production-alerts` channel
    * Configure to trigger on `created` and `updated` events

    **Workflow:**

    1. Engineer updates prompt and assigns `production` label
    2. Slack notification sent to `#production-alerts`
    3. Team aware of change, can monitor for issues
    4. If problems arise, easy to correlate with prompt update

    **Example Slack message:**

    ```
    🚨 Production Prompt Updated

    Name: customer-support/billing
    Version: 12
    Action: created
    Label: production

    Commit: "Updated refund policy for EU customers"

    @channel - New billing prompt deployed
    ```

    Team can immediately investigate if customer support tickets spike after the change.
  </Accordion>

  <Accordion title="Team Coordination" icon="users">
    Keep cross-functional teams informed about prompt changes that affect their work.

    **Setup:**

    * Create multiple webhooks for different teams
    * Filter by tags (e.g., `team:customer-support`, `team:marketing`)
    * Route notifications to team-specific Slack channels

    **Example:**

    * **Customer support team:** Notified of prompts tagged `customer-support`
    * **Marketing team:** Notified of prompts tagged `marketing`
    * **Engineering team:** Notified of all `production` prompts

    **Benefit:** Each team sees only relevant changes, reducing notification fatigue while ensuring visibility.
  </Accordion>

  <Accordion title="Automated CI/CD Pipelines" icon="gears">
    Trigger automated testing and deployment workflows when prompts change.

    **Setup:**

    * Configure custom webhook to trigger GitHub Actions, Jenkins, or GitLab CI
    * Run automated tests on prompt changes
    * Deploy to staging/production environments

    **Example workflow:**

    1. Engineer updates prompt in ABV
    2. Webhook triggers GitHub Actions workflow
    3. Workflow runs integration tests with new prompt
    4. If tests pass, deploy prompt to staging
    5. Manual approval → deploy to production

    **Implementation:** See [GitHub Integration](/developer/prompt-management/github-integration) for detailed setup.
  </Accordion>

  <Accordion title="External System Sync" icon="arrows-rotate">
    Automatically sync prompts to external databases, search indices, or documentation systems.

    **Use cases:**

    * **Elasticsearch index:** Keep searchable prompt catalog up-to-date
    * **Documentation:** Auto-update internal wiki when prompts change
    * **Audit database:** Log all prompt changes for compliance
    * **Prompt versioning system:** Sync to external version control

    **Example: Sync to Elasticsearch**

    ```python theme={null}
    from elasticsearch import Elasticsearch

    es = Elasticsearch(["https://your-elasticsearch-cluster"])

    @app.post("/api/webhooks/abv-prompts")
    async def sync_to_elasticsearch(payload: WebhookPayload):
        # Index prompt in Elasticsearch
        es.index(
            index="prompts",
            id=payload.prompt["id"],
            document={
                "name": payload.prompt["name"],
                "version": payload.prompt["version"],
                "content": payload.prompt["prompt"],
                "labels": payload.prompt["labels"],
                "tags": payload.prompt["tags"],
                "updated_at": payload.timestamp
            }
        )

        return {"status": "synced"}
    ```

    Now prompts are searchable in Elasticsearch, enabling advanced search capabilities.
  </Accordion>

  <Accordion title="Compliance Audit Trails" icon="scroll">
    Maintain comprehensive audit logs of all prompt changes for regulatory compliance (GDPR, HIPAA, SOC 2, etc.).

    **Setup:**

    * Configure webhook to log all events to audit database
    * Capture who made the change, what changed, when, and why (commit message)
    * Store immutable records for compliance audits

    **Example audit record:**

    ```json theme={null}
    {
      "event_id": "550e8400-e29b-41d4-a716-446655440000",
      "timestamp": "2024-07-10T10:30:00Z",
      "action": "created",
      "resource_type": "prompt",
      "resource_id": "prompt_abc123",
      "resource_name": "customer-support/gdpr-request-handler",
      "version": 5,
      "labels": ["production"],
      "commit_message": "Updated GDPR data deletion flow per legal review",
      "actor": "engineer@company.com",
      "changes": {
        "before": {...},
        "after": {...}
      }
    }
    ```

    **Compliance value:** Demonstrates change management controls, supports audit requirements, proves data governance.
  </Accordion>
</AccordionGroup>

# Next Steps

<CardGroup cols={2}>
  <Card title="GitHub Integration" icon="github" href="/developer/prompt-management/github-integration">
    Trigger GitHub Actions workflows and sync prompts to git repositories
  </Card>

  <Card title="Get Started with Prompt Management" icon="rocket" href="/developer/prompt-management/get-started">
    Complete quickstart guide for creating and deploying prompts
  </Card>

  <Card title="Version Control" icon="code-branch" href="/developer/prompt-management/version-control">
    Deploy and rollback prompts safely using labels and versions
  </Card>

  <Card title="A/B Testing Prompts" icon="flask" href="/developer/prompt-management/ab-testing-llm-prompts">
    Run statistical A/B tests on prompt variants in production
  </Card>
</CardGroup>
