Skip to content

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.

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

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

WebhookRoute

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

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

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

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

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

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

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

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

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

yaml
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

Released under the MIT License.