Hookbase
Docs
GuideAPI ReferenceIntegrationsUse CasesCLIMCP
Getting StartedSDK ReferencePortal ComponentsAPI Reference
Get Started

Getting Started

IntroductionQuick StartBest PracticesPipeline Architecture

Core Concepts

SourcesDestinationsRoutes

Advanced Features

TransformsAI TransformsFiltersSchemasDeduplicationCustom DomainsTunnelsCron JobsScheduled Sends

Enterprise Security

OverviewCircuit BreakerFailover DestinationsIP FilteringStatic IP DeliveryNotification ChannelsObservability ExportField EncryptionAudit Logs

Kubernetes

Operator GuideCRD ReferenceHelm Chart

Operations

Plans & LimitsProduction ReadinessTroubleshootingTestingComparison
DocsReceiveGuideKubernetes Crds

CRD Reference

The Hookbase Kubernetes Operator provides 10 Custom Resource Definitions. All resources use the API group hookbase.io/v1alpha1.

Core Resources

WebhookSource

Defines a webhook ingestion endpoint.

apiVersion: hookbase.io/v1alpha1
kind: WebhookSource
metadata:
  name: github-webhooks
spec:
  name: GitHub Webhooks             # Display name
  slug: github-webhooks             # URL slug (immutable after creation)
  provider: github                  # Provider for signature verification
  description: "GitHub org webhooks"
  verifySignature: true             # Enable provider signature verification
  signingSecretRef:                 # K8s Secret containing signing secret
    name: github-webhook-secret
    key: secret
  rejectInvalidSignatures: true     # Reject webhooks with invalid signatures
  rateLimitPerMinute: 1000          # Rate limit for incoming webhooks
  ipFilterMode: allowlist           # "allowlist" or "denylist"
  ipAllowlist:                      # CIDR ranges to allow
    - "192.168.0.0/16"
  dedupStrategy: auto               # "auto", "provider_id", "payload_hash", "idempotency_key", "none"
  dedupWindowHours: 24              # Deduplication window
  apiKeyRef:                        # Override API key (optional)
    name: my-secret
    key: apiKey
status:
  sourceId: "src_abc123"            # API resource ID
  ingestUrl: "https://..."          # Webhook ingestion URL
  conditions:                       # Standard K8s conditions
    - type: Ready
      status: "True"
      reason: Synced
    - type: Synced
      status: "True"
  observedGeneration: 1
  lastSyncTime: "2026-02-17T12:00:00Z"

Supported providers: generic, github, gitlab, stripe, shopify, slack, twilio, sendgrid, paddle, linear, vercel, discord

WebhookDestination

Defines where webhooks are delivered.

apiVersion: hookbase.io/v1alpha1
kind: WebhookDestination
metadata:
  name: internal-api
spec:
  name: Internal API
  slug: internal-api                # URL slug (immutable)
  url: "https://api.example.com/webhooks"
  method: POST                      # HTTP method (default: POST)
  headers:                          # Custom headers
    X-Custom-Header: "value"
  authType: bearer                  # "bearer", "basic", "header", "none"
  authSecretRef:                    # K8s Secret for auth credentials
    name: api-auth-secret
    key: token
  timeoutMs: 10000                  # Request timeout (milliseconds)
  rateLimitPerMinute: 500           # Outbound rate limit
  useStaticIp: true                 # Route via static IP proxy (Pro/Business)
  apiKeyRef:                        # Override API key (optional)
    name: my-secret
    key: apiKey
status:
  destinationId: "dst_xyz789"
  conditions:
    - type: Ready
      status: "True"
  observedGeneration: 1
  lastSyncTime: "2026-02-17T12:00:00Z"

Warehouse Destination (S3)

For warehouse destinations (S3, R2, GCS, Azure Blob), use type and configSecretRef instead of url:

apiVersion: hookbase.io/v1alpha1
kind: WebhookDestination
metadata:
  name: s3-warehouse
spec:
  name: S3 Data Warehouse
  type: s3                            # "s3", "r2", "gcs", "azure_blob"
  configSecretRef:                    # K8s Secret with warehouse credentials
    name: s3-warehouse-creds
    key: config
  fieldMapping:                       # Map webhook fields to warehouse columns
    - source: "$.id"
      target: event_id
      type: string
    - source: "$.body"
      target: payload
      type: json
    - source: "$.headers.x-event-type"
      target: event_type
      type: string
      default: "unknown"
    - source: "$.timestamp"
      target: received_at
      type: timestamp
  apiKeyRef:
    name: my-secret
    key: apiKey
---
# Secret with warehouse credentials
apiVersion: v1
kind: Secret
metadata:
  name: s3-warehouse-creds
type: Opaque
stringData:
  bucket: my-webhook-data
  region: us-east-1
  accessKeyId: AKIA...
  secretAccessKey: "secret..."
  prefix: webhooks/

Supported warehouse types: s3, r2 (Cloudflare R2), gcs (Google Cloud Storage), azure_blob (Azure Blob Storage)

WebhookRoute

Connects a source to a destination with optional filtering and transformation.

apiVersion: hookbase.io/v1alpha1
kind: WebhookRoute
metadata:
  name: github-to-api
spec:
  name: GitHub to Internal API
  sourceRef: github-webhooks         # WebhookSource name in same namespace
  destinationRef: internal-api       # WebhookDestination name
  filterRef: production-only         # WebhookFilter name (optional)
  # OR inline filter conditions (mutually exclusive with filterRef):
  filterConditions:
    - field: headers.x-github-event
      operator: in
      value: "push,pull_request,release"
  filterLogic: AND                   # "AND" or "OR" (default: AND)
  transformRef: strip-headers        # WebhookTransform name (optional)
  schemaRef: github-schema           # WebhookSchema name (optional)
  priority: 10                       # Route priority (lower = higher priority)
  isActive: true                     # Enable/disable the route
  failoverDestinationRefs:           # Backup destinations
    - backup-api
  circuitBreaker:
    failureThreshold: 5              # Failures before circuit opens
    cooldownSeconds: 60              # Cooldown before probing
  apiKeyRef:                         # Override API key (optional)
    name: my-secret
    key: apiKey
status:
  routeId: "rt_def456"
  resolvedSourceId: "src_abc123"     # Resolved API ID from sourceRef
  resolvedDestinationId: "dst_xyz789"
  conditions:
    - type: Ready
      status: "True"
  observedGeneration: 1
  lastSyncTime: "2026-02-17T12:00:00Z"

WebhookTunnel

Creates a public URL that tunnels to a local Kubernetes service.

apiVersion: hookbase.io/v1alpha1
kind: WebhookTunnel
metadata:
  name: dev-tunnel
spec:
  name: Dev Tunnel
  subdomain: my-app-dev             # Custom subdomain (immutable, optional)
  targetPort: 8080                   # Port to forward to
  targetService: my-app              # K8s Service name (optional, defaults to localhost)
  authTokenSecretRef:                # Custom Secret name for auth token (optional)
    name: my-tunnel-auth
  sidecarInjection:                  # Automatic sidecar injection (optional)
    deploymentRef: my-app            # Target Deployment name
    agentImage: "ghcr.io/hookbase/hookbase-agent:v0.1.0"  # Override agent image
    resources:
      requests:
        cpu: 10m
        memory: 16Mi
      limits:
        cpu: 100m
        memory: 64Mi
  apiKeyRef:
    name: my-secret
    key: apiKey
status:
  tunnelId: "tun_ghi012"
  publicUrl: "https://my-app-dev.tunnel.hookbase.app"
  connectionStatus: "configured"     # "configured", "connected", "disconnected"
  sidecarInjected: true
  conditions:
    - type: Ready
      status: "True"
  observedGeneration: 1
  lastSyncTime: "2026-02-17T12:00:00Z"

Pipeline Resources

WebhookTransform

Defines a transformation applied to webhook payloads.

apiVersion: hookbase.io/v1alpha1
kind: WebhookTransform
metadata:
  name: strip-headers
spec:
  name: Strip Headers
  slug: strip-headers
  description: "Remove sensitive headers before forwarding"
  transformType: jsonata             # "jsonata", "javascript", "mapping"
  code: |
    {
      "body": $,
      "timestamp": $now()
    }
  # OR load code from a ConfigMap:
  # codeFrom:
  #   configMapKeyRef:
  #     name: transforms
  #     key: strip-headers.jsonata
  inputFormat: json
  outputFormat: json
  apiKeyRef:
    name: my-secret
    key: apiKey
status:
  transformId: "tfm_jkl345"
  conditions:
    - type: Ready
      status: "True"

WebhookFilter

Defines conditions that determine which webhooks are routed.

apiVersion: hookbase.io/v1alpha1
kind: WebhookFilter
metadata:
  name: production-only
spec:
  name: Production Only
  slug: production-only
  description: "Only route production events"
  conditions:
    - field: headers.x-environment
      operator: equals
      value: "production"
    - field: body.action
      operator: in
      value: "created,updated"
  logic: AND                         # "AND" or "OR"
  apiKeyRef:
    name: my-secret
    key: apiKey
status:
  filterId: "flt_mno678"
  conditions:
    - type: Ready
      status: "True"

Supported operators: equals, not_equals, contains, not_contains, starts_with, ends_with, in, not_in, exists, not_exists, regex, gt, gte, lt, lte

WebhookSchema

Defines JSON Schema validation for incoming webhooks.

apiVersion: hookbase.io/v1alpha1
kind: WebhookSchema
metadata:
  name: order-schema
spec:
  name: Order Schema
  slug: order-schema
  description: "Validate order webhook payloads"
  jsonSchema: |
    {
      "type": "object",
      "required": ["order_id", "amount"],
      "properties": {
        "order_id": { "type": "string" },
        "amount": { "type": "number", "minimum": 0 }
      }
    }
  # OR load from ConfigMap:
  # jsonSchemaFrom:
  #   configMapKeyRef:
  #     name: schemas
  #     key: order.json
  apiKeyRef:
    name: my-secret
    key: apiKey
status:
  schemaId: "sch_pqr901"
  conditions:
    - type: Ready
      status: "True"

Infrastructure Resources

HookbaseCronJob

Defines a scheduled HTTP request managed by Hookbase.

apiVersion: hookbase.io/v1alpha1
kind: HookbaseCronJob
metadata:
  name: hourly-sync
spec:
  name: Hourly Sync
  description: "Sync data every hour"
  cronExpression: "0 * * * *"
  url: "https://api.example.com/sync"
  method: POST
  headers:
    Authorization: "Bearer token"
  payload: |
    {"action": "sync"}
  # OR load from ConfigMap:
  # payloadFrom:
  #   configMapKeyRef:
  #     name: payloads
  #     key: sync.json
  timezone: "UTC"
  timeoutMs: 30000
  isActive: true
  apiKeyRef:
    name: my-secret
    key: apiKey
status:
  cronJobId: "cron_stu234"
  lastRunAt: "2026-02-17T11:00:00Z"
  nextRunAt: "2026-02-17T12:00:00Z"
  conditions:
    - type: Ready
      status: "True"

HookbaseAPIKey

Provisions scoped API keys and stores them as Kubernetes Secrets.

apiVersion: hookbase.io/v1alpha1
kind: HookbaseAPIKey
metadata:
  name: team-key
  labels:
    hookbase.io/default: "true"      # Make this the default key for the namespace
spec:
  name: Team API Key
  scopes:
    - sources:read
    - sources:write
    - destinations:read
    - destinations:write
    - routes:read
    - routes:write
    - events:read
  expiresInDays: 90
  secretRef:                         # Where to store the raw API key
    name: hookbase-team-key
    key: apiKey
status:
  apiKeyId: "key_vwx567"
  keyPrefix: "whr_abc"
  expiresAt: "2026-05-17T00:00:00Z"
  conditions:
    - type: Ready
      status: "True"

Available scopes: sources:read, sources:write, destinations:read, destinations:write, routes:read, routes:write, events:read, events:write, tunnels:read, tunnels:write, cron:read, cron:write, api-keys:read, api-keys:write

HookbaseConfig

Cluster-scoped configuration for the operator.

apiVersion: hookbase.io/v1alpha1
kind: HookbaseConfig
metadata:
  name: hookbase-config              # Only one per cluster
spec:
  apiBaseUrl: "https://api.hookbase.app"
  defaultBootstrapAPIKeySecretRef:
    name: hookbase-bootstrap-key
    namespace: hookbase-system
    key: apiKey
  defaultAgentImage: "ghcr.io/hookbase/hookbase-agent:v0.1.0"
  namespaceSelector:                 # Limit which namespaces the operator watches
    matchLabels:
      hookbase.io/enabled: "true"
  defaultReconcileInterval: "5m"

Common Patterns

Shared Types

All CRDs that reference K8s Secrets use the SecretKeyRef type:

secretRef:
  name: secret-name     # K8s Secret name in the same namespace
  key: secret-key       # Key within the Secret (defaults to "apiKey")

Conditions

Every CRD status includes standard Kubernetes conditions:

ConditionMeaning
ReadyOverall resource health
SyncedLast successful sync with Hookbase API

Finalizers

All resources use the finalizer hookbase.io/finalizer. This ensures that when a CRD is deleted via kubectl delete, the corresponding API resource is also cleaned up.

Labels

LabelUsage
hookbase.io/default=trueMarks a HookbaseAPIKey as the default for its namespace
hookbase.io/tunnel={name}Applied to auth Secrets created by tunnel controller

See Also

  • Kubernetes Operator Guide -- installation and usage
  • Helm Chart Reference -- all Helm values
PreviousOperator GuideNextHelm Chart

On this page

Core ResourcesWebhookSourceWebhookDestinationWebhookRouteWebhookTunnelPipeline ResourcesWebhookTransformWebhookFilterWebhookSchemaInfrastructure ResourcesHookbaseCronJobHookbaseAPIKeyHookbaseConfigCommon PatternsShared TypesConditionsFinalizersLabelsSee Also