{
  "openapi": "3.0.0",
  "paths": {
    "/api/v1/oauth/token": {
      "post": {
        "description": "Exchange an OAuth client’s client_id and client_secret for a bearer token for /public/* routes. Send `grant_type=client_credentials`, and optionally `scope` (space-separated) to narrow the token. Authenticate with HTTP Basic or with client_id and client_secret in the body.",
        "operationId": "OAuthController_token",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "client_credentials"
                    ]
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string",
                    "example": "contacts:read messages:send"
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "client_credentials"
                    ]
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string",
                    "example": "contacts:read messages:send"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An access token. Send it as `Authorization: Bearer <access_token>`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "access_token",
                    "token_type",
                    "expires_in",
                    "scope"
                  ],
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    },
                    "scope": {
                      "type": "string",
                      "example": "contacts:read messages:send"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_request, unsupported_grant_type, invalid_scope or unauthorized_client (RFC 6749 §5.2).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "invalid_request",
                        "invalid_client",
                        "invalid_scope",
                        "unauthorized_client",
                        "unsupported_grant_type",
                        "slow_down"
                      ]
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_client: unknown client, wrong secret, or a disabled or revoked client.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "invalid_request",
                        "invalid_client",
                        "invalid_scope",
                        "unauthorized_client",
                        "unsupported_grant_type",
                        "slow_down"
                      ]
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "slow_down: over the client’s rate limit. See `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "invalid_request",
                        "invalid_client",
                        "invalid_scope",
                        "unauthorized_client",
                        "unsupported_grant_type",
                        "slow_down"
                      ]
                    },
                    "error_description": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "summary": "Get an access token (client credentials grant)",
        "tags": [
          "OAuth"
        ]
      }
    },
    "/api/v1/public/audiences": {
      "get": {
        "operationId": "PublicAudiencesController_list",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List audiences",
        "tags": [
          "Public API — Audiences"
        ]
      },
      "post": {
        "operationId": "PublicAudiencesController_create",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateStaticAudienceDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Create an empty STATIC audience; add contacts with …/members",
        "tags": [
          "Public API — Audiences"
        ]
      }
    },
    "/api/v1/public/audiences/{audienceId}": {
      "get": {
        "operationId": "PublicAudiencesController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get one audience",
        "tags": [
          "Public API — Audiences"
        ]
      },
      "delete": {
        "operationId": "PublicAudiencesController_delete",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Delete a STATIC audience",
        "tags": [
          "Public API — Audiences"
        ]
      }
    },
    "/api/v1/public/audiences/{audienceId}/members": {
      "get": {
        "operationId": "PublicAudiencesController_members",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceMemberListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "A STATIC audience's members",
        "tags": [
          "Public API — Audiences"
        ]
      },
      "post": {
        "description": "By Senpede id, your own externalRef, or both. Any unknown contact fails the whole call; contacts already in the audience are left as they are.",
        "operationId": "PublicAudiencesController_add",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAddAudienceMembersDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudienceMembersAddedResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Add up to 500 contacts to a STATIC audience",
        "tags": [
          "Public API — Audiences"
        ]
      }
    },
    "/api/v1/public/audiences/{audienceId}/members/{contactId}": {
      "delete": {
        "operationId": "PublicAudiencesController_remove",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "audienceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removed, or was not a member."
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Remove a contact from a STATIC audience",
        "tags": [
          "Public API — Audiences"
        ]
      }
    },
    "/api/v1/public/broadcasts": {
      "post": {
        "operationId": "PublicBroadcastsController_create",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBroadcastDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BroadcastResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Create a campaign to a supplied recipient list and submit it for approval",
        "tags": [
          "Public API — Broadcasts"
        ]
      }
    },
    "/api/v1/public/campaigns": {
      "get": {
        "operationId": "PublicCampaignsController_list",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "PENDING_APPROVAL",
                "APPROVED",
                "SCHEDULED",
                "EXECUTING",
                "PAUSED",
                "COMPLETED",
                "CANCELLED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List campaigns, optionally by status",
        "tags": [
          "Public API — Campaigns"
        ]
      },
      "post": {
        "operationId": "PublicCampaignsController_create",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCampaignDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Create a draft campaign against an existing audience",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}": {
      "get": {
        "operationId": "PublicCampaignsController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get one campaign with its status history",
        "tags": [
          "Public API — Campaigns"
        ]
      },
      "patch": {
        "operationId": "PublicCampaignsController_update",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCampaignDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Update a draft campaign",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/cancel": {
      "post": {
        "operationId": "PublicCampaignsController_cancel",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransitionReasonDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Cancel a campaign; pending deliveries are dropped",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/messages": {
      "get": {
        "operationId": "PublicCampaignsController_messages",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "SENT",
                "FAILED",
                "SKIPPED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignMessageListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "A campaign's messages with their delivery status, receipts, replies and clicks",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/messages/{messageId}": {
      "get": {
        "operationId": "PublicCampaignsController_message",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignMessageResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "One of a campaign's messages",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/pause": {
      "post": {
        "operationId": "PublicCampaignsController_pause",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransitionReasonDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Pause an executing campaign",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/resume": {
      "post": {
        "operationId": "PublicCampaignsController_resume",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Resume a paused campaign",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/schedule": {
      "post": {
        "operationId": "PublicCampaignsController_schedule",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleCampaignDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleCampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Schedule an approved campaign, optionally recurring",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/campaigns/{campaignId}/submit": {
      "post": {
        "operationId": "PublicCampaignsController_submit",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Submit a draft for approval by a member of the organization",
        "tags": [
          "Public API — Campaigns"
        ]
      }
    },
    "/api/v1/public/channels": {
      "get": {
        "operationId": "PublicTemplatesController_channels",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "The organization's channels, to choose one to send with",
        "tags": [
          "Public API — Templates and channels"
        ]
      }
    },
    "/api/v1/public/consent-assertions": {
      "post": {
        "description": "Each item is resolved and recorded on its own; the response has one result per item. A GRANTED is refused (conflict) when the contact withdrew after capturedAt. Suppressions are never lifted and are listed in blockedBy.",
        "operationId": "PublicConsentController_assert",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssertConsentDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentAssertionsResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Record consent or withdrawals you captured, up to 500 per call",
        "tags": [
          "Public API — Consent"
        ]
      }
    },
    "/api/v1/public/contacts": {
      "get": {
        "operationId": "PublicContactsController_list",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "ARCHIVED"
              ]
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List contacts; `q` searches name, email, phone and external reference",
        "tags": [
          "Public API — Contacts"
        ]
      },
      "post": {
        "operationId": "PublicContactsController_create",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerInputDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Create a contact",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/contacts/{contactId}": {
      "get": {
        "operationId": "PublicContactsController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get one contact",
        "tags": [
          "Public API — Contacts"
        ]
      },
      "patch": {
        "operationId": "PublicContactsController_update",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Update a contact; omitted fields are kept",
        "tags": [
          "Public API — Contacts"
        ]
      },
      "delete": {
        "description": "Archived contacts are left out of audiences and sends but keep their history. Restore with POST …/restore. To remove personal data, request erasure instead.",
        "operationId": "PublicContactsController_archive",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Archive a contact",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/contacts/{contactId}/consent": {
      "get": {
        "operationId": "PublicConsentController_contactConsent",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactConsentStateResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "A contact's consent records and the suppressions in force",
        "tags": [
          "Public API — Consent"
        ]
      }
    },
    "/api/v1/public/contacts/{contactId}/erasure": {
      "post": {
        "description": "Schedules anonymization after the grace period (30 days), during which a member can cancel it in the dashboard. Message history is kept without personal data.",
        "operationId": "PublicContactsController_requestContactErasure",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactErasureResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Request erasure of a contact's personal data",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/contacts/{contactId}/restore": {
      "post": {
        "operationId": "PublicContactsController_restore",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Restore an archived contact",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/contacts/by-ref/{externalRef}": {
      "put": {
        "description": "Matches by externalRef, then by email (adopting a contact that has no reference yet). Sent fields replace stored ones; omitted fields are kept. 201 when created, 200 when updated. An archived contact is updated but stays archived. Inline `consent` is recorded like POST /public/consent-assertions and needs consent:write.",
        "operationId": "PublicContactsController_upsert",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "externalRef",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertContactInputDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpsertContactResponse"
                }
              }
            }
          },
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpsertContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Create or update a contact by your own id",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/contacts/imports": {
      "post": {
        "description": "Rows match existing contacts by externalRef, then email. UPSERT (default) updates matches; CREATE_ONLY skips them. Rows that fail are skipped with a reason; the rest are imported.",
        "operationId": "PublicContactImportsController_start",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartContactImportDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactImportResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Import up to 10,000 contacts in the background",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/contacts/imports/{importId}": {
      "get": {
        "operationId": "PublicContactImportsController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "importId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactImportResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "An import's status, counts and skipped rows",
        "tags": [
          "Public API — Contacts"
        ]
      }
    },
    "/api/v1/public/journey-enrollments/{enrollmentId}": {
      "get": {
        "operationId": "PublicJourneyEnrollmentsController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "enrollmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyEnrollmentResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get an enrollment",
        "tags": [
          "Public API — Journeys"
        ]
      }
    },
    "/api/v1/public/journey-enrollments/{enrollmentId}/exit": {
      "post": {
        "description": "Stops the enrollment before its next step. Exiting an enrollment that already exited returns it unchanged; a completed one cannot be exited (409). Messages a step already queued are not recalled.",
        "operationId": "PublicJourneyEnrollmentsController_exit",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "enrollmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExitEnrollmentDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyEnrollmentResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Take a contact out of a journey",
        "tags": [
          "Public API — Journeys"
        ]
      }
    },
    "/api/v1/public/journeys": {
      "get": {
        "operationId": "PublicJourneysController_list",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "PUBLISHED",
                "PAUSED",
                "ARCHIVED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List journeys",
        "tags": [
          "Public API — Journeys"
        ]
      }
    },
    "/api/v1/public/journeys/{journeyId}": {
      "get": {
        "operationId": "PublicJourneysController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "journeyId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get a journey",
        "tags": [
          "Public API — Journeys"
        ]
      }
    },
    "/api/v1/public/journeys/{journeyId}/enrollments": {
      "post": {
        "description": "The journey must be PUBLISHED. Identify the contact by contactId, externalRef or email; archived contacts are not found. 201 when a new enrollment starts. 200 with the existing enrollment when the contact is already in the journey, or already finished it and the journey does not allow re-entry — safe to retry.",
        "operationId": "PublicJourneysController_enroll",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "journeyId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollContactDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollContactResponse"
                }
              }
            }
          },
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Enroll a contact in a journey",
        "tags": [
          "Public API — Journeys"
        ]
      },
      "get": {
        "operationId": "PublicJourneysController_enrollments",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "journeyId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "contactId",
            "required": false,
            "in": "query",
            "description": "Only this contact’s enrollments.",
            "schema": {
              "minLength": 1,
              "maxLength": 64,
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "COMPLETED",
                "EXITED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyEnrollmentListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List a journey’s enrollments, newest first",
        "tags": [
          "Public API — Journeys"
        ]
      }
    },
    "/api/v1/public/messages": {
      "post": {
        "operationId": "PublicMessagesController_send",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Send one transactional message to one contact",
        "tags": [
          "Public API — Messages"
        ]
      }
    },
    "/api/v1/public/messages/{messageId}": {
      "get": {
        "operationId": "PublicMessagesController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Read one message's delivery status",
        "tags": [
          "Public API — Messages"
        ]
      }
    },
    "/api/v1/public/organizations": {
      "post": {
        "description": "Partners only. 201 when created; 200 with the existing tenant when one with this externalRef already exists — safe to retry. The tenant bills through the partner, has no members, and starts one trust tier below the partner.",
        "operationId": "PublicOrganizationsController_create",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTenantOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateTenantOrganizationResponse"
                }
              }
            }
          },
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateTenantOrganizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Create a tenant organization",
        "tags": [
          "Public API — Tenant organizations"
        ]
      },
      "get": {
        "operationId": "PublicOrganizationsController_list",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "SUSPENDED",
                "DEACTIVATED"
              ]
            }
          },
          {
            "name": "externalRef",
            "required": false,
            "in": "query",
            "description": "Find the tenant with this externalRef.",
            "schema": {
              "minLength": 1,
              "maxLength": 120,
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOrganizationListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List tenant organizations, newest first",
        "tags": [
          "Public API — Tenant organizations"
        ]
      }
    },
    "/api/v1/public/organizations/{organizationId}": {
      "get": {
        "operationId": "PublicOrganizationsController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOrganizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get a tenant organization",
        "tags": [
          "Public API — Tenant organizations"
        ]
      },
      "patch": {
        "operationId": "PublicOrganizationsController_update",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTenantOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOrganizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Rename a tenant organization or change its externalRef",
        "tags": [
          "Public API — Tenant organizations"
        ]
      }
    },
    "/api/v1/public/organizations/{organizationId}/invitations": {
      "post": {
        "description": "Returns an acceptUrl for you to send to them; Senpede does not email it. Any role but owner; defaults to admin.",
        "operationId": "PublicOrganizationsController_invite",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "organizationId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteTenantMemberDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantInvitationResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Invite someone to sign in to a tenant organization",
        "tags": [
          "Public API — Tenant organizations"
        ]
      }
    },
    "/api/v1/public/sandbox/messages": {
      "get": {
        "operationId": "PublicSandboxController_messages",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxCapturedMessageListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Messages the sandbox captured instead of sending, newest first",
        "tags": [
          "Public API — Sandbox"
        ]
      }
    },
    "/api/v1/public/sandbox/messages/{messageId}/events": {
      "post": {
        "description": "The event is handled like a real provider callback: the message status, the contact’s consent and your webhooks all change as they would live. `messageId` is a campaign message (`cmsg_…`) or single message (`cntf_…`) id.",
        "operationId": "PublicSandboxController_trigger",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TriggerSandboxEventDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxEventResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Simulate a delivery receipt, read, failure, reply or opt-out for a sent message",
        "tags": [
          "Public API — Sandbox"
        ]
      }
    },
    "/api/v1/public/suppressions": {
      "get": {
        "operationId": "PublicConsentController_suppressions",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuppressionListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Every suppression in force across the organization",
        "tags": [
          "Public API — Consent"
        ]
      }
    },
    "/api/v1/public/templates": {
      "get": {
        "operationId": "PublicTemplatesController_templates",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "default": "APPROVED",
              "type": "string",
              "enum": [
                "DRAFT",
                "APPROVED",
                "ARCHIVED"
              ]
            }
          },
          {
            "name": "channelType",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "SMS",
                "EMAIL",
                "WHATSAPP",
                "TELEGRAM",
                "PUSH",
                "WEBHOOK",
                "CUSTOM"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Message templates, APPROVED unless `status` says otherwise",
        "tags": [
          "Public API — Templates and channels"
        ]
      }
    },
    "/api/v1/public/usage": {
      "get": {
        "description": "Figures come from the same ledger sends reserve against, so they include sends in progress (`pending`). Organizations without a plan (the free trial) have no allowances listed.",
        "operationId": "PublicUsageController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummaryResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Allowances for the current billing period, and how much of each is used",
        "tags": [
          "Public API — Usage"
        ]
      }
    },
    "/api/v1/public/usage/tenants": {
      "get": {
        "description": "How much of the partner's shared allowance each tenant used, by usage type — the breakdown behind the partner's own totals. Tenants that used nothing are left out.",
        "operationId": "PublicUsageController_tenants",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantUsageSummaryResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Partners only: each tenant organization's usage this billing period",
        "tags": [
          "Public API — Usage"
        ]
      }
    },
    "/api/v1/public/webhook-endpoints": {
      "post": {
        "operationId": "PublicWebhookEndpointsController_create",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecretResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Register an endpoint; the signing secret is returned once",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      },
      "get": {
        "operationId": "PublicWebhookEndpointsController_list",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "List webhook endpoints",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      }
    },
    "/api/v1/public/webhook-endpoints/{endpointId}": {
      "get": {
        "operationId": "PublicWebhookEndpointsController_get",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Get one webhook endpoint",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      },
      "patch": {
        "operationId": "PublicWebhookEndpointsController_update",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Change an endpoint’s URL, description, event types or enabled state",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      },
      "delete": {
        "operationId": "PublicWebhookEndpointsController_remove",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Delete an endpoint and its delivery log",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      }
    },
    "/api/v1/public/webhook-endpoints/{endpointId}/deliveries": {
      "get": {
        "operationId": "PublicWebhookEndpointsController_deliveries",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "default": 1,
              "type": "number"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "type": "number"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "SUCCEEDED",
                "FAILED",
                "DEAD"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryListResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "An endpoint’s delivery log, optionally by status",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      }
    },
    "/api/v1/public/webhook-endpoints/{endpointId}/deliveries/{deliveryId}/replay": {
      "post": {
        "operationId": "PublicWebhookEndpointsController_replay",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deliveryId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Re-send a delivery with a fresh retry budget",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      }
    },
    "/api/v1/public/webhook-endpoints/{endpointId}/rotate-secret": {
      "post": {
        "operationId": "PublicWebhookEndpointsController_rotateSecret",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointWithSecretResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Replace the signing secret; the new one is returned once",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      }
    },
    "/api/v1/public/webhook-endpoints/{endpointId}/test": {
      "post": {
        "operationId": "PublicWebhookEndpointsController_sendTest",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional on writes. The first successful response for a key is replayed for 24 hours.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Senpede-Organization",
            "in": "header",
            "description": "Partner keys only: the id of one of the partner's tenant organizations to act on. Omit to act in the key's own organization.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endpointId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                }
              }
            }
          },
          "400": {
            "description": "VALIDATION_ERROR — the request body, query or a header is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "AUTHENTICATION_REQUIRED — missing, invalid, expired or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "AUTHORIZATION_DENIED (missing scope, or IP not allowed) or ORGANIZATION_SUSPENDED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "RESOURCE_NOT_FOUND — does not exist in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "RESOURCE_CONFLICT, or IDEMPOTENCY_REQUEST_IN_PROGRESS while the first request with this Idempotency-Key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED — this Idempotency-Key was used for a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMIT_EXCEEDED — wait Retry-After seconds, then retry.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this key.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Seconds until the window resets.",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          },
          {
            "oauth2": []
          }
        ],
        "summary": "Send a `webhook.test` event to this endpoint",
        "tags": [
          "Public API — Webhook endpoints"
        ]
      }
    }
  },
  "info": {
    "title": "Senpede Public API",
    "description": "Integrate with Senpede using an organization API key: contacts, campaigns, broadcasts, single messages and outbound event webhooks. Full guide: https://senpede.com/developers",
    "version": "1.3.1",
    "contact": {},
    "x-changelog": [
      {
        "version": "1.3.1",
        "date": "2026-09-28",
        "changes": [
          {
            "kind": "changed",
            "text": "Journey message steps are now marketing messages: each is sent only to a contact who granted marketing consent for its channel, and is otherwise skipped (`message.skipped`) while the journey carries on. They were sent as transactional messages before. Single messages (`POST /public/messages`) are unchanged."
          }
        ]
      },
      {
        "version": "1.3.0",
        "date": "2026-09-28",
        "changes": [
          {
            "kind": "added",
            "text": "Partner accounts. An organization Senpede makes a partner creates one tenant organization per customer of its own platform with `POST /public/organizations` (idempotent on `externalRef`), and lists, reads, renames and invites staff to them. Needs the new `organizations:manage` scope."
          },
          {
            "kind": "added",
            "text": "Every operation accepts an optional `Senpede-Organization` header: a partner's key acts inside the named tenant organization with its usual scopes. A test key acts in that tenant's sandbox."
          },
          {
            "kind": "added",
            "text": "Webhook endpoints take `includeTenantEvents`: a partner's endpoint also receives its tenants' events, each carrying the tenant's `organizationId`."
          },
          {
            "kind": "added",
            "text": "Tenants draw on their partner's allowance: `GET /public/usage` reports the shared totals, and the new `GET /public/usage/tenants` breaks them down per tenant."
          }
        ]
      },
      {
        "version": "1.2.0",
        "date": "2026-09-27",
        "changes": [
          {
            "kind": "added",
            "text": "Journeys: `GET /public/journeys` and `GET /public/journeys/{journeyId}` (scope `journeys:read`). Journeys are still built and published in the dashboard."
          },
          {
            "kind": "added",
            "text": "`POST /public/journeys/{journeyId}/enrollments` enrolls a contact by `contactId`, `externalRef` or `email` (scope `journeys:enroll`); 201 for a new enrollment, 200 with the existing one. `GET /public/journeys/{journeyId}/enrollments`, `GET /public/journey-enrollments/{enrollmentId}` and `POST /public/journey-enrollments/{enrollmentId}/exit` follow and end enrollments."
          },
          {
            "kind": "added",
            "text": "Webhook events `journey.enrolled`, `journey.completed` and `journey.exited`, for every enrollment however it started (dashboard, automation rule or API)."
          }
        ]
      },
      {
        "version": "1.1.0",
        "date": "2026-09-27",
        "changes": [
          {
            "kind": "added",
            "text": "`GET /public/usage`: the allowances for the current billing period, with how much of each is used, set aside for sends in progress and left. Needs the new `usage:read` scope."
          },
          {
            "kind": "added",
            "text": "Webhook events `usage.quota_low` (an allowance passed 75% or 90% of its included quantity) and `usage.quota_exhausted` (it reached 100%), once per allowance per billing period."
          }
        ]
      },
      {
        "version": "1.0.0",
        "date": "2026-09-27",
        "changes": [
          {
            "kind": "added",
            "text": "First versioned release of the public API contract. It covers contacts (including upsert by your own reference, archive, restore, erasure and bulk imports), consent assertions and suppressions, audiences, templates and channels, campaigns and broadcasts with their per-message status, single messages, webhook endpoints and deliveries, OAuth 2.0 client credentials, and test mode."
          },
          {
            "kind": "added",
            "text": "`GET /public/contacts` and `GET /public/campaigns` now publish their `page`, `pageSize`, `q` and `status` query parameters in the contract."
          },
          {
            "kind": "added",
            "text": "Deprecated operations are marked `deprecated` in the contract and answer with `Deprecation` and `Sunset` headers."
          }
        ]
      }
    ]
  },
  "tags": [],
  "servers": [
    {
      "url": "https://api.senpede.com"
    }
  ],
  "components": {
    "schemas": {
      "ApiErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "category",
              "message",
              "retryable"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable, machine-readable code to branch on.",
                "example": "VALIDATION_ERROR"
              },
              "category": {
                "type": "string",
                "description": "Sen Core error category; decides the HTTP status.",
                "example": "VALIDATION"
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              },
              "retryable": {
                "type": "boolean",
                "description": "True when the same request may succeed if retried later."
              },
              "details": {
                "description": "Code-specific extra information, when any."
              },
              "validationIssues": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "message"
                  ],
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "expected": {},
                    "received": {}
                  }
                }
              },
              "correlationId": {
                "type": "string"
              },
              "requestId": {
                "type": "string",
                "description": "Quote this when asking for support."
              }
            }
          }
        }
      },
      "AssertConsentDto": {
        "type": "object",
        "properties": {
          "assertions": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentAssertionDto"
            }
          }
        },
        "required": [
          "assertions"
        ]
      },
      "AudienceDto": {
        "type": "object",
        "properties": {
          "type": {
            "enum": [
              "STATIC",
              "DYNAMIC"
            ],
            "type": "string",
            "description": "STATIC audiences list their members; DYNAMIC ones match contacts by criteria and are read-only here."
          },
          "criteria": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Matching rules of a DYNAMIC audience; null for STATIC."
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "type",
          "criteria",
          "id",
          "name",
          "description",
          "createdAt",
          "updatedAt"
        ]
      },
      "AudienceListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AudienceDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "AudienceMemberDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "fullName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "fullName",
          "email",
          "phone"
        ]
      },
      "AudienceMemberListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AudienceMemberDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "AudienceMembersAddedDto": {
        "type": "object",
        "properties": {
          "added": {
            "type": "number"
          }
        },
        "required": [
          "added"
        ]
      },
      "AudienceMembersAddedResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AudienceMembersAddedDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "AudienceResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AudienceDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "BroadcastDto": {
        "type": "object",
        "properties": {
          "campaign": {
            "$ref": "#/components/schemas/CampaignDto"
          },
          "audienceId": {
            "type": "string"
          },
          "recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BroadcastRecipientResultDto"
            }
          }
        },
        "required": [
          "campaign",
          "audienceId",
          "recipients"
        ]
      },
      "BroadcastRecipientDto": {
        "type": "object",
        "properties": {
          "contactId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "externalRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 32
          },
          "fullName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "preferredLanguage": {
            "type": "string",
            "maxLength": 16
          },
          "timeZone": {
            "type": "string"
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "consent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentStatementDto"
            }
          }
        }
      },
      "BroadcastRecipientResultDto": {
        "type": "object",
        "properties": {
          "resolution": {
            "enum": [
              "contactId",
              "externalRef",
              "email",
              "created"
            ],
            "type": "string"
          },
          "index": {
            "type": "number"
          },
          "contactId": {
            "type": "string"
          },
          "consent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentAssertionResultDto"
            }
          }
        },
        "required": [
          "resolution",
          "index",
          "contactId",
          "consent"
        ]
      },
      "BroadcastResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/BroadcastDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignDeliveryCountsDto": {
        "type": "object",
        "properties": {
          "PENDING": {
            "type": "number"
          },
          "SENT": {
            "type": "number"
          },
          "FAILED": {
            "type": "number"
          },
          "SKIPPED": {
            "type": "number"
          }
        },
        "required": [
          "PENDING",
          "SENT",
          "FAILED",
          "SKIPPED"
        ]
      },
      "CampaignDetailDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "INFORMATIONAL",
              "OPERATIONAL",
              "CUSTOMER_SUCCESS"
            ]
          },
          "sendWindowMode": {
            "type": "string",
            "enum": [
              "ORGANIZATION",
              "CUSTOM",
              "NONE"
            ]
          },
          "sendWindow": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "PENDING_APPROVAL",
              "APPROVED",
              "SCHEDULED",
              "EXECUTING",
              "PAUSED",
              "COMPLETED",
              "CANCELLED"
            ]
          },
          "recurrenceRule": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Recurrence rule when the campaign repeats; null for a one-off send."
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "audienceId": {
            "type": "string"
          },
          "channelId": {
            "type": "string",
            "nullable": true
          },
          "templateId": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "messageHtml": {
            "type": "string",
            "nullable": true
          },
          "trackLinks": {
            "type": "boolean"
          },
          "scheduledAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "approvedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "startedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "pausedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "completedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "cancelledAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "cycleSeq": {
            "type": "number"
          },
          "occurrenceCount": {
            "type": "number"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          },
          "history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CampaignHistoryEntryDto"
            }
          }
        },
        "required": [
          "type",
          "sendWindowMode",
          "sendWindow",
          "status",
          "recurrenceRule",
          "id",
          "name",
          "description",
          "audienceId",
          "channelId",
          "templateId",
          "message",
          "subject",
          "messageHtml",
          "trackLinks",
          "scheduledAt",
          "approvedAt",
          "startedAt",
          "pausedAt",
          "completedAt",
          "cancelledAt",
          "cycleSeq",
          "occurrenceCount",
          "createdAt",
          "updatedAt",
          "history"
        ]
      },
      "CampaignDetailResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignDetailDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "INFORMATIONAL",
              "OPERATIONAL",
              "CUSTOMER_SUCCESS"
            ]
          },
          "sendWindowMode": {
            "type": "string",
            "enum": [
              "ORGANIZATION",
              "CUSTOM",
              "NONE"
            ]
          },
          "sendWindow": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "PENDING_APPROVAL",
              "APPROVED",
              "SCHEDULED",
              "EXECUTING",
              "PAUSED",
              "COMPLETED",
              "CANCELLED"
            ]
          },
          "recurrenceRule": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Recurrence rule when the campaign repeats; null for a one-off send."
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "audienceId": {
            "type": "string"
          },
          "channelId": {
            "type": "string",
            "nullable": true
          },
          "templateId": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "messageHtml": {
            "type": "string",
            "nullable": true
          },
          "trackLinks": {
            "type": "boolean"
          },
          "scheduledAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "approvedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "startedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "pausedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "completedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "cancelledAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "cycleSeq": {
            "type": "number"
          },
          "occurrenceCount": {
            "type": "number"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "type",
          "sendWindowMode",
          "sendWindow",
          "status",
          "recurrenceRule",
          "id",
          "name",
          "description",
          "audienceId",
          "channelId",
          "templateId",
          "message",
          "subject",
          "messageHtml",
          "trackLinks",
          "scheduledAt",
          "approvedAt",
          "startedAt",
          "pausedAt",
          "completedAt",
          "cancelledAt",
          "cycleSeq",
          "occurrenceCount",
          "createdAt",
          "updatedAt"
        ]
      },
      "CampaignHistoryEntryDto": {
        "type": "object",
        "properties": {
          "fromStatus": {
            "nullable": true,
            "enum": [
              "DRAFT",
              "PENDING_APPROVAL",
              "APPROVED",
              "SCHEDULED",
              "EXECUTING",
              "PAUSED",
              "COMPLETED",
              "CANCELLED"
            ],
            "type": "string"
          },
          "toStatus": {
            "enum": [
              "DRAFT",
              "PENDING_APPROVAL",
              "APPROVED",
              "SCHEDULED",
              "EXECUTING",
              "PAUSED",
              "COMPLETED",
              "CANCELLED"
            ],
            "type": "string"
          },
          "actorUserId": {
            "type": "string",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "fromStatus",
          "toStatus",
          "actorUserId",
          "reason",
          "createdAt"
        ]
      },
      "CampaignListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CampaignDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "CampaignMessageDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "SENT",
              "FAILED",
              "SKIPPED"
            ]
          },
          "id": {
            "type": "string"
          },
          "contactId": {
            "type": "string"
          },
          "channelId": {
            "type": "string"
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "attempts": {
            "type": "number"
          },
          "sentAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "deliveredAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "readAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "repliedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "clickedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "heldUntil": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status",
          "id",
          "contactId",
          "channelId",
          "detail",
          "attempts",
          "sentAt",
          "deliveredAt",
          "readAt",
          "repliedAt",
          "clickedAt",
          "heldUntil",
          "createdAt"
        ]
      },
      "CampaignMessageListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CampaignMessageDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          },
          "summary": {
            "$ref": "#/components/schemas/CampaignMessageSummaryDto"
          }
        },
        "required": [
          "data",
          "pagination",
          "summary"
        ]
      },
      "CampaignMessageResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignMessageDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignMessageSummaryDto": {
        "type": "object",
        "properties": {
          "byStatus": {
            "$ref": "#/components/schemas/CampaignDeliveryCountsDto"
          },
          "receipts": {
            "$ref": "#/components/schemas/CampaignReceiptCountsDto"
          }
        },
        "required": [
          "byStatus",
          "receipts"
        ]
      },
      "CampaignReceiptCountsDto": {
        "type": "object",
        "properties": {
          "delivered": {
            "type": "number"
          },
          "read": {
            "type": "number"
          },
          "replied": {
            "type": "number"
          },
          "clicked": {
            "type": "number"
          }
        },
        "required": [
          "delivered",
          "read",
          "replied",
          "clicked"
        ]
      },
      "CampaignResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "CapacityEstimateDto": {
        "type": "object",
        "properties": {
          "estimatedRecipients": {
            "type": "number"
          },
          "remainingAllowance": {
            "type": "number",
            "nullable": true
          },
          "ceiling": {
            "type": "number",
            "nullable": true
          },
          "sufficient": {
            "type": "boolean"
          }
        },
        "required": [
          "estimatedRecipients",
          "remainingAllowance",
          "ceiling",
          "sufficient"
        ]
      },
      "ChannelDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED",
              "MIGRATING"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "healthStatus": {
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "type",
          "status",
          "id",
          "name",
          "provider",
          "healthStatus",
          "createdAt"
        ]
      },
      "ChannelListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChannelDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "ConsentAssertionDto": {
        "type": "object",
        "properties": {
          "channel": {
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM",
              "ALL"
            ],
            "type": "string"
          },
          "purpose": {
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "ALL"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "GRANTED",
              "WITHDRAWN"
            ],
            "type": "string"
          },
          "lawfulBasis": {
            "enum": [
              "CONSENT",
              "CONTRACT",
              "LEGAL_OBLIGATION",
              "VITAL_INTEREST",
              "PUBLIC_TASK",
              "LEGITIMATE_INTEREST"
            ],
            "type": "string"
          },
          "expiresAt": {
            "type": "string"
          },
          "evidenceRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "capturedAt": {
            "type": "string"
          },
          "contact": {
            "$ref": "#/components/schemas/ContactReferenceDto"
          }
        },
        "required": [
          "channel",
          "purpose",
          "status",
          "lawfulBasis",
          "evidenceRef",
          "capturedAt",
          "contact"
        ]
      },
      "ConsentAssertionResultDto": {
        "type": "object",
        "properties": {
          "result": {
            "enum": [
              "recorded",
              "unchanged",
              "conflict",
              "not_found"
            ],
            "type": "string",
            "description": "recorded: stored. unchanged: the same status and evidenceRef were already stored. conflict: not stored, the contact withdrew after capturedAt. not_found: no active contact matches."
          },
          "index": {
            "type": "number"
          },
          "contactId": {
            "type": "string",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "blockedBy": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentBlockDto"
            }
          }
        },
        "required": [
          "result",
          "index",
          "contactId",
          "detail",
          "blockedBy"
        ]
      },
      "ConsentAssertionsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentAssertionResultDto"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "ConsentBlockDto": {
        "type": "object",
        "properties": {
          "scope": {
            "enum": [
              "GLOBAL",
              "CHANNEL",
              "PURPOSE",
              "CAMPAIGN"
            ],
            "type": "string"
          },
          "channel": {
            "nullable": true,
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM",
              "ALL"
            ],
            "type": "string"
          },
          "purpose": {
            "nullable": true,
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "ALL"
            ],
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "suppressedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "scope",
          "channel",
          "purpose",
          "source",
          "suppressedAt"
        ]
      },
      "ConsentRecordDto": {
        "type": "object",
        "properties": {
          "channel": {
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM",
              "ALL"
            ],
            "type": "string"
          },
          "purpose": {
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "ALL"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "GRANTED",
              "WITHDRAWN",
              "EXPIRED",
              "REVOKED",
              "UNKNOWN"
            ],
            "type": "string"
          },
          "lawfulBasis": {
            "nullable": true,
            "enum": [
              "CONSENT",
              "CONTRACT",
              "LEGAL_OBLIGATION",
              "VITAL_INTEREST",
              "PUBLIC_TASK",
              "LEGITIMATE_INTEREST"
            ],
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "id": {
            "type": "string"
          },
          "organizationId": {
            "type": "string"
          },
          "customerId": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "capturedByUserId": {
            "type": "string",
            "nullable": true
          },
          "evidenceRef": {
            "type": "string",
            "nullable": true
          },
          "grantedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "withdrawnAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "evidenceCapturedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "channel",
          "purpose",
          "status",
          "lawfulBasis",
          "metadata",
          "id",
          "organizationId",
          "customerId",
          "source",
          "capturedByUserId",
          "evidenceRef",
          "grantedAt",
          "withdrawnAt",
          "expiresAt",
          "evidenceCapturedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "ConsentStatementDto": {
        "type": "object",
        "properties": {
          "channel": {
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM",
              "ALL"
            ],
            "type": "string"
          },
          "purpose": {
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "ALL"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "GRANTED",
              "WITHDRAWN"
            ],
            "type": "string"
          },
          "lawfulBasis": {
            "enum": [
              "CONSENT",
              "CONTRACT",
              "LEGAL_OBLIGATION",
              "VITAL_INTEREST",
              "PUBLIC_TASK",
              "LEGITIMATE_INTEREST"
            ],
            "type": "string"
          },
          "expiresAt": {
            "type": "string"
          },
          "evidenceRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "capturedAt": {
            "type": "string"
          }
        },
        "required": [
          "channel",
          "purpose",
          "status",
          "lawfulBasis",
          "evidenceRef",
          "capturedAt"
        ]
      },
      "ContactConsentStateDto": {
        "type": "object",
        "properties": {
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentRecordDto"
            }
          },
          "activeSuppressions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuppressionDto"
            }
          }
        },
        "required": [
          "records",
          "activeSuppressions"
        ]
      },
      "ContactConsentStateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ContactConsentStateDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "ContactDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "ARCHIVED"
            ]
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "id": {
            "type": "string"
          },
          "fullName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "externalRef": {
            "type": "string",
            "nullable": true
          },
          "preferredLanguage": {
            "type": "string",
            "nullable": true
          },
          "timeZone": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          },
          "isSuppressed": {
            "type": "boolean"
          }
        },
        "required": [
          "status",
          "customFields",
          "id",
          "fullName",
          "email",
          "phone",
          "externalRef",
          "preferredLanguage",
          "timeZone",
          "tags",
          "notes",
          "createdAt",
          "updatedAt"
        ]
      },
      "ContactErasureDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "SCHEDULED",
              "ANONYMIZED",
              "CANCELLED"
            ]
          },
          "id": {
            "type": "string"
          },
          "requestedByUserId": {
            "type": "string"
          },
          "requestedAt": {
            "format": "date-time",
            "type": "string"
          },
          "effectiveAt": {
            "format": "date-time",
            "type": "string"
          },
          "cancelledAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "anonymizedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "status",
          "id",
          "requestedByUserId",
          "requestedAt",
          "effectiveAt",
          "cancelledAt",
          "anonymizedAt"
        ]
      },
      "ContactErasureResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ContactErasureDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "ContactImportDto": {
        "type": "object",
        "properties": {
          "status": {
            "enum": [
              "QUEUED",
              "RUNNING",
              "COMPLETED",
              "FAILED"
            ],
            "type": "string"
          },
          "mode": {
            "enum": [
              "CREATE_ONLY",
              "UPSERT"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "totalRows": {
            "type": "number"
          },
          "processedRows": {
            "type": "number"
          },
          "createdCount": {
            "type": "number"
          },
          "updatedCount": {
            "type": "number"
          },
          "skippedCount": {
            "type": "number"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactImportRowErrorDto"
            }
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "startedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "completedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status",
          "mode",
          "id",
          "totalRows",
          "processedRows",
          "createdCount",
          "updatedCount",
          "skippedCount",
          "errors",
          "detail",
          "startedAt",
          "completedAt",
          "createdAt"
        ]
      },
      "ContactImportResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ContactImportDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "ContactImportRowDto": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 32
          },
          "externalRef": {
            "type": "string",
            "maxLength": 120
          },
          "preferredLanguage": {
            "type": "string",
            "maxLength": 16
          },
          "timeZone": {
            "type": "string"
          },
          "tags": {
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 40
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "notes": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "ContactImportRowErrorDto": {
        "type": "object",
        "properties": {
          "row": {
            "type": "number"
          },
          "externalRef": {
            "type": "string",
            "nullable": true
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "row",
          "externalRef",
          "reason"
        ]
      },
      "ContactListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "ContactReferenceDto": {
        "type": "object",
        "properties": {
          "contactId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "externalRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          }
        }
      },
      "ContactResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ContactDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "CreateBroadcastDto": {
        "type": "object",
        "properties": {
          "sendWindowMode": {
            "enum": [
              "ORGANIZATION",
              "CUSTOM",
              "NONE"
            ],
            "type": "string"
          },
          "sendWindow": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "type": {
            "type": "string",
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "INFORMATIONAL",
              "OPERATIONAL",
              "CUSTOMER_SUCCESS"
            ]
          },
          "channelId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "templateId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "messageHtml": {
            "type": "string",
            "maxLength": 50000
          },
          "recipients": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BroadcastRecipientDto"
            }
          }
        },
        "required": [
          "name",
          "channelId",
          "message",
          "recipients"
        ]
      },
      "CreateCampaignDto": {
        "type": "object",
        "properties": {
          "sendWindowMode": {
            "enum": [
              "ORGANIZATION",
              "CUSTOM",
              "NONE"
            ],
            "type": "string"
          },
          "sendWindow": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "type": {
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "INFORMATIONAL",
              "OPERATIONAL",
              "CUSTOMER_SUCCESS"
            ],
            "type": "string"
          },
          "audienceId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "channelId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "templateId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "messageHtml": {
            "type": "string",
            "maxLength": 50000
          },
          "trackLinks": {
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "audienceId",
          "message"
        ]
      },
      "CreateStaticAudienceDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "description": {
            "type": "string",
            "maxLength": 500
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateTenantOrganizationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "externalRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "country": {
            "type": "string",
            "pattern": "^[A-Za-z]{2}$"
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateTenantOrganizationResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CreateTenantOrganizationResultDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "CreateTenantOrganizationResultDto": {
        "type": "object",
        "properties": {
          "created": {
            "type": "boolean"
          },
          "organization": {
            "$ref": "#/components/schemas/TenantOrganizationDto"
          }
        },
        "required": [
          "created",
          "organization"
        ]
      },
      "CreateWebhookEndpointDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 8,
            "maxLength": 2048
          },
          "description": {
            "type": "string",
            "maxLength": 300
          },
          "eventTypes": {
            "type": "array",
            "uniqueItems": true,
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.read",
                "message.replied",
                "message.clicked",
                "message.failed",
                "message.skipped",
                "contact.opted_out",
                "consent.changed",
                "campaign.status_changed",
                "contact_import.completed",
                "usage.quota_low",
                "usage.quota_exhausted",
                "journey.enrolled",
                "journey.completed",
                "journey.exited"
              ]
            }
          },
          "includeTenantEvents": {
            "type": "boolean"
          }
        },
        "required": [
          "url",
          "eventTypes"
        ]
      },
      "CustomerInputDto": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 32
          },
          "externalRef": {
            "type": "string",
            "maxLength": 120
          },
          "preferredLanguage": {
            "type": "string",
            "maxLength": 16
          },
          "timeZone": {
            "type": "string"
          },
          "tags": {
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 40
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "notes": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "fullName"
        ]
      },
      "EnrollContactDto": {
        "type": "object",
        "properties": {
          "contact": {
            "$ref": "#/components/schemas/ContactReferenceDto"
          }
        },
        "required": [
          "contact"
        ]
      },
      "EnrollContactResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/EnrollContactResultDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "EnrollContactResultDto": {
        "type": "object",
        "properties": {
          "created": {
            "type": "boolean"
          },
          "enrollment": {
            "$ref": "#/components/schemas/JourneyEnrollmentDto"
          }
        },
        "required": [
          "created",
          "enrollment"
        ]
      },
      "ExitEnrollmentDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "InviteTenantMemberDto": {
        "type": "object",
        "properties": {
          "role": {
            "enum": [
              "admin",
              "manager",
              "campaign_manager",
              "analyst",
              "billing_manager",
              "viewer"
            ],
            "type": "string",
            "default": "admin"
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          }
        },
        "required": [
          "email"
        ]
      },
      "JourneyDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "PUBLISHED",
              "PAUSED",
              "ARCHIVED"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "version": {
            "type": "number"
          },
          "stepCount": {
            "type": "number"
          },
          "allowReEntry": {
            "type": "boolean"
          },
          "publishedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status",
          "id",
          "name",
          "description",
          "version",
          "stepCount",
          "allowReEntry",
          "publishedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "JourneyEnrollmentDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "COMPLETED",
              "EXITED"
            ]
          },
          "id": {
            "type": "string"
          },
          "journeyId": {
            "type": "string"
          },
          "contactId": {
            "type": "string"
          },
          "currentStepIndex": {
            "type": "number"
          },
          "journeyVersion": {
            "type": "number"
          },
          "source": {
            "type": "string"
          },
          "exitReason": {
            "type": "string",
            "nullable": true
          },
          "enrolledAt": {
            "format": "date-time",
            "type": "string"
          },
          "completedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "exitedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "status",
          "id",
          "journeyId",
          "contactId",
          "currentStepIndex",
          "journeyVersion",
          "source",
          "exitReason",
          "enrolledAt",
          "completedAt",
          "exitedAt"
        ]
      },
      "JourneyEnrollmentListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JourneyEnrollmentDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "JourneyEnrollmentResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/JourneyEnrollmentDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "JourneyListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JourneyDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "JourneyResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/JourneyDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "MessageDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "SENT",
              "FAILED",
              "SKIPPED"
            ]
          },
          "id": {
            "type": "string"
          },
          "customerId": {
            "type": "string"
          },
          "channelId": {
            "type": "string"
          },
          "templateId": {
            "type": "string",
            "nullable": true
          },
          "recipientRef": {
            "type": "string",
            "nullable": true
          },
          "providerMessageId": {
            "type": "string",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "attempts": {
            "type": "number"
          },
          "triggerEvent": {
            "type": "string"
          },
          "respectSendWindow": {
            "type": "boolean"
          },
          "heldUntil": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "sentAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status",
          "id",
          "customerId",
          "channelId",
          "templateId",
          "recipientRef",
          "providerMessageId",
          "detail",
          "attempts",
          "triggerEvent",
          "respectSendWindow",
          "heldUntil",
          "sentAt",
          "createdAt"
        ]
      },
      "MessageResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MessageDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "PaginationDto": {
        "type": "object",
        "properties": {
          "page": {
            "type": "number"
          },
          "pageSize": {
            "type": "number"
          },
          "totalItems": {
            "type": "number"
          },
          "totalPages": {
            "type": "number"
          },
          "hasNextPage": {
            "type": "boolean"
          },
          "hasPreviousPage": {
            "type": "boolean"
          }
        },
        "required": [
          "hasNextPage"
        ]
      },
      "PublicAddAudienceMembersDto": {
        "type": "object",
        "properties": {
          "contactIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "externalRefs": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 120
            }
          }
        }
      },
      "SandboxCapturedMessageDto": {
        "type": "object",
        "properties": {
          "channelType": {
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM"
            ],
            "type": "string"
          },
          "scenario": {
            "enum": [
              "delivered",
              "read",
              "failed",
              "replied",
              "opted_out",
              "no_receipt"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "organizationId": {
            "type": "string"
          },
          "channelId": {
            "type": "string"
          },
          "messageId": {
            "type": "string",
            "nullable": true
          },
          "recipientRef": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "text": {
            "type": "string"
          },
          "providerMessageId": {
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "channelType",
          "scenario",
          "id",
          "organizationId",
          "channelId",
          "messageId",
          "recipientRef",
          "subject",
          "text",
          "providerMessageId",
          "createdAt"
        ]
      },
      "SandboxCapturedMessageListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SandboxCapturedMessageDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "SandboxEventDto": {
        "type": "object",
        "properties": {
          "type": {
            "enum": [
              "delivered",
              "read",
              "failed",
              "replied",
              "opted_out"
            ],
            "type": "string"
          },
          "messageId": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "messageId"
        ]
      },
      "SandboxEventResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SandboxEventDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "ScheduleCampaignDto": {
        "type": "object",
        "properties": {
          "scheduledAt": {
            "type": "string"
          },
          "recurrence": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "scheduledAt"
        ]
      },
      "ScheduleCampaignResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignDto"
          },
          "capacityEstimate": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityEstimateDto"
              }
            ]
          }
        },
        "required": [
          "data",
          "capacityEstimate"
        ]
      },
      "SendMessageDto": {
        "type": "object",
        "properties": {
          "to": {
            "$ref": "#/components/schemas/ContactReferenceDto"
          },
          "channelId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "templateId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "respectSendWindow": {
            "type": "boolean"
          }
        },
        "required": [
          "to",
          "channelId"
        ]
      },
      "SendWindowInputDto": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "example": "08:00",
            "description": "Opening time, HH:mm (24-hour)."
          },
          "end": {
            "type": "string",
            "example": "20:00",
            "description": "Closing time, HH:mm. Earlier than start means the window runs past midnight."
          },
          "days": {
            "items": {
              "type": "number",
              "enum": [
                0,
                3,
                1,
                2,
                4,
                5,
                6
              ]
            },
            "example": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Days the window opens, 0 (Sunday) to 6 (Saturday).",
            "type": "array"
          },
          "timeZone": {
            "type": "string",
            "example": "Africa/Accra",
            "description": "IANA time zone used when a customer's own time zone isn't known."
          }
        },
        "required": [
          "start",
          "end",
          "days",
          "timeZone"
        ]
      },
      "StartContactImportDto": {
        "type": "object",
        "properties": {
          "rows": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactImportRowDto"
            }
          },
          "mode": {
            "type": "string",
            "enum": [
              "CREATE_ONLY",
              "UPSERT"
            ]
          },
          "attestedAcceptableUse": {
            "type": "boolean"
          }
        },
        "required": [
          "rows",
          "attestedAcceptableUse"
        ]
      },
      "SuppressionDto": {
        "type": "object",
        "properties": {
          "scope": {
            "enum": [
              "GLOBAL",
              "CHANNEL",
              "PURPOSE",
              "CAMPAIGN"
            ],
            "type": "string"
          },
          "channel": {
            "nullable": true,
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM",
              "ALL"
            ],
            "type": "string"
          },
          "purpose": {
            "nullable": true,
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "ALL"
            ],
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "id": {
            "type": "string"
          },
          "organizationId": {
            "type": "string"
          },
          "customerId": {
            "type": "string"
          },
          "campaignId": {
            "type": "string",
            "nullable": true
          },
          "reason": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "suppressedByUserId": {
            "type": "string",
            "nullable": true
          },
          "suppressedAt": {
            "format": "date-time",
            "type": "string"
          },
          "liftedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "liftedByUserId": {
            "type": "string",
            "nullable": true
          },
          "evidenceRef": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "scope",
          "channel",
          "purpose",
          "metadata",
          "id",
          "organizationId",
          "customerId",
          "campaignId",
          "reason",
          "source",
          "suppressedByUserId",
          "suppressedAt",
          "liftedAt",
          "liftedByUserId",
          "evidenceRef",
          "createdAt",
          "updatedAt"
        ]
      },
      "SuppressionListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuppressionDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "TemplateDto": {
        "type": "object",
        "properties": {
          "channelType": {
            "type": "string",
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "APPROVED",
              "ARCHIVED"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "body": {
            "type": "string"
          },
          "variables": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "approvedAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "channelType",
          "status",
          "id",
          "name",
          "subject",
          "body",
          "variables",
          "approvedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "TemplateListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "TenantInvitationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "expiresAt": {
            "format": "date-time",
            "type": "string"
          },
          "acceptUrl": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "email",
          "role",
          "status",
          "expiresAt",
          "acceptUrl"
        ]
      },
      "TenantInvitationResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenantInvitationDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "TenantOrganizationDto": {
        "type": "object",
        "properties": {
          "status": {
            "enum": [
              "ACTIVE",
              "SUSPENDED",
              "DEACTIVATED"
            ],
            "type": "string"
          },
          "trustTier": {
            "enum": [
              "NEW",
              "VERIFIED",
              "ESTABLISHED",
              "REVIEW_REQUIRED",
              "RESTRICTED",
              "SUSPENDED"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "externalRef": {
            "type": "string",
            "nullable": true
          },
          "country": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status",
          "trustTier",
          "id",
          "name",
          "externalRef",
          "country",
          "createdAt",
          "updatedAt"
        ]
      },
      "TenantOrganizationListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantOrganizationDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "TenantOrganizationResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenantOrganizationDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "TenantUsageDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "externalRef": {
            "type": "string",
            "nullable": true
          },
          "usage": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantUsageLineDto"
            }
          }
        },
        "required": [
          "organizationId",
          "name",
          "externalRef",
          "usage"
        ]
      },
      "TenantUsageLineDto": {
        "type": "object",
        "properties": {
          "usageType": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "used": {
            "type": "number"
          }
        },
        "required": [
          "usageType",
          "unit",
          "used"
        ]
      },
      "TenantUsageSummaryDto": {
        "type": "object",
        "properties": {
          "from": {
            "format": "date-time",
            "type": "string"
          },
          "to": {
            "format": "date-time",
            "type": "string"
          },
          "billingPeriodId": {
            "type": "string",
            "nullable": true
          },
          "tenants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantUsageDto"
            }
          }
        },
        "required": [
          "from",
          "to",
          "billingPeriodId",
          "tenants"
        ]
      },
      "TenantUsageSummaryResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TenantUsageSummaryDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "TransitionReasonDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "TriggerSandboxEventDto": {
        "type": "object",
        "properties": {
          "type": {
            "enum": [
              "delivered",
              "read",
              "failed",
              "replied",
              "opted_out"
            ],
            "type": "string"
          },
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000
          },
          "failureReason": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          }
        },
        "required": [
          "type"
        ]
      },
      "UpdateCampaignDto": {
        "type": "object",
        "properties": {
          "sendWindowMode": {
            "enum": [
              "ORGANIZATION",
              "CUSTOM",
              "NONE"
            ],
            "type": "string"
          },
          "sendWindow": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/SendWindowInputDto"
              }
            ]
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 160
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "type": {
            "enum": [
              "MARKETING",
              "TRANSACTIONAL",
              "INFORMATIONAL",
              "OPERATIONAL",
              "CUSTOMER_SUCCESS"
            ],
            "type": "string"
          },
          "audienceId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "channelId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "templateId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "messageHtml": {
            "type": "string",
            "maxLength": 50000
          },
          "trackLinks": {
            "type": "boolean"
          }
        }
      },
      "UpdateCustomerDto": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 32
          },
          "externalRef": {
            "type": "string",
            "maxLength": 120
          },
          "preferredLanguage": {
            "type": "string",
            "maxLength": 16
          },
          "timeZone": {
            "type": "string"
          },
          "tags": {
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 40
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "notes": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "UpdateTenantOrganizationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "externalRef": {
            "type": "string",
            "nullable": true,
            "maxLength": 120
          }
        }
      },
      "UpdateWebhookEndpointDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 8,
            "maxLength": 2048
          },
          "description": {
            "type": "string",
            "maxLength": 300
          },
          "eventTypes": {
            "type": "array",
            "uniqueItems": true,
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.read",
                "message.replied",
                "message.clicked",
                "message.failed",
                "message.skipped",
                "contact.opted_out",
                "consent.changed",
                "campaign.status_changed",
                "contact_import.completed",
                "usage.quota_low",
                "usage.quota_exhausted",
                "journey.enrolled",
                "journey.completed",
                "journey.exited"
              ]
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "includeTenantEvents": {
            "type": "boolean"
          }
        }
      },
      "UpsertContactDto": {
        "type": "object",
        "properties": {
          "created": {
            "type": "boolean"
          },
          "contact": {
            "$ref": "#/components/schemas/ContactDto"
          },
          "consent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentAssertionResultDto"
            }
          }
        },
        "required": [
          "created",
          "contact",
          "consent"
        ]
      },
      "UpsertContactInputDto": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 32
          },
          "preferredLanguage": {
            "type": "string",
            "maxLength": 16
          },
          "timeZone": {
            "type": "string"
          },
          "tags": {
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 40
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "notes": {
            "type": "string",
            "maxLength": 2000
          },
          "consent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConsentStatementDto"
            }
          }
        }
      },
      "UpsertContactResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UpsertContactDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "UsageAllowanceDto": {
        "type": "object",
        "properties": {
          "usageType": {
            "type": "string"
          },
          "unit": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/UsageAllowanceScopeDto"
          },
          "included": {
            "type": "number",
            "nullable": true
          },
          "hardLimit": {
            "type": "number",
            "nullable": true
          },
          "overageAllowed": {
            "type": "boolean"
          },
          "used": {
            "type": "number"
          },
          "pending": {
            "type": "number"
          },
          "remaining": {
            "type": "number",
            "nullable": true
          },
          "percentUsed": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "usageType",
          "unit",
          "scope",
          "included",
          "hardLimit",
          "overageAllowed",
          "used",
          "pending",
          "remaining",
          "percentUsed"
        ]
      },
      "UsageAllowanceScopeDto": {
        "type": "object",
        "properties": {
          "channelType": {
            "type": "string",
            "nullable": true,
            "enum": [
              "SMS",
              "EMAIL",
              "WHATSAPP",
              "TELEGRAM",
              "PUSH",
              "WEBHOOK",
              "CUSTOM"
            ]
          },
          "ownershipMode": {
            "type": "string",
            "nullable": true,
            "enum": [
              "BRING_YOUR_OWN_PROVIDER",
              "SENPEDE_MANAGED",
              "DEDICATED_MANAGED"
            ]
          },
          "provider": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "channelType",
          "ownershipMode",
          "provider"
        ]
      },
      "UsageBillingPeriodDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "startAt": {
            "format": "date-time",
            "type": "string"
          },
          "endAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "startAt",
          "endAt"
        ]
      },
      "UsagePlanDto": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "name"
        ]
      },
      "UsageSummaryDto": {
        "type": "object",
        "properties": {
          "plan": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/UsagePlanDto"
              }
            ]
          },
          "status": {
            "type": "string"
          },
          "billingPeriod": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/UsageBillingPeriodDto"
              }
            ]
          },
          "allowances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageAllowanceDto"
            }
          }
        },
        "required": [
          "plan",
          "status",
          "billingPeriod",
          "allowances"
        ]
      },
      "UsageSummaryResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UsageSummaryDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "WebhookDeliveryDto": {
        "type": "object",
        "properties": {
          "status": {
            "enum": [
              "PENDING",
              "SUCCEEDED",
              "FAILED",
              "DEAD"
            ],
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "endpointId": {
            "type": "string"
          },
          "eventId": {
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "attempts": {
            "type": "number"
          },
          "lastStatusCode": {
            "type": "number",
            "nullable": true
          },
          "lastError": {
            "type": "string",
            "nullable": true
          },
          "nextAttemptAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "deliveredAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "status",
          "id",
          "endpointId",
          "eventId",
          "eventType",
          "attempts",
          "lastStatusCode",
          "lastError",
          "nextAttemptAt",
          "deliveredAt",
          "createdAt"
        ]
      },
      "WebhookDeliveryListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationDto"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "WebhookDeliveryResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookDeliveryDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "WebhookEndpointDto": {
        "type": "object",
        "properties": {
          "eventTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.sent",
                "message.delivered",
                "message.read",
                "message.replied",
                "message.clicked",
                "message.failed",
                "message.skipped",
                "contact.opted_out",
                "consent.changed",
                "campaign.status_changed",
                "contact_import.completed",
                "usage.quota_low",
                "usage.quota_exhausted",
                "journey.enrolled",
                "journey.completed",
                "journey.exited"
              ]
            }
          },
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "enabled": {
            "type": "boolean"
          },
          "includeTenantEvents": {
            "type": "boolean"
          },
          "secretPrefix": {
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "eventTypes",
          "id",
          "url",
          "description",
          "enabled",
          "includeTenantEvents",
          "secretPrefix",
          "createdAt",
          "updatedAt"
        ]
      },
      "WebhookEndpointListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpointDto"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "WebhookEndpointResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookEndpointDto"
          }
        },
        "required": [
          "data"
        ]
      },
      "WebhookEndpointWithSecretDto": {
        "type": "object",
        "properties": {
          "endpoint": {
            "$ref": "#/components/schemas/WebhookEndpointDto"
          },
          "secret": {
            "type": "string"
          }
        },
        "required": [
          "endpoint",
          "secret"
        ]
      },
      "WebhookEndpointWithSecretResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookEndpointWithSecretDto"
          }
        },
        "required": [
          "data"
        ]
      }
    },
    "securitySchemes": {
      "api-key": {
        "scheme": "bearer",
        "bearerFormat": "sen_…",
        "type": "http",
        "description": "Organization API key, sent as `Authorization: Bearer sen_…`."
      },
      "oauth2": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://api.senpede.com/api/v1/oauth/token",
            "scopes": {
              "contacts:read": "contacts:read",
              "contacts:write": "contacts:write",
              "contacts:import": "contacts:import",
              "consent:write": "consent:write",
              "audiences:read": "audiences:read",
              "audiences:write": "audiences:write",
              "templates:read": "templates:read",
              "campaigns:read": "campaigns:read",
              "campaigns:write": "campaigns:write",
              "campaigns:send": "campaigns:send",
              "messages:send": "messages:send",
              "webhooks:manage": "webhooks:manage",
              "usage:read": "usage:read",
              "journeys:read": "journeys:read",
              "journeys:enroll": "journeys:enroll",
              "organizations:manage": "organizations:manage"
            }
          }
        },
        "description": "OAuth 2.0 client credentials: exchange an OAuth client’s client_id and client_secret for a short-lived access token, sent as `Authorization: Bearer …`."
      }
    }
  }
}
