Authentication and scope
Every endpoint requires an authenticated session and workspace context. A workspace-scoped channel is managed byADMIN or OWNER. A personal channel
is managed only by its owner. Channel-side agent pairing uses the same rule.
Template endpoints are workspace-wide and require ADMIN or OWNER.
Secrets and destination addresses are not returned by the agent-pairing API.
Agent access is default-deny: an agent can send only after a human grants the
specific (channel, agent) pairing.
All routes require authentication and workspace context. Missing workspace
context is 400; no authenticated user is 401; a non-member is 403.
Handler/database failures are 500 unless a route below specifies another
status.
Channel contracts
GET /api/v1/notification-channels
Returns 200 OK with an object containing a channels array. The default
scope includes all workspace channels and the authenticated user’s personal
channels. ?scope=all is an admin overview that also includes other members’
personal channels, but redacts their destination fields. Secrets are never
returned.
POST /api/v1/notification-channels
Creates a channel and returns 201 Created. Workspace channels require
ADMIN or OWNER; personal: true lets any member create a channel owned by
the authenticated user. The server ignores any client-supplied owner.
type is email, webhook, or shoutrrr. Email uses to; shoutrrr uses
provider plus provider-specific fields (or the compatibility
shoutrrr_url). events defaults to ["run.failed"] and accepts
completed, failed, or all; an empty categories list means every
category; min_priority defaults to low. The response includes secret
only on this create response. For a webhook it is the HMAC secret; for
shoutrrr it is the composed service URL.
PATCH /api/v1/notification-channels/{id}
Auth: authenticated workspace member; workspace channels require ADMIN
or OWNER, personal channels require their owner.
Updates only supplied settings and returns 200 OK with
{ "updated": "nch_01..." }. Optional fields are enabled (boolean),
categories (array; empty means every category), min_priority (low,
medium, high, or urgent), and events (legacy completed, failed, or
all). Workspace channels require ADMIN or OWNER; personal channels
require their owner. Invalid input is 400; an unavailable channel is 404.
POST /api/v1/notification-channels/{id}/test
Sends a synthetic run.completed event and returns 200 OK with
{ "ok": true, "channel_id": "nch_01..." }. A delivery failure returns
502; authorization follows the PATCH rule.
DELETE /api/v1/notification-channels/{id}
Deletes the channel and returns 200 OK with { "deleted": "nch_01..." }.
Missing or unauthorized channels return 404 or 403 respectively.
POST /api/v1/notification-channels/test
Auth: authenticated workspace member with workspace context.
Tests an unsaved draft without persisting it. The body accepts the delivery
fields needed to compose a channel (type, url/to, or provider plus
fields, with optional secret) and the response is 200 OK with
{ "ok": true }. Invalid drafts return 400; a provider or mailer failure
returns 502.
type must be email, webhook, or shoutrrr. Email drafts require to,
webhook drafts require url, and shoutrrr drafts require a known provider and
all provider fields (or a composed shoutrrr_url).
Agent pairing
GET /api/v1/notification-channels/{id}/agents
Auth: authenticated workspace member; channel access follows the channel
owner/manage permission.
Lists agents allowed to send to the channel.
POST /api/v1/notification-channels/{id}/agents
Auth: authenticated workspace member with manage permission for the
channel (ADMIN/OWNER for workspace channels, owner for personal channels).
Allows an agent from the current workspace to send to the channel.
Request:
DELETE /api/v1/notification-channels/{id}/agents/{agentId}
Revokes the pairing. Response:
404 when the agent was not paired with the channel.
Invalid path or JSON input is 400; an unauthorized personal channel is
403; a pairing-store failure is 500.
Provider registry
GET /api/v1/notification-providers
Auth: any authenticated workspace member. Request: no body.
Response: 200 OK:
500.
PATCH /api/v1/notification-providers/{provider}
Auth: instance administrator; the switch applies to every workspace, so a
workspace ADMIN or OWNER role is not enough (403). Request: JSON
{ "enabled": true }. Response: 200 OK with
{ "provider": "slack", "enabled": true }. Unknown providers return 404;
invalid JSON returns 400; a settings write failure returns 500. Switching
a provider off blocks new channels and stops delivery through the ones that
exist; they are not deleted.
Notification templates
Templates change the wording of notifications generated by Crewship. They do not rewrite text authored by a routinenotify step or by an agent.
GET /api/v1/notification-templates
Lists workspace overrides. An empty channel_id applies to every channel.
ADMIN or OWNER. Request: no body. Response: 200 OK
with { "templates": [...] }; 400 when workspace context is missing, 401
without authentication, 403 for a non-member or insufficient role, and
500 for the template query.
PUT /api/v1/notification-templates
Creates or replaces one category/channel override.
200 OK. Empty title and body remove the
override. Categories and template references are validated on write; invalid
input returns 400.
Auth: ADMIN or OWNER. Request: JSON { "category", "channel_id", "title", "body" }. Response: 200 OK with the saved template;
400 for invalid JSON, category, or template reference; 401 without
authentication; 403 for a non-member or insufficient role; and 500 for a
persistence failure.
Supported references are {{ vars.<fact> }}, {{ source.title }},
{{ source.body }}, {{ source.category }}, and {{ source.kind }}. Missing
facts render as empty; if a rendered title or body is empty, Crewship keeps the
producer’s original wording.
DELETE /api/v1/notification-templates
Removes an override. category is required; channel_id is optional.
204 No Content. Deleting an override that does not exist is
intentionally idempotent.
Auth: ADMIN or OWNER. Request: required category and optional
channel_id query parameters; no body. Statuses: 204 No Content, 400
when category or workspace context is missing, 401 without authentication,
403 for a non-member or insufficient role, or 500 for a delete failure.
Delivery log
GET /api/v1/notification-deliveries
Lists outbound delivery attempts for the current workspace. This endpoint is
restricted to ADMIN and OWNER because the log spans every recipient.
Response:
error is omitted when there is no recorded error. The result is ordered
newest first and is always an object containing a deliveries array, including
when no rows match.