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
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.
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:
| Condition | Meaning |
|---|---|
Ready | Overall resource health |
Synced | Last 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
| Label | Usage |
|---|---|
hookbase.io/default=true | Marks 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