Bearer authentication, API key behavior, permissions, and common authorization errors.
Alfred authenticates API requests with bearer API keys and authorizes each route through principal permissions.
Authorization: Bearer <alfred-api-key>Missing, malformed, expired, revoked, or unknown keys return:
{
"error": "unauthorized",
"message": "Missing or invalid bearer token"
}with HTTP 401.
An authenticated principal without the required permission receives HTTP 403:
{
"error": "forbidden",
"message": "Missing required permission: workflows:add-domain"
}| Permission | Allows |
|---|---|
workflows:onboard-domain | Interact with onboard-domain. |
workflows:add-certificate | Interact with add-certificate. |
workflows:add-domain | Interact with add-domain. |
workflows:add-subdomain | Interact with add-subdomain. |
workflows:update-lambda-version | Interact with update-lambda-version. |
A workflow permission grants every supported client interaction for that workflow: submission, readback, cancellation, retry, recovery, and rollback. It also grants access to that workflow's execution events, stream records, and add-subdomain plan operations where applicable. Alfred exposes no manual pause operation; approval-driven waiting remains part of workflow orchestration.
Execution lists and SSE streams include only workflows the principal can currently access. Supplying a workflow filter never expands that access.
| Permission | Allows |
|---|---|
subscriptions:manage | Create and manage the principal's webhook subscriptions. |
principals:manage | Manage another principal's API keys and revoke keys. |
audit:read | Query authorization decisions. |
admin:read | Inspect event-version usage and the configured Workflow Admin proxy. |
admin:write | Archive an eligible deprecated event version after confirmation. |
Operators grant workflow permissions by assigning roles in Alfred's persisted RBAC store. API clients and Slack users cannot grant themselves roles or permissions. The client API intentionally has no RBAC administration routes.
Slack uses the same permission names against the immutable
slack:<workspace-id>:<user-id> principal. Membership in the configured
workflow-operator group can supplement these permissions for Slack interactions
only; it does not change bearer API permissions.
API key creation returns plaintext exactly once:
curl --fail-with-body --silent --show-error \
-X POST "$ALFRED_API_URL/v1/principals/$PRINCIPAL_ID/api-keys" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jqStore apiKey.plaintextToken in a secret manager. List responses expose only
metadata and a display prefix. A principal may list or mint its own keys;
principals:manage is required for another principal.
Revoke a key by ID:
curl --fail-with-body --silent --show-error \
-X DELETE "$ALFRED_API_URL/v1/api-keys/$API_KEY_ID" \
-H "Authorization: Bearer $ADMIN_API_KEY"Revocation requires principals:manage and is immediate for subsequent
authentication.
Stream tokens are not general API credentials. They: