Public integration API
Galassify Broadcast 0.20.0rc1. Download OpenAPI JSON
Integrate a signup form
- Fetch
GET /api/v1/public/organisations/{slug}and its subjects. Show the organisation's descriptions and opt-in setting. - Default to all returned subjects. Omit
subject_idsto select all current subjects; an empty array is allowed only when the organisation has none. - POST JSON with
email, optional names and choices to/api/v1/public/organisations/{slug}/subscriptions. Usecredentials: "omit". No administrator cookie or API key. - Show the generic 202 message exactly as returned. It confirms processing, not membership, activation or inbox delivery.
- Display 422 field errors, respect 429 Retry-After, explain disabled signup on 409 and allow retry on 503. Never infer whether an address already exists.
Your exact website origin must be configured in the organisation's allowlist. CORS has no wildcard or credentials. The central preferences request is same-origin; link visitors to the hosted preferences portal.
One association uses organisation SMTP; multiple associations use one neutral central email and one scoped link, including disabled associations. Missing transport gives the same public response, with no fallback. Only preferences mail bypasses disabled status. Confirmation and resubscription require explicit capability actions.
Operations
GET /assets/{storage_key} — Public Image
Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.
Scope: public/capability
Parameters
storage_key(path, required)
{
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"operationId": "public_image_assets__storage_key__get",
"parameters": [
{
"in": "path",
"name": "storage_key",
"required": true,
"schema": {
"format": "uuid",
"title": "Storage Key",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"image/*": {
"schema": {
"format": "binary",
"type": "string"
}
}
},
"description": "Public image or unsubscribe confirmation."
},
"403": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Public Image",
"tags": [
"Assets"
],
"x-required-role": "public/capability"
}GET /api/v1/public/organisations/{slug} — Organisation
Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.
Scope: public/capability
Parameters
slug(path, required)
{
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.",
"operationId": "organisation_api_v1_public_organisations__slug__get",
"parameters": [
{
"in": "path",
"name": "slug",
"required": true,
"schema": {
"title": "Slug",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPublicOrganisation"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Organisation",
"tags": [
"Signup"
],
"x-required-role": "public/capability"
}GET /api/v1/public/organisations/{slug}/subjects — Subjects
Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.
Scope: public/capability
Parameters
slug(path, required)
{
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.",
"operationId": "subjects_api_v1_public_organisations__slug__subjects_get",
"parameters": [
{
"in": "path",
"name": "slug",
"required": true,
"schema": {
"title": "Slug",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultSubjects"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Subjects",
"tags": [
"Signup"
],
"x-required-role": "public/capability"
}POST /api/v1/public/organisations/{slug}/subscriptions — Subscribe
Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.
Scope: public/capability
Parameters
slug(path, required)
{
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.",
"operationId": "subscribe_api_v1_public_organisations__slug__subscriptions_post",
"parameters": [
{
"in": "path",
"name": "slug",
"required": true,
"schema": {
"title": "Slug",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"example": {
"email": "reader@example.com",
"first_name": "Sam"
},
"schema": {
"$ref": "#/components/schemas/Subscription"
}
}
},
"required": true
},
"responses": {
"202": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultGeneric"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Subscribe",
"tags": [
"Signup"
],
"x-required-role": "public/capability"
}POST /api/v1/public/organisations/{slug}/confirmation-requests — Replacement
Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.
Scope: public/capability
Parameters
slug(path, required)
{
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state.",
"operationId": "replacement_api_v1_public_organisations__slug__confirmation_requests_post",
"parameters": [
{
"in": "path",
"name": "slug",
"required": true,
"schema": {
"title": "Slug",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EmailRequest"
}
}
},
"required": true
},
"responses": {
"202": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultGeneric"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Replacement",
"tags": [
"Signup"
],
"x-required-role": "public/capability"
}POST /api/v1/public/confirmations — Confirm
Token in JSON for server clients, or exchanged broadcast_activation cookie. Browser requests require canonical Origin and broadcast_activation_csrf via X-CSRF-Token. GET links never activate. Disabled organisations cannot activate.
Scope: public/capability
Parameters
Origin(header) Required with capability cookie or a browser request.X-CSRF-Token(header) Required for browser/cookie activation.
{
"description": "Token in JSON for server clients, or exchanged broadcast_activation cookie. Browser requests require canonical Origin and broadcast_activation_csrf via X-CSRF-Token. GET links never activate. Disabled organisations cannot activate.",
"operationId": "confirm_api_v1_public_confirmations_post",
"parameters": [
{
"description": "Required with capability cookie or a browser request.",
"in": "header",
"name": "Origin",
"required": false,
"schema": {
"type": "string"
}
},
{
"description": "Required for browser/cookie activation.",
"in": "header",
"name": "X-CSRF-Token",
"required": false,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Confirmation"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultActivation"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Confirm",
"tags": [
"Signup"
],
"x-required-role": "public/capability"
}POST /api/v1/public/resubscriptions — Resubscribe
Token in JSON for server clients, or exchanged broadcast_activation cookie. Browser requests require canonical Origin and broadcast_activation_csrf via X-CSRF-Token. GET links never activate. Disabled organisations cannot activate.
Scope: public/capability
Parameters
Origin(header) Required with capability cookie or a browser request.X-CSRF-Token(header) Required for browser/cookie activation.
{
"description": "Token in JSON for server clients, or exchanged broadcast_activation cookie. Browser requests require canonical Origin and broadcast_activation_csrf via X-CSRF-Token. GET links never activate. Disabled organisations cannot activate.",
"operationId": "resubscribe_api_v1_public_resubscriptions_post",
"parameters": [
{
"description": "Required with capability cookie or a browser request.",
"in": "header",
"name": "Origin",
"required": false,
"schema": {
"type": "string"
}
},
{
"description": "Required for browser/cookie activation.",
"in": "header",
"name": "X-CSRF-Token",
"required": false,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Resubscription"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultActivation"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Resubscribe",
"tags": [
"Signup"
],
"x-required-role": "public/capability"
}POST /api/v1/public/preferences-requests — Request Link
Same generic 202 for zero/one/multiple associations, cooldown and missing/unhealthy SMTP. One organisation uses its sender; multiple use neutral central mail. Disabled associations remain eligible for preferences only. No source fallback.
Scope: public/capability
Parameters
Origin(header, required) Exact configured application origin; this endpoint is same-origin, not organisation CORS.
{
"description": "Same generic 202 for zero/one/multiple associations, cooldown and missing/unhealthy SMTP. One organisation uses its sender; multiple use neutral central mail. Disabled associations remain eligible for preferences only. No source fallback.",
"operationId": "request_link_api_v1_public_preferences_requests_post",
"parameters": [
{
"description": "Exact configured application origin; this endpoint is same-origin, not organisation CORS.",
"in": "header",
"name": "Origin",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"example": {
"email": "reader@example.com"
},
"schema": {
"$ref": "#/components/schemas/EmailRequest"
}
}
},
"required": true
},
"responses": {
"202": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultGeneric"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Request Link",
"tags": [
"Preferences"
],
"x-required-role": "public/capability"
}GET /api/v1/public/preferences — Preferences
Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session.
Scope: public/capability
{
"description": "Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session.",
"operationId": "preferences_api_v1_public_preferences_get",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPreferences"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [
{
"PreferencesCapability": []
},
{
"PreferencesCookie": []
}
],
"summary": "Preferences",
"tags": [
"Preferences"
],
"x-required-role": "public/capability"
}PATCH /api/v1/public/preferences/{org_id} — Update
Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session.
Scope: public/capability
Parameters
org_id(path, required)Origin(header) Required for cookie/browser requests.X-CSRF-Token(header) Scoped CSRF from the hosted preferences page, required for cookie/browser requests.
{
"description": "Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session.",
"operationId": "update_api_v1_public_preferences__org_id__patch",
"parameters": [
{
"in": "path",
"name": "org_id",
"required": true,
"schema": {
"format": "uuid",
"title": "Org Id",
"type": "string"
}
},
{
"description": "Required for cookie/browser requests.",
"in": "header",
"name": "Origin",
"required": false,
"schema": {
"type": "string"
}
},
{
"description": "Scoped CSRF from the hosted preferences page, required for cookie/browser requests.",
"in": "header",
"name": "X-CSRF-Token",
"required": false,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Choices"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPreferenceChange"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [
{
"PreferencesCapability": []
},
{
"PreferencesCookie": []
}
],
"summary": "Update",
"tags": [
"Preferences"
],
"x-required-role": "public/capability"
}POST /api/v1/public/preferences/{org_id}/unsubscribe — Unsubscribe
Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session.
Scope: public/capability
Parameters
org_id(path, required)Origin(header) Required for cookie/browser requests.X-CSRF-Token(header) Scoped CSRF from the hosted preferences page, required for cookie/browser requests.
{
"description": "Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session.",
"operationId": "unsubscribe_api_v1_public_preferences__org_id__unsubscribe_post",
"parameters": [
{
"in": "path",
"name": "org_id",
"required": true,
"schema": {
"format": "uuid",
"title": "Org Id",
"type": "string"
}
},
{
"description": "Required for cookie/browser requests.",
"in": "header",
"name": "Origin",
"required": false,
"schema": {
"type": "string"
}
},
{
"description": "Scoped CSRF from the hosted preferences page, required for cookie/browser requests.",
"in": "header",
"name": "X-CSRF-Token",
"required": false,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Withdrawal"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPreferenceChange"
}
},
"required": [
"data"
],
"type": "object"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [
{
"PreferencesCapability": []
},
{
"PreferencesCookie": []
}
],
"summary": "Unsubscribe",
"tags": [
"Preferences"
],
"x-required-role": "public/capability"
}GET /u/{raw} — Direct Page
Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.
Scope: public/capability
Parameters
raw(path, required)
{
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"operationId": "direct_page_u__raw__get",
"parameters": [
{
"in": "path",
"name": "raw",
"required": true,
"schema": {
"title": "Raw",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Public image or unsubscribe confirmation."
},
"403": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Direct Page",
"tags": [
"Preferences"
],
"x-required-role": "public/capability"
}POST /u/{raw} — Direct Unsubscribe
Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.
Scope: public/capability
Parameters
raw(path, required)
{
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"operationId": "direct_unsubscribe_u__raw__post",
"parameters": [
{
"in": "path",
"name": "raw",
"required": true,
"schema": {
"title": "Raw",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"properties": {
"List-Unsubscribe": {
"const": "One-Click"
}
},
"required": [
"List-Unsubscribe"
],
"type": "object"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultUnsubscribe"
}
},
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Successful result. 202 means durable processing, not delivery."
},
"403": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Role, origin or CSRF denied."
},
"404": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Missing or inaccessible resource; tenant existence is not disclosed."
},
"409": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition."
},
"410": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Expired operation or invalid/expired capability."
},
"413": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request or upload exceeds its limit."
},
"415": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Unsupported content type."
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Validation failed; unknown mutation fields are rejected."
},
"429": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "Rate limited; obey Retry-After.",
"headers": {
"Retry-After": {
"description": "Seconds until retry.",
"schema": {
"type": "integer"
}
}
}
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"description": "Request could not be durably processed."
}
},
"security": [],
"summary": "Direct Unsubscribe",
"tags": [
"Preferences"
],
"x-required-role": "public/capability"
}GET /health/live — Live
Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.
Scope: public/capability
{
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"operationId": "live_health_live_get",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
},
"description": "Healthy probe."
}
},
"security": [],
"summary": "Live",
"tags": [
"Main"
],
"x-required-role": "public/capability"
}GET /health/ready — Readiness
Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.
Scope: public/capability
{
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"operationId": "readiness_health_ready_get",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
},
"description": "Healthy probe."
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
},
"description": "Not ready or degraded."
}
},
"security": [],
"summary": "Readiness",
"tags": [
"Main"
],
"x-required-role": "public/capability"
}GET /health — Health
Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.
Scope: public/capability
{
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"operationId": "health_health_get",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
},
"description": "Healthy probe."
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
},
"description": "Not ready or degraded."
}
},
"security": [],
"summary": "Health",
"tags": [
"Main"
],
"x-required-role": "public/capability"
}Component schemas
Complete machine-readable contract
{
"openapi": "3.1.0",
"info": {
"title": "Galassify Broadcast \u2014 Public integration",
"description": "Actual implemented operations. Accepted public requests do not prove activation or inbox delivery. Public signup uses no admin cookie or API key. Capability endpoints have their own authority.",
"version": "0.20.0rc1"
},
"paths": {
"/assets/{storage_key}": {
"get": {
"summary": "Public Image",
"operationId": "public_image_assets__storage_key__get",
"parameters": [
{
"name": "storage_key",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid",
"title": "Storage Key"
}
}
],
"responses": {
"200": {
"description": "Public image or unsubscribe confirmation.",
"content": {
"image/*": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Assets"
],
"x-required-role": "public/capability",
"security": [],
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow."
}
},
"/api/v1/public/organisations/{slug}": {
"get": {
"summary": "Organisation",
"operationId": "organisation_api_v1_public_organisations__slug__get",
"parameters": [
{
"name": "slug",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Slug"
}
}
],
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPublicOrganisation"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Signup"
],
"x-required-role": "public/capability",
"security": [],
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state."
}
},
"/api/v1/public/organisations/{slug}/subjects": {
"get": {
"summary": "Subjects",
"operationId": "subjects_api_v1_public_organisations__slug__subjects_get",
"parameters": [
{
"name": "slug",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Slug"
}
}
],
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultSubjects"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Signup"
],
"x-required-role": "public/capability",
"security": [],
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state."
}
},
"/api/v1/public/organisations/{slug}/subscriptions": {
"post": {
"summary": "Subscribe",
"operationId": "subscribe_api_v1_public_organisations__slug__subscriptions_post",
"parameters": [
{
"name": "slug",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Slug"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Subscription"
},
"example": {
"email": "reader@example.com",
"first_name": "Sam"
}
}
}
},
"responses": {
"202": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultGeneric"
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Signup"
],
"x-required-role": "public/capability",
"security": [],
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state."
}
},
"/api/v1/public/organisations/{slug}/confirmation-requests": {
"post": {
"summary": "Replacement",
"operationId": "replacement_api_v1_public_organisations__slug__confirmation_requests_post",
"parameters": [
{
"name": "slug",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Slug"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EmailRequest"
}
}
}
},
"responses": {
"202": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultGeneric"
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Signup"
],
"x-required-role": "public/capability",
"security": [],
"description": "Exact configured organisation CORS origins only; credentials omitted. Omitted subject_ids selects all; explicit [] is rejected when subjects exist. Generic success depends only on public opt-in mode, not address state."
}
},
"/api/v1/public/confirmations": {
"post": {
"summary": "Confirm",
"operationId": "confirm_api_v1_public_confirmations_post",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Confirmation"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultActivation"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Signup"
],
"x-required-role": "public/capability",
"parameters": [
{
"name": "Origin",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Required with capability cookie or a browser request."
},
{
"name": "X-CSRF-Token",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Required for browser/cookie activation."
}
],
"security": [],
"description": "Token in JSON for server clients, or exchanged broadcast_activation cookie. Browser requests require canonical Origin and broadcast_activation_csrf via X-CSRF-Token. GET links never activate. Disabled organisations cannot activate."
}
},
"/api/v1/public/resubscriptions": {
"post": {
"summary": "Resubscribe",
"operationId": "resubscribe_api_v1_public_resubscriptions_post",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Resubscription"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultActivation"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Signup"
],
"x-required-role": "public/capability",
"parameters": [
{
"name": "Origin",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Required with capability cookie or a browser request."
},
{
"name": "X-CSRF-Token",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Required for browser/cookie activation."
}
],
"security": [],
"description": "Token in JSON for server clients, or exchanged broadcast_activation cookie. Browser requests require canonical Origin and broadcast_activation_csrf via X-CSRF-Token. GET links never activate. Disabled organisations cannot activate."
}
},
"/api/v1/public/preferences-requests": {
"post": {
"summary": "Request Link",
"operationId": "request_link_api_v1_public_preferences_requests_post",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EmailRequest"
},
"example": {
"email": "reader@example.com"
}
}
},
"required": true
},
"responses": {
"202": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultGeneric"
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Preferences"
],
"x-required-role": "public/capability",
"parameters": [
{
"name": "Origin",
"in": "header",
"required": true,
"schema": {
"type": "string"
},
"description": "Exact configured application origin; this endpoint is same-origin, not organisation CORS."
}
],
"security": [],
"description": "Same generic 202 for zero/one/multiple associations, cooldown and missing/unhealthy SMTP. One organisation uses its sender; multiple use neutral central mail. Disabled associations remain eligible for preferences only. No source fallback."
}
},
"/api/v1/public/preferences": {
"get": {
"summary": "Preferences",
"operationId": "preferences_api_v1_public_preferences_get",
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPreferences"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Preferences"
],
"x-required-role": "public/capability",
"parameters": [],
"security": [
{
"PreferencesCapability": []
},
{
"PreferencesCookie": []
}
],
"description": "Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session."
}
},
"/api/v1/public/preferences/{org_id}": {
"patch": {
"summary": "Update",
"operationId": "update_api_v1_public_preferences__org_id__patch",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid",
"title": "Org Id"
}
},
{
"name": "Origin",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Required for cookie/browser requests."
},
{
"name": "X-CSRF-Token",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Scoped CSRF from the hosted preferences page, required for cookie/browser requests."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Choices"
}
}
}
},
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPreferenceChange"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Preferences"
],
"x-required-role": "public/capability",
"security": [
{
"PreferencesCapability": []
},
{
"PreferencesCookie": []
}
],
"description": "Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session."
}
},
"/api/v1/public/preferences/{org_id}/unsubscribe": {
"post": {
"summary": "Unsubscribe",
"operationId": "unsubscribe_api_v1_public_preferences__org_id__unsubscribe_post",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid",
"title": "Org Id"
}
},
{
"name": "Origin",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Required for cookie/browser requests."
},
{
"name": "X-CSRF-Token",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Scoped CSRF from the hosted preferences page, required for cookie/browser requests."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Withdrawal"
}
}
}
},
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/components/schemas/ResultPreferenceChange"
}
},
"required": [
"data"
]
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Preferences"
],
"x-required-role": "public/capability",
"security": [
{
"PreferencesCapability": []
},
{
"PreferencesCookie": []
}
],
"description": "Only existing capability grants. Server clients may use X-Preferences-Token without Origin. Browser/cookie mutations require canonical Origin and scoped X-CSRF-Token; no admin session."
}
},
"/u/{raw}": {
"get": {
"summary": "Direct Page",
"operationId": "direct_page_u__raw__get",
"parameters": [
{
"name": "raw",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Raw"
}
}
],
"responses": {
"200": {
"description": "Public image or unsubscribe confirmation.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Preferences"
],
"x-required-role": "public/capability",
"security": [],
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow."
},
"post": {
"summary": "Direct Unsubscribe",
"operationId": "direct_unsubscribe_u__raw__post",
"parameters": [
{
"name": "raw",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Raw"
}
}
],
"responses": {
"200": {
"description": "Successful result. 202 means durable processing, not delivery.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultUnsubscribe"
}
},
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"403": {
"description": "Role, origin or CSRF denied.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"404": {
"description": "Missing or inaccessible resource; tenant existence is not disclosed.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"409": {
"description": "Conflict, stale revision/confirmation, disabled organisation or invalid transition.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"410": {
"description": "Expired operation or invalid/expired capability.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"413": {
"description": "Request or upload exceeds its limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"415": {
"description": "Unsupported content type.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
},
"422": {
"description": "Validation failed; unknown mutation fields are rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
},
"429": {
"description": "Rate limited; obey Retry-After.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Seconds until retry."
}
}
},
"503": {
"description": "Request could not be durably processed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultError"
}
}
}
}
},
"tags": [
"Preferences"
],
"x-required-role": "public/capability",
"security": [],
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow.",
"requestBody": {
"required": true,
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"type": "object",
"properties": {
"List-Unsubscribe": {
"const": "One-Click"
}
},
"required": [
"List-Unsubscribe"
]
}
}
}
}
}
},
"/health/live": {
"get": {
"summary": "Live",
"operationId": "live_health_live_get",
"responses": {
"200": {
"description": "Healthy probe.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
}
}
},
"tags": [
"Main"
],
"x-required-role": "public/capability",
"parameters": [],
"security": [],
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow."
}
},
"/health/ready": {
"get": {
"summary": "Readiness",
"operationId": "readiness_health_ready_get",
"responses": {
"200": {
"description": "Healthy probe.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
}
},
"503": {
"description": "Not ready or degraded.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
}
}
},
"tags": [
"Main"
],
"x-required-role": "public/capability",
"parameters": [],
"security": [],
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow."
}
},
"/health": {
"get": {
"summary": "Health",
"operationId": "health_health_get",
"responses": {
"200": {
"description": "Healthy probe.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
}
},
"503": {
"description": "Not ready or degraded.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResultProbe"
}
}
}
}
},
"tags": [
"Main"
],
"x-required-role": "public/capability",
"parameters": [],
"security": [],
"description": "Uses the shared domain service and current authorization checks. See the integration/operator walkthrough for the surrounding workflow."
}
}
},
"components": {
"schemas": {
"Choices": {
"properties": {
"subject_ids": {
"items": {
"type": "string",
"format": "uuid"
},
"type": "array",
"maxItems": 1000,
"title": "Subject Ids"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"subject_ids"
],
"title": "Choices"
},
"Confirmation": {
"properties": {
"token": {
"anyOf": [
{
"type": "string",
"maxLength": 43,
"minLength": 43
},
{
"type": "null"
}
],
"title": "Token"
},
"subject_ids": {
"anyOf": [
{
"items": {
"type": "string",
"format": "uuid"
},
"type": "array",
"maxItems": 1000
},
{
"type": "null"
}
],
"title": "Subject Ids"
}
},
"additionalProperties": false,
"type": "object",
"title": "Confirmation"
},
"EmailRequest": {
"properties": {
"email": {
"type": "string",
"maxLength": 254,
"title": "Email"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"email"
],
"title": "EmailRequest"
},
"Resubscription": {
"properties": {
"token": {
"anyOf": [
{
"type": "string",
"maxLength": 43,
"minLength": 43
},
{
"type": "null"
}
],
"title": "Token"
},
"subject_ids": {
"anyOf": [
{
"items": {
"type": "string",
"format": "uuid"
},
"type": "array",
"maxItems": 1000
},
{
"type": "null"
}
],
"title": "Subject Ids"
},
"confirmed": {
"type": "boolean",
"title": "Confirmed"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"confirmed"
],
"title": "Resubscription"
},
"Subscription": {
"properties": {
"email": {
"type": "string",
"maxLength": 254,
"title": "Email"
},
"first_name": {
"anyOf": [
{
"type": "string",
"maxLength": 100
},
{
"type": "null"
}
],
"title": "First Name"
},
"last_name": {
"anyOf": [
{
"type": "string",
"maxLength": 100
},
{
"type": "null"
}
],
"title": "Last Name"
},
"subject_ids": {
"anyOf": [
{
"items": {
"type": "string",
"format": "uuid"
},
"type": "array",
"maxItems": 1000
},
{
"type": "null"
}
],
"title": "Subject Ids"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"email"
],
"title": "Subscription"
},
"Withdrawal": {
"properties": {},
"additionalProperties": false,
"type": "object",
"title": "Withdrawal"
},
"ResultError": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"fields": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"request_id": {
"type": "string"
}
},
"required": [
"code",
"message",
"fields",
"request_id"
]
}
},
"required": [
"error"
]
},
"ResultGeneric": {
"type": "object",
"properties": {
"success": {
"const": true
},
"status": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"success",
"status",
"message"
]
},
"ResultUnsubscribe": {
"type": "object",
"properties": {
"success": {
"const": true
},
"message": {
"type": "string"
}
},
"required": [
"success",
"message"
]
},
"ResultPublicOrganisation": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"brand_colour": {
"type": "string"
},
"background_mode": {
"type": "string"
},
"signup_intro": {
"type": "string"
},
"confirmation_intro": {
"type": "string"
},
"double_opt_in": {
"type": "boolean"
},
"signup_available": {
"type": "boolean"
},
"logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"subjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"id",
"name",
"description"
]
}
}
},
"required": [
"name",
"slug",
"subjects",
"double_opt_in",
"signup_available"
]
},
"ResultSubjects": {
"type": "object",
"properties": {
"subjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"id",
"name",
"description"
]
}
}
},
"required": [
"subjects"
]
},
"ResultActivation": {
"type": "object",
"properties": {
"confirmed": {
"const": true
}
},
"required": [
"confirmed"
]
},
"ResultPreferences": {
"type": "object",
"properties": {
"central": {
"type": "boolean"
},
"organisations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"brand_colour": {
"type": "string"
},
"background_mode": {
"type": "string"
},
"signup_intro": {
"type": "string"
},
"confirmation_intro": {
"type": "string"
},
"double_opt_in": {
"type": "boolean"
},
"signup_available": {
"type": "boolean"
},
"logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"subjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"id",
"name",
"description"
]
}
},
"preferences_intro": {
"type": "string"
},
"state": {
"type": "string"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"org_id": {
"type": "string",
"format": "uuid"
},
"subject_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": []
}
}
},
"required": [
"central",
"organisations"
]
},
"ResultPreferenceChange": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"brand_colour": {
"type": "string"
},
"background_mode": {
"type": "string"
},
"signup_intro": {
"type": "string"
},
"confirmation_intro": {
"type": "string"
},
"double_opt_in": {
"type": "boolean"
},
"signup_available": {
"type": "boolean"
},
"logo_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"subjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"id",
"name",
"description"
]
}
},
"preferences_intro": {
"type": "string"
},
"state": {
"type": "string"
},
"first_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"org_id": {
"type": "string",
"format": "uuid"
},
"subject_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
"required": []
},
"ResultProbe": {
"type": "object",
"properties": {
"status": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"status",
"version"
]
}
},
"securitySchemes": {
"PreferencesCapability": {
"type": "apiKey",
"in": "header",
"name": "X-Preferences-Token"
},
"PreferencesCookie": {
"type": "apiKey",
"in": "cookie",
"name": "broadcast_preferences"
}
}
}
}