> Production API availability: use /api/v1/help?view=guides and the resource operations catalog before following a recipe. Some localhost capabilities are not deployed yet; an absent operation is unavailable.
What this module owns
Campaign drafts, lists, audiences, recipient rendering and preference handling. Preparing content is separate from sending mail.
Prepare without sending
Read campaign lists, then compose a draft campaign and inspect recipient rendering. generate-recap builds content. sync-audience and list sync change audience records. Neither a rendered message nor an audience snapshot is delivery evidence.
Use returned campaign IDs and inspect the handler fields below. Preference and unsubscribe URLs use recipient tokens, not an administrator’s API credential; do not publish those tokens as examples. Email sending needs explicit task authorization and its own delivery checks.
First read
Use API_URL with /api/v1, for example http://localhost/api/v1. Set API_KEY privately. Replace any resource placeholder with an ID returned by discovery.
curl --fail-with-body "$API_URL/mail-campaigns" \
-H "Authorization: Bearer $API_KEY"Registered agent routes
The entries below are extracted from the current route and handler source. Scope tokens can represent alternatives or different method branches, not a requirement to grant every listed scope. Body fields are observed inputs, not a complete required-field schema. Follow the resource guide and the deployed validation response for a write.
/api/v1/mail-campaigns
Intended request methods: GET, POST. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, databoard:write, forms:read, forms:write, mail_campaign:read, mail_campaign:write
Observed JSON fields: audiences, auto_generate, campaign_type, content_html, content_text, databoard_id, domain, generate_recap, group_id, items, list_id, metadata, preheader, scheduled_at, snapshot_audience, status, subject, sync_audience, title, website_id.
Selected rejection messages:
- title is required
- group_id is not writable by API key user
- list_id is not owned by API key user
- list_id does not belong to group_id
- Campaign save failed
/api/v1/mail-campaign-lists
Intended request methods: GET, POST. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, databoard:write, forms:read, forms:write, mail_campaign:read, mail_campaign:write
Observed JSON fields: description, domains, form_hashes, group_id, metadata, name, sync_from_forms, upsert.
Selected rejection messages:
- group_id is required
- group_id is not writable by API key user
- List save failed
/api/v1/mail-campaign-lists/{id}
Intended request methods: DELETE, GET, PATCH, POST, PUT. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, databoard:write, forms:read, forms:write, mail_campaign:read, mail_campaign:write
Observed JSON fields: description, metadata, name, status.
Selected rejection messages:
- Mail campaign list not found
- List update failed
/api/v1/mail-campaign-lists/{id}/members
Intended request methods: GET. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, forms:read, mail_campaign:read
Selected rejection messages:
- Mail campaign list not found
/api/v1/mail-campaign-lists/{id}/sync
Intended request methods: POST. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:write, forms:write, mail_campaign:write
Observed JSON fields: domains, form_hashes.
Selected rejection messages:
- Mail campaign list not found
/api/v1/mail-campaigns/{id}
Intended request methods: DELETE, GET, PATCH, POST, PUT. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, databoard:write, forms:read, forms:write, mail_campaign:read, mail_campaign:write
Observed JSON fields: audiences, campaign_type, content_html, content_text, databoard_id, domain, group_id, items, list_id, metadata, preheader, scheduled_at, status, subject, title, website_id.
Selected rejection messages:
- Mail campaign not found
- title is required
- group_id is not writable by API key user
- list_id is not owned by API key user
- list_id does not belong to group_id
- Campaign save failed
/api/v1/mail-campaigns/{id}/generate-recap
Intended request methods: POST. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:write, forms:write, mail_campaign:write
Selected rejection messages:
- Mail campaign not found
/api/v1/mail-campaigns/{id}/sync-audience
Intended request methods: POST. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:write, forms:write, mail_campaign:write
Selected rejection messages:
- Mail campaign not found
/api/v1/mail-campaigns/{id}/recipients
Intended request methods: GET. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, forms:read, mail_campaign:read
Selected rejection messages:
- Mail campaign not found
/api/v1/mail-campaigns/{id}/recipients/{rid}/render
Intended request methods: GET. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: databoard:read, forms:read, mail_campaign:read
Selected rejection messages:
- Mail campaign not found
- Recipient not found
/api/v1/mail/unsubscribe/{token}
Intended request methods: GET. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: No per-user scope token was extracted; inspect the service/token or discovery authorization before calling.
Selected rejection messages:
- Invalid unsubscribe token
/api/v1/mail/preferences/{token}
Intended request methods: GET, POST. Confirm allowed_methods and method_evidence in the deployed operations catalog; documented methods do not grant access.
Scope tokens in the implementation: No per-user scope token was extracted; inspect the service/token or discovery authorization before calling.
Observed JSON fields: every_post, product_updates, unsubscribe_all, weekly_recap.
Selected rejection messages:
- Invalid preferences token
Access boundary
External agents use only the versioned operations documented above and returned by the deployed catalog. Browser actions and internal controllers are not substitutes for missing API operations.
Verification before automation
Read back the owned record after a write. On a dedicated local fixture, test missing input, wrong owner, missing scope and stale revisions where supported. Confirm the request did not change state when rejected. Check the generated projection separately from the source record. Never replay sends, payments or deletion requests merely to test connectivity.
See API validation and remaining gaps for the shared test strategy.
HTTP discovery and safety contract
Read GET /api/v1/help?view=guide&resource=mail-campaigns for this module's machine-readable guidance. Discover supported operations through its discovery_url when present. A null discovery_url means no direct resource API is documented; related endpoints, when provided, have their own ownership and scope requirements.
Use GET /api/v1/me with your key to confirm identity and scopes. Only request methods and fields supported by this deployment. The shared transport boundary rejects unsupported methods and malformed JSON on covered routes, but field schemas and revision checks remain resource-specific. Notes and Carousels expose typed save schemas and payload-only validation; other modules must not be assumed to share that contract.
Create, update, replace, patch, delete, send and publish are distinct capabilities. An operation absent from the returned catalog is unavailable, not permission to guess a URL. Read back after writes; after a timeout inspect the result before retrying. Never automatically replay a payment, message, deployment or deletion.