Skip to main content
PUT
Create or update a notification channel

Authorizations

Authorization
string
header
required

A Barndoor API key, sent as Authorization: Bearer <key>. Keys are prefixed bdai_ and are opaque — do not attempt to decode one. Interchangeable with an OAuth 2.0 access token.

Body

application/json

Create or update one notification channel and replace its subscription set.

This is a full upsert, not a patch: subscriptions is replaced by what you send, so omitting it removes every subscription the channel had. Send the complete desired set on every call — which is what makes the endpoint safe to drive from a declarative tool.

Which fields are permitted depends on type; sending one that does not belong to the type is a 422, not a silently ignored field. See ChannelType for the full matrix.

Identity. Without id the channel is keyed on its type's natural identity, so repeating the same call is idempotent rather than creating duplicates: personal types by (organization, type, caller), email by (organization, email_address), webhook by (organization, url), slack by (organization, slack_channel_id). With id it is an authoritative edit of that row — the only way to change a teams channel, whose natural identity is a secret URL you never hold back.

type
enum<string>
required

The kind of destination, and the discriminator for every other field. Immutable in practice: an edit-by-id that changes type is rejected, and an upsert without id and a different type addresses a different natural identity, so it creates a separate channel.

Available options:
in_app,
user_email,
email,
webhook,
slack,
teams
id
string<uuid> | null

Existing channel to edit authoritatively. Omit to create-or-dedup on the type's natural identity (see the model description). When supplied and unknown — or owned by another organization — the request is a 404, never a create.

enabled
boolean
default:true

Whether the channel delivers. false suspends delivery while keeping the channel and its subscriptions intact — the reversible alternative to deleting it.

email_address
string | null

Destination address for type: email. Any deliverable address — a team alias or a ticketing inbox, not necessarily a platform user. Validated and normalized; also the channel's natural identity, so reusing an address updates that channel. Forbidden on every other type.

url
string | null

Destination endpoint for type: webhook. Must be https and must resolve to a public address — private, loopback, link-local, and cloud-metadata targets are rejected with a 422 naming the reason. Also the channel's natural identity. Forbidden on every other type.

Example:

"https://hooks.example.com/barndoor"

label
string | null

Human-readable name, shown wherever the channel is listed. Required for slack and teams (for teams it is the only non-secret identifier you get back). Forbidden on the other types.

Example:

"#security-alerts"

slack_channel_id
string | null

Slack channel id (not its name) for type: slack; the organization's Slack app must already be installed. Also the channel's natural identity. Forbidden on every other type.

Example:

"C0123456789"

teams_workflow_url
string | null

Microsoft Teams Workflows incoming-webhook URL for type: teams. Write-only: it is stored as a secret and never returned by any endpoint — reads expose only has_workflow_url. Required on create, optional on edit-by-id (omit to keep the stored URL). Must be https, resolve to a public address, and sit on the Power Automate host allowlist. Forbidden on every other type.

subscriptions
ChannelSubscriptionInput · object[]

The complete set of alert types to deliver to this channel. Replaces the channel's existing set — an omitted or empty list unsubscribes it from everything. At most one entry per alert type; duplicates are a 422.

Response

Successful Response

A channel and its subscriptions. Secrets (webhook signing secret, slack bot token) live in OpenBao and are never surfaced here except as a one-time reveal via signing_secret, populated only on the response to the request that just generated it (webhook create or regenerate); slack channels expose only the non-secret label + slack_channel_id.

id
string<uuid>
required

Server-assigned channel id. Stable across updates; pass it as id to edit by id.

type
enum<string>
required

The kind of destination. See ChannelType.

Available options:
in_app,
user_email,
email,
webhook,
slack,
teams
enabled
boolean
required

Whether the channel currently delivers.

user_id
string<uuid> | null
required

Owning user for a personal channel (in_app, user_email). null for the org-wide types, which belong to the organization rather than one user.

email_address
string | null
required

Destination address for type: email, normalized. null for every other type.

url
string | null
required

Destination endpoint for type: webhook. null for every other type.

label
string | null
required

Human-readable name, set for slack and teams. null for the other types.

slack_channel_id
string | null
required

Slack channel id for type: slack. null for every other type.

subscriptions
ChannelSubscription · object[]
required

The alert types this channel currently delivers. Empty means it delivers nothing.

created_at
string<date-time>
required

When the channel was created (UTC).

updated_at
string<date-time>
required

When the channel or its subscriptions last changed (UTC).

has_signing_secret
boolean
default:false

Whether a webhook channel has a stored signing secret — always true for a webhook channel, false otherwise. The secret itself is never readable back; use POST /channels/{channel_id}/regenerate-secret to obtain a fresh one.

has_workflow_url
boolean
default:false

Whether a teams channel has a stored Workflows URL. The URL is a secret and is never returned; this flag is the only readable signal that one is configured.

signing_secret
string | null

One-time reveal of a newly generated webhook signing secret. Present only on the response to the request that created it — the PUT that first creates a webhook channel — and null on every list or subsequent read. Store it when you receive it; the only way to recover from losing it is to rotate.