Skip to content

Authentication Reference

Complete reference for CarvOS API authentication.

API Key Authentication

Header Format

X-API-Key: your-api-key

Context Headers

Header Required Description
X-API-Key Always Your ATS API key
X-ATS-Client-ID For entity operations ATS client identifier (maps to workspace)
X-ATS-User-ID For entity operations ATS user identifier (maps to member)

Webhook Signature Verification

Signature Header

All outgoing webhooks include:

X-Webhook-Signature: t=1234567890,v1=[hex-digest]

Verification Algorithm

import hmac
import hashlib
import time

def verify_signature(
    payload: bytes,
    signature_header: str,
    secret: str,
    tolerance_seconds: int = 300,
) -> bool:
    """
    Verify webhook signature.

    Args:
        payload: Raw request body bytes
        signature_header: Value of X-Webhook-Signature header (t=...,v1=...)
        secret: Your outgoing webhook secret
        tolerance_seconds: Max age of signature (default: 5 minutes)

    Returns:
        True if signature is valid
    """
    parts = dict(part.split("=", 1) for part in signature_header.split(","))
    timestamp = parts["t"]
    provided_sig = parts["v1"]

    # Reject signatures older than tolerance
    if abs(time.time() - int(timestamp)) > tolerance_seconds:
        return False

    signed_payload = f"{timestamp}.".encode() + payload
    expected = hmac.new(
        secret.encode("utf-8"),
        signed_payload,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected, provided_sig)

Signature Components

The signature is computed over:

  1. Timestamp + raw request body — The string {timestamp}. encoded to bytes, concatenated with the raw request body bytes
  2. UTF-8 encoded secret — Your webhook secret as UTF-8 bytes

Warning

Timing-safe comparison — Always use constant-time comparison (hmac.compare_digest) to prevent timing attacks.

Security Best Practices

  • Store keys securely


    Use environment variables or secret management

  • Rotate keys periodically


    Request new keys every 90 days

  • Use separate keys per environment


    Never use production keys in development

  • Verify all signatures


    Never skip webhook verification