Supported workflow triggers, request behavior, permissions, and durable stages.
All workflow routes use:
POST /v1/workflows/{workflow}and require:
Authorization: Bearer <api-key>
Content-Type: application/json
Idempotency-Key: <caller-generated-delivery-key>| Workflow | Permission | Concurrency | Stages |
|---|---|---|---|
onboard-domain | workflows:onboard-domain | Global aws-infrastructure lane; Maps recovery uses google-maps-api-keys | registration, planning, creation, CloudFront setup, ELB linking, platform routing, finalization, Google Maps whitelisting, completion |
add-certificate | workflows:add-certificate | Global aws-infrastructure lane | planning, creation, CloudFront setup, ELB linking, platform routing, finalization |
add-domain | workflows:add-domain | Global aws-infrastructure lane | registration |
add-subdomain | workflows:add-subdomain | Per execution | planning, approval, Route53 |
update-lambda-version | workflows:update-lambda-version | Per target and environment | planning, update, deployment observation, finalization |
The Slack launcher exposes unified onboard-domain, add-subdomain,
update-lambda-version, and execution lookup. add-domain and
add-certificate remain supported API and internal workflow surfaces. The
permission named for a workflow grants submission plus every supported
execution interaction for that workflow. See
Service Capabilities for contract boundaries
and configuration-gated surfaces.
The first accepted submission returns HTTP 202:
{
"estimatedDurationSeconds": 1800,
"executionId": "exec_...",
"links": {
"cancel": "/v1/executions/exec_.../cancel",
"events": "/v1/executions/exec_.../events",
"self": "/v1/executions/exec_..."
},
"stages": [
"stage-1-registration",
"stage-1-planning",
"stage-2-creation",
"stage-3-cloudfront-setup",
"stage-4-elb-linking",
"stage-5-platform-routing",
"stage-6-finalization",
"stage-7-google-maps-whitelisting",
"stage-8-completion"
],
"status": "queued",
"workflow": "onboard-domain"
}A completed idempotent replay returns HTTP 200 and the
Idempotent-Replay: true header. An equivalent logical request may reuse an
execution even when the delivery key is new.
| Field | Type | Required | Behavior |
|---|---|---|---|
domainString | comma-separated domain string | Yes | Removes spaces, lowercases domains, and rejects duplicates or invalid names. |
isKirby | boolean | No | Defaults to true; selects Kirby routing behavior when true. |
ticketId | comma-separated positive decimal IDs | No | Normalized and deduplicated for Zendesk completion. |
recentCertOverrideDomain | domain or null | No | Requests a specific recent certificate candidate, subject to validation. |
options.dryRun | boolean | No | Defaults to false; computes workflow behavior without provider mutation. |
options.skipReadinessCheck | boolean | No | Defaults to false; bypasses provider readiness probes when true. |
Certificate groups are capped at 30 SAN entries. Alfred selects an issued, in-use certificate with capacity for both the requested domain and wildcard. An invalid explicit override is rejected in favor of a safe alternative. When no safe candidate exists, the workflow plans a new certificate.
{
"domainString": "example.com"
}Send a bare root/apex domain such as example.com. Do not send a URL such as
https://example.com/path, a wildcard such as *.example.com, or a hostname
with a leading www such as www.example.com.
The request schema only checks that domainString is non-empty. Alfred trims
and lowercases it while creating the canonical execution input, but this is not
domain-shape or ownership validation. The workflow's GoDaddy lookup is the
authoritative check that the domain belongs to the configured GoDaddy account
and is ACTIVE; the workflow stops before Route53 or nameserver mutations when
that check fails.
POST /v1/workflows/onboard-domain accepts one primary domain and the
certificate options used by the standalone certificate workflow:
{
"domain": "example.com",
"options": {
"dryRun": false,
"skipReadinessCheck": false
},
"recentCertOverrideDomain": null,
"ticketId": "12345,67890"
}domain is trimmed and lowercased and must contain exactly one DNS name. The
schema rejects URLs, paths, wildcards, comma-separated names, and malformed DNS
names. Alfred derives the certificate domain from that single primary domain;
callers cannot provide a second certificate-domain field. Zendesk ticket IDs
are normalized and deduplicated.
The workflow records registration before certificate state. An active domain and existing hosted zone are recorded as already registered and onboarding continues. A registration failure stops all certificate mutations.
After infrastructure finalization, Alfred adds
https://<domain>/* and https://*.<domain>/* to every configured Kirby and
Zapdos Google Maps browser key. The complete key set is preflighted before any
write. Each key is limited to 1,200 referrers, equivalent to 600 roots with
this two-referrer rule; Alfred warns below 50 remaining roots and does not
shard keys. A manual Maps outcome leaves infrastructure successful and Zendesk
open for the Maps-only retry.
When onboarding needs a new CloudFront distribution, Alfred calls
CreateDistributionWithTags. The runtime IAM principal must allow both
cloudfront:CreateDistribution and cloudfront:TagResource; denying the tag
action causes the CloudFront stage to fail before a distribution is created.
The MicroBrands baseline also attaches its configured WAF ACL, so the principal
must allow wafv2:GetWebACL for that ACL ARN. This read permission lets
CloudFront validate the association; it does not allow Alfred to change WAF
rules.
{
"rootDomain": "example.com",
"subdomains": ["blog", "offers.eu"]
}rootDomain is normalized to a lowercase DNS name. subdomains contains 1–10
submitted relative labels; labels are normalized and deduplicated in their
first-seen order. Wildcards, malformed labels, and complete hostnames ending
in the root domain are rejected. For example, subdomains: ["blog"] is valid,
while subdomains: ["blog.example.com"] is not: Alfred appends each relative
label to rootDomain. The workflow mirrors the root domain's apex Route53
A-alias and does not change certificates, CDN, or platform routing.
GET /v1/executions/{executionId} includes outcome for
onboard-domain executions. The normalized outcome is derived from persisted
execution and stage data and contains:
| Section | Contents |
|---|---|
domain | Primary domain and registered, already-registered, not-registered, or unknown state. |
certificate | Primary domain, full ARN, compact certificate ID, and created, adopted, not-created, or unknown state. |
distributions | Kirby and nginx distribution IDs with created, updated, adopted, not-created, or unknown state. |
cleanup | Cleanup state, manual action, old certificate ARN, and remaining attachments when available. |
zendesk | Ticket ID, intended action, and update state. |
googleMaps | Per-key safe display name and state, aggregate outcome, and minimum remaining root-domain capacity when known. |
assistance | Deduplicated structured reasons with platform or requester audience. |
| top level | Execution ID, execution status, and Workflow SDK run ID when available. |
Missing or malformed persisted data produces explicit not-created,
not-reached, or unknown values. Alfred does not infer artifacts or
assistance from log or error text.
Platform assistance is present only for explicit structured infrastructure
manual-required signals. Failed Zendesk completion or correction produces a
requester assistance reason containing the ticket ID and intended action.
Generic workflow failure does not imply Platform assistance.
Google Maps capacity, authentication, runtime, or provider failures create a
requester assistance reason without exposing key resource names. A succeeded
onboarding with a manual Maps outcome can call
POST /v1/executions/{id}/retry-maps-whitelist; the command reruns only Maps
whitelisting and completion.
| Status | Error | Meaning |
|---|---|---|
400 | missing_idempotency_key | Idempotency-Key was omitted. |
400 | invalid_json | Request body is not valid JSON. |
400 | validation_error | The workflow's Zod schema rejected the body. |
401 | unauthorized | Bearer token is missing or invalid. |
403 | forbidden | Principal lacks a required permission. |
409 | idempotency_conflict | The key was previously used for a different request. |
Use the generated API reference for complete request schemas and examples.
POST /v1/workflows/update-lambda-version changes the numbered Lambda@Edge
version on an approved CloudFront fleet. The request body is:
{
"environment": "test",
"options": { "dryRun": false },
"target": "microbrands",
"version": 43
}version must be a positive whole number. Alfred resolves the corresponding
published Lambda version in us-east-1 and requires it to be active with a
successful last update. $LATEST, aliases, zero, negative numbers, and
fractions are rejected.
The supported matrix is:
| Target | Environment | Lambda function | Fleet selector | Behavior scope |
|---|---|---|---|---|
headout | production | uuid-assigner | The single enabled distribution with alias headout.com | Default and eligible ordered behaviors |
headout | test | uuid-assigner-test | The single enabled distribution with alias *.test-headout.com | Default and eligible ordered behaviors |
microbrands | production | uuid-assigner | Default cache policy 1e6fcb00-882b-40a4-813a-21d5f61b6142; aliases contain no test hostname | Default behavior only |
microbrands | test | uuid-assigner-test | The same cache policy; every alias is test-headout.com or a subdomain of it | Default behavior only |
microbrands-booking-flow | production | uuid-assigner | Default cache policy 292abe6a-03d5-4730-86ec-f265f4ef61f9 | Default behavior only |
microbrands-booking-flow has no test environment. For the cache-policy-selected
MicroBrands and MicroBrands Booking Flow fleets, a distribution containing both
production and test aliases is rejected. kirby.headout.com is denied even if
it otherwise matches a selector.
For Headout, Alfred excludes an ordered behavior when its path pattern contains
api, assets, or _next, case-insensitively. For both MicroBrands targets,
every ordered behavior is outside the update scope. Alfred updates only
existing, numbered uuid-assigner or uuid-assigner-test associations that
were frozen into the plan. It can repair an environment-function mismatch, but
does not attach or detach Lambda functions, add or remove associations, change
event types or IncludeBody, or modify any other CloudFront field.
Set options.dryRun to true to resolve the Lambda, discover the fleet, and
produce the plan without preparing or submitting a CloudFront write. The
default is false.
Planning freezes distribution IDs, aliases, behavior membership, association
identity, and the plan hash before mutation. Different target/environment
lanes can run concurrently. A different version in an active lane returns
409 active_target_conflict and links the existing execution.
CloudFront submissions run in bounded batches. Cancellation stops future submissions, but Alfred continues observing updates CloudFront already accepted. A failed or canceled execution can retry only unfinished distributions; persisted planning, receipts, and completed peers are reused. After a terminal execution has durable receipts, rollback restores the exact before-ARNs. Restoration fails closed if the receipt target has drifted instead of overwriting an unexpected change.
Synchronous trigger errors include the common errors above plus:
| Status | Error | Meaning |
|---|---|---|
400 | invalid_environment | The target/environment pair is unsupported. |
409 | active_target_conflict | Another version owns the same target/environment lane. |
409 | reservation_replay_pending | An equivalent reservation exists but is not yet linked to an execution. |
Provider planning and mutation run asynchronously. Read the execution and its events for these stable failure codes:
| Error | Meaning |
|---|---|
lambda_version_not_found | The exact active published version was not resolved. |
ambiguous_fleet | Discovery matched an unsafe or denied fleet. |
mixed_environment_aliases | A cache-policy-selected MicroBrands distribution mixes production and test aliases, or MicroBrands Booking Flow contains a test distribution. |
empty_fleet | No eligible distribution matched. |
plan_stale | The reviewed fleet, association membership, or plan hash changed. |
provider_failure | A CloudFront or Lambda provider operation failed. |
The API runtime needs CloudFront permission to list distributions, list by
cache policy, get distributions and their configuration, update distributions,
and read deployment status. In IAM action names, these are
cloudfront:ListDistributions,
cloudfront:ListDistributionsByCachePolicyId,
cloudfront:GetDistribution, cloudfront:GetDistributionConfig, and
cloudfront:UpdateDistribution. It also needs
lambda:ListVersionsByFunction and lambda:GetFunctionConfiguration for
numbered uuid-assigner and uuid-assigner-test versions in us-east-1.