HTTP Sink
Forwards CDEvents to an external HTTP endpoint via POST request. Use for webhooks, external APIs, notification services, and any HTTP-based system that accepts JSON events.
Configuration
[sinks.webhook]
enabled = true
type = "http"
destination = "https://example.com/webhook"Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | — | Must be "http" |
destination | string | — | Destination endpoint URL |
enabled | boolean | true | Enable/disable this sink |
headers | table | {} | Outgoing request headers (auth, signatures, etc.) |
trusted_redirect_hosts | array | [] | Glob patterns (e.g. "*.example.com") of hosts a cross-origin redirect may reach while keeping headers. See Redirects |
total_duration_of_retries | duration | "30m" | Retry budget for transient failures (network errors, 5xx) |
log_errors | boolean | true | Log a warning on non-2xx responses |
log_full_response_on_error | boolean | false | Also log response headers and body on non-2xx (handy in CI) |
user_agent | string | cdviz-collector/<version> | User-Agent header |
transformer_refs | array | [] | (beta) Transformers applied to events before this sink sends them |
Request Format
- Method:
POST - Content-Type:
application/json - Body: Complete CDEvent serialized as JSON
- Errors: Failed requests (HTTP 3xx+ or network errors) are logged; processing continues
Redirects
Redirects are followed, but configured headers (tokens, API keys, signatures) are dropped on a cross-origin redirect so credentials never leak to another server. To keep them for a known host (e.g. an API redirecting to its own CDN), allowlist it:
[sinks.webhook]
trusted_redirect_hosts = ["*.example.com"]An https → http downgrade is never trusted.
Authentication
Bearer token
[sinks.webhook.headers]
"authorization" = { type = "secret", value = "Bearer your-api-token" }API key (secret value)
Keep the secret out of the config file. Use the _file suffix to read it from a mounted file:
[sinks.webhook.headers]
"x-api-key" = { type = "secret", value_file = "/run/secrets/api_key" }Or set it at runtime. Keep the hyphens in header names (see Configuration: Environment Variables):
# Preferred: --set flag handles hyphens cleanly
cdviz-collector connect --config config.toml \
--set 'sinks.webhook.headers."x-api-key".value = "actual-api-key"'
# Or via env wrapper (bash cannot export names with hyphens directly):
env 'CDVIZ_COLLECTOR__SINKS__WEBHOOK__HEADERS__X-API-KEY__VALUE=actual-api-key' \
cdviz-collector connect --config config.tomlKubernetes env[].name and GitHub Actions env: support hyphens natively.
HMAC signature (for webhook receivers that verify signatures)
[sinks.webhook.headers]
"x-hub-signature-256" = { type = "signature", token_file = "/run/secrets/hmac_secret", signature_prefix = "sha256=", signature_on = "body", signature_encoding = "hex" }→ Complete Header Authentication Guide
Transformers beta
The HTTP sink accepts transformer_refs: a chain of transformers applied to events just before this sink sends them, without affecting other sinks. Two main uses:
- Filter which events are sent: a transformer that outputs an empty list (
[]) drops the event for this sink only - Reshape the body into the JSON the destination expects. The output does not have to be a CDEvent
Reshaping lets the destination consume the payload as-is, and can replace an intermediate service whose only job is translating events 1-to-1 into another system's API call. For example, instead of routing through an Argo Workflows template that only converts the event into a GitHub repository_dispatch call, a sink transformer can build that payload and the sink posts it to the GitHub API directly:
[sinks.github_dispatch]
enabled = true
type = "http"
destination = "https://api.github.com/repos/my-org/my-repo/dispatches"
transformer_refs = ["service_deployed_to_dispatch"]
[sinks.github_dispatch.headers]
"authorization" = { type = "secret", value = "Bearer GITHUB_TOKEN" }
"accept" = { type = "static", value = "application/vnd.github+json" }
[transformers.service_deployed_to_dispatch]
type = "vrl"
template = '''
if !contains(string!(.body.context.type), "service.deployed") {
[] # drop: this sink only reacts to deployments
} else {
.body = {
"event_type": "test-deployed-service",
"client_payload": {
"artifactId": .body.subject.content.artifactId,
"environment": .body.subject.content.environment.id,
},
}
[.]
}
'''Common Use Cases
# Slack notification on deployment
[sinks.slack]
enabled = true
type = "http"
destination = "https://hooks.slack.com/services/T00/B00/XXX"
# Forward to authenticated internal API
[sinks.internal_api]
enabled = true
type = "http"
destination = "https://platform.company.com/api/events"
[sinks.internal_api.headers]
"authorization" = { type = "secret", value = "Bearer PLATFORM_API_TOKEN" }
# Fan-out: multiple HTTP sinks all receive every event
[sinks.backup_receiver]
enabled = true
type = "http"
destination = "https://backup-collector.company.com/webhook/events"Error Handling
Transient failures (network errors, timeouts, 5xx) are retried with exponential backoff for up to total_duration_of_retries. Once the budget is exhausted, or on a non-retryable response, the failure is logged and processing continues. The event is not stored for later. For guaranteed delivery, use the Kafka sink or NATS sink with a durable consumer.
Related
- Kafka Sink: durable, high-throughput event delivery
- NATS Sink: lightweight publish-subscribe delivery
- Header Authentication: configure outgoing request headers
- Database Sink: store CDEvents for analytics and dashboards