openapi: 3.1.0 info: title: Outpost API version: "0.0.1" description: | The Outpost API is a REST-based JSON API for managing tenants, destinations, and publishing events. Outpost runs in two deployment models: **managed** (hosted by Hookdeck) and **self-hosted**. They differ in where the API is served and in which API key authenticates server-side calls. On managed Outpost, use a Hookdeck project API key from your Outpost project. On self-hosted Outpost, use the key set in the `API_KEY` environment variable. A few endpoints exist in one model only and say so in their description. contact: name: Outpost Support email: support@hookdeck.com url: https://hookdeck.com/docs/outpost security: - AdminApiKey: [] - TenantJwt: [] servers: - url: https://api.outpost.hookdeck.com/2025-07-01 description: Managed Outpost, hosted by Hookdeck at `api.outpost.hookdeck.com`. The Hookdeck Event Gateway API at `api.hookdeck.com` is a separate API. - url: http://localhost:3333/api/v1 description: Self-hosted Outpost, at its default local address. A deployed instance serves the same paths under its own host. components: securitySchemes: AdminApiKey: type: http scheme: bearer description: | Bearer token for server-side calls. Where it comes from depends on the deployment: - **Managed:** a Hookdeck **project API key belonging to your Outpost project** (Hookdeck Dashboard → your Outpost project → Settings → Secrets). A key from a different Hookdeck project authenticates but returns `404` on most Outpost routes. - **Self-hosted:** the admin API key set in the `API_KEY` environment variable. The scheme is named for the self-hosted credential. Managed Outpost has no separate admin key to create. The project API key takes its place. TenantJwt: type: http scheme: bearer bearerFormat: JWT description: | Per-tenant JWT token valid for 24 hours. **JWT Structure:** The token is a standard JWT signed with HS256 algorithm containing the following claims: - `iss` (issuer): Always "outpost" - `sub` (subject): The tenant_id this token is scoped to - `iat` (issued at): Unix timestamp when the token was created - `exp` (expiration): Unix timestamp when the token expires (24 hours after issuance) **Example decoded payload:** ```json { "iss": "outpost", "sub": "tenant_123", "iat": 1704067200, "exp": 1704153600 } ``` responses: BadRequest: description: Malformed JSON or invalid request parameters. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" Unauthorized: description: Missing or invalid authentication credentials. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" Forbidden: description: The credentials are valid but not allowed to perform the request. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" NotFound: description: Requested resource not found. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" ValidationError: description: Request body fails validation. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" InternalServerError: description: Unexpected server error. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" schemas: # Shared Query Schemas Operator: type: object description: Comparison operators for filtering by date-time values (RFC3339 or YYYY-MM-DD format). properties: gte: type: string format: date-time description: Filter with value >= the specified date-time. lte: type: string format: date-time description: Filter with value <= the specified date-time. gt: type: string format: date-time description: Filter with value > the specified date-time. lt: type: string format: date-time description: Filter with value < the specified date-time. # Base Schemas Tenant: type: object properties: id: type: string description: User-defined system ID for the tenant. example: "123" destinations_count: type: integer description: Number of destinations associated with the tenant. example: 5 topics: type: array items: type: string description: List of subscribed topics across all destinations for this tenant. example: ["user.created", "user.deleted"] metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary key-value pairs for storing contextual information about the tenant. example: { "name": "Acme Inc." } created_at: type: string format: date-time description: ISO Date when the tenant was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the tenant was last updated. example: "2024-01-01T00:00:00Z" TenantUpsert: type: object properties: metadata: type: object additionalProperties: type: string nullable: true description: Optional key/value metadata to store with the tenant. TenantPaginatedResult: type: object description: Paginated list of tenants. properties: models: type: array items: $ref: "#/components/schemas/Tenant" description: Array of tenant objects. pagination: $ref: "#/components/schemas/SeekPagination" count: type: integer description: Total count of all tenants. example: 42 PortalRedirect: type: object properties: redirect_url: type: string format: url description: Redirect URL containing a JWT to authenticate the user with the portal. example: "https://webhooks.acme.com/?token=JWT_TOKEN&tenant_id=tenant_123" tenant_id: type: string description: The ID of the tenant associated with this portal session. example: "tenant_123" TenantToken: type: object properties: token: type: string description: JWT token scoped to the tenant for safe browser API calls. example: "SOME_JWT_TOKEN" tenant_id: type: string description: The ID of the tenant this token is scoped to. example: "tenant_123" SuccessResponse: type: object properties: success: type: boolean example: true Topics: oneOf: - type: string enum: ["*"] - type: array items: type: string description: '"*" or an array of enabled topics. Topic strings can include "*" as a wildcard matching any run of characters. When available topics are configured, wildcard patterns must match at least one available topic.' example: "*" Filter: type: object nullable: true additionalProperties: true description: | Optional JSON schema filter for event matching. Events must match this filter to be delivered to this destination. Supports operators: $eq, $neq, $gt, $gte, $lt, $lte, $in, $nin, $startsWith, $endsWith, $exist, $or, $and, $not. If null or empty, all events matching the topic filter will be delivered. Uses full-replacement semantics on update: send a new object to replace, null or `{}` to clear, omit for no change. example: data: amount: $gte: 100 customer: tier: "premium" SeekPagination: type: object description: Cursor-based pagination metadata for list responses. properties: order_by: type: string description: The field being sorted on. example: "created_at" dir: type: string enum: [asc, desc] description: Sort direction. example: "desc" limit: type: integer description: Page size limit. example: 100 next: type: string nullable: true description: Cursor for the next page of results. Null if no more results. example: "MTcwNDA2NzIwMA==" prev: type: string nullable: true description: Cursor for the previous page of results. Null if on first page. example: null APIErrorResponse: type: object description: Standard error response format. properties: status: type: integer description: HTTP status code. example: 422 message: type: string description: Human-readable error message. example: "validation error" data: description: Additional error details. For validation errors, this is an array of human-readable messages. oneOf: - type: array items: type: string description: Array of validation error messages. example: ["email is required", "password must be at least 6 characters"] - type: object additionalProperties: true description: Additional contextual data about the error. # Destination Type Specific Config/Credentials Schemas WebhookConfig: type: object required: [url] properties: url: type: string format: url description: The URL to send the webhook events to. example: "https://example.com/webhooks/user" custom_headers: type: string description: JSON string of custom HTTP headers to include with every webhook request. Header names must be valid HTTP header tokens (alphanumeric, hyphens, underscores). Reserved headers (Content-Type, Host, etc.) cannot be overridden. example: '{"x-api-key":"secret123","x-tenant-id":"customer-456"}' WebhookCredentials: type: object properties: secret: type: string description: The secret used for signing webhook requests. Auto-generated if omitted on creation by admin. Read-only for tenants unless rotating. example: "whsec_abc123" previous_secret: type: string description: The previous secret used during rotation. Valid for 24 hours by default. Read-only. example: "whsec_xyz789" previous_secret_invalid_at: type: string format: date-time description: ISO timestamp when the previous secret becomes invalid. Read-only. example: "2024-01-02T00:00:00Z" AWSSQSConfig: type: object required: [queue_url] properties: endpoint: type: string format: url description: Optional. Custom AWS endpoint URL (e.g., for LocalStack or specific regions). example: "https://sqs.us-east-1.amazonaws.com" # Corrected Example queue_url: type: string format: url # Technically an ARN/URL hybrid, but URL format is close enough description: The URL of the SQS queue. example: "https://sqs.us-east-1.amazonaws.com/123456789012/my-queue" AWSSQSCredentials: type: object required: [key, secret] properties: key: type: string description: AWS Access Key ID. example: "AKIAIOSFODNN7EXAMPLE" secret: type: string description: AWS Secret Access Key. example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" session: type: string description: Optional AWS Session Token (for temporary credentials). example: "AQoDYXdzEPT//////////wEXAMPLE..." CloudflareQueuesConfig: type: object required: [account_id, queue_id] properties: account_id: type: string description: Cloudflare Account ID (32-character hex string). pattern: "^[0-9a-f]{32}$" example: "023e105f4ecef8ad9ca31a8372d0c353" queue_id: type: string description: Cloudflare Queue ID (32-character hex string, not the queue name). pattern: "^[0-9a-f]{32}$" example: "9d7d4cf8a3a14d9aaeb50c3e74e2f4b1" CloudflareQueuesCredentials: type: object required: [api_token] properties: api_token: type: string description: Cloudflare API Token with the Account > Queues > Edit (Queues Write) permission, scoped to the target account. example: "v1.0-1234567890abcdef..." AWSEventBridgeConfig: type: object required: [region] properties: event_bus_name: type: string description: Optional. The name or ARN of the EventBridge event bus. Defaults to the account's default event bus. example: "my-event-bus" region: type: string description: The AWS region where the event bus is located. example: "us-east-1" endpoint: type: string format: url description: Optional. Custom AWS endpoint URL (e.g., for LocalStack or VPC endpoints). example: "https://events.us-east-1.amazonaws.com" AWSEventBridgeCredentials: type: object required: [key, secret] properties: key: type: string description: AWS Access Key ID. example: "AKIAIOSFODNN7EXAMPLE" secret: type: string description: AWS Secret Access Key. example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" session: type: string description: Optional AWS Session Token (for temporary credentials). example: "AQoDYXdzEPT//////////wEXAMPLE..." RabbitMQConfig: type: object required: [server_url, exchange] properties: server_url: type: string description: RabbitMQ server address (host:port). example: "localhost:5672" exchange: type: string description: The exchange to publish messages to. example: "my-exchange" tls: type: string enum: ["true", "false"] description: Whether to use TLS connection (amqps). Defaults to "false". example: "false" RabbitMQCredentials: type: object required: [username, password] properties: username: type: string description: RabbitMQ username. example: "guest" password: type: string description: RabbitMQ password. example: "guest" HookdeckCredentials: # Hookdeck has no config fields, only credentials type: object required: [token] properties: token: type: string description: Hookdeck authentication token. example: "hd_token_..." AWSKinesisConfig: type: object required: [stream_name, region] properties: stream_name: type: string description: The name of the AWS Kinesis stream. example: "my-data-stream" region: type: string description: The AWS region where the Kinesis stream is located. example: "us-east-1" endpoint: type: string format: url description: Optional. Custom AWS endpoint URL (e.g., for LocalStack or VPC endpoints). example: "https://kinesis.us-east-1.amazonaws.com" partition_key_template: type: string description: Optional. JMESPath template to extract the partition key from the event payload (e.g., `metadata."event-id"`). Defaults to event ID. example: 'data."user_id"' AWSKinesisCredentials: type: object required: [key, secret] properties: key: type: string description: AWS Access Key ID. example: "AKIAIOSFODNN7EXAMPLE" secret: type: string description: AWS Secret Access Key. example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" session: type: string description: Optional AWS Session Token (for temporary credentials). example: "AQoDYXdzEPT//////////wEXAMPLE..." AzureServiceBusConfig: type: object required: [name] properties: name: type: string description: The name of the Azure Service Bus queue or topic to publish messages to. example: "my-queue-or-topic" AzureServiceBusCredentials: type: object required: [connection_string] properties: connection_string: type: string description: The connection string for the Azure Service Bus namespace. example: "Endpoint=sb://namespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=abc123" AWSS3Config: type: object required: [bucket, region] properties: bucket: type: string description: The name of your AWS S3 bucket. example: "my-bucket" region: type: string description: The AWS region where your bucket is located. pattern: "^[a-z]{2}-[a-z]+-[0-9]+$" example: "us-east-1" key_template: type: string description: JMESPath expression for generating S3 object keys. Default is join('', [time.rfc3339_nano, '_', metadata."event-id", '.json']). example: 'join(''/'', [time.year, time.month, time.day, metadata."event-id", ''.json''])' storage_class: type: string description: The storage class for the S3 objects (e.g., STANDARD, INTELLIGENT_TIERING, GLACIER, etc.). Defaults to "STANDARD". example: "STANDARD" AWSS3Credentials: type: object required: [key, secret] properties: key: type: string description: AWS Access Key ID. example: "AKIAIOSFODNN7EXAMPLE" secret: type: string description: AWS Secret Access Key. example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" session: type: string description: Optional AWS Session Token (for temporary credentials). example: "AQoDYXdzEPT//////////wEXAMPLE..." GCPPubSubConfig: type: object required: [project_id, topic] properties: project_id: type: string description: The GCP project ID. example: "my-project-123" topic: type: string description: The Pub/Sub topic name. example: "events-topic" endpoint: type: string description: Optional. Custom endpoint URL (e.g., localhost:8085 for emulator). example: "pubsub.googleapis.com:443" GCPPubSubCredentials: type: object required: [service_account_json] properties: service_account_json: type: string description: Service account key JSON. The entire JSON key file content as a string. example: '{"type":"service_account","project_id":"my-project","private_key_id":"key123","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n","client_email":"my-service@my-project.iam.gserviceaccount.com"}' KafkaConfig: type: object required: [brokers, topic, sasl_mechanism] properties: brokers: type: string description: Comma-separated list of Kafka broker addresses. example: "broker1.example.com:9092,broker2.example.com:9092" topic: type: string description: The Kafka topic to publish messages to. example: "events" sasl_mechanism: type: string enum: [plain, scram-sha-256, scram-sha-512] description: SASL authentication mechanism. example: "scram-sha-256" tls: type: string enum: ["true", "false"] description: Whether to enable TLS for the connection. default: "true" example: "true" partition_key_template: type: string description: Optional JMESPath template to extract the partition key from the event payload. Defaults to the event ID. example: "data.customer_id" KafkaCredentials: type: object required: [username, password] properties: username: type: string description: SASL username for authentication. example: "outpost" password: type: string description: SASL password for authentication. example: "secure_password_123" # Type-Specific Destination Schemas (for Responses) DestinationWebhook: type: object x-docs-type: "Webhook" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [webhook] example: "webhook" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/WebhookConfig" credentials: $ref: "#/components/schemas/WebhookCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (e.g., URL host). Read-only. readOnly: true example: "my-service.com" target_url: type: string format: url nullable: true # Should always have a URL for webhook description: A URL link to the destination target (the webhook URL). Read-only. readOnly: true example: "https://my-service.com/webhook/handler" example: id: "des_webhook_123" type: "webhook" topics: ["user.created", "order.shipped"] disabled_at: null created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/handler" credentials: secret: "whsec_abc123def456" previous_secret: "whsec_prev789xyz012" previous_secret_invalid_at: "2024-02-16T10:00:00Z" DestinationAWSSQS: type: object x-docs-type: "AWS SQS" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [aws_sqs] example: "aws_sqs" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/AWSSQSConfig" credentials: $ref: "#/components/schemas/AWSSQSCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (SQS queue name). Read-only. readOnly: true example: "my-app-queue" target_url: type: string format: url nullable: true # Can construct AWS console URL description: A URL link to the destination target (AWS Console link to the queue). Read-only. readOnly: true example: "https://us-west-2.console.aws.amazon.com/sqs/v2/home?region=us-west-2#/queues/https%3A%2F%2Fsqs.us-west-2.amazonaws.com%2F123456789012%2Fmy-app-queue" example: id: "des_sqs_456" type: "aws_sqs" topics: ["*"] disabled_at: "2024-03-01T12:00:00Z" created_at: "2024-02-20T11:30:00Z" updated_at: "2024-02-20T11:30:00Z" config: queue_url: "https://sqs.us-west-2.amazonaws.com/123456789012/my-app-queue" endpoint: "https://sqs.us-west-2.amazonaws.com" credentials: key: "AKIAIOSFODNN7EXAMPLE" secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" DestinationRabbitMQ: type: object x-docs-type: "RabbitMQ" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [rabbitmq] example: "rabbitmq" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/RabbitMQConfig" credentials: $ref: "#/components/schemas/RabbitMQCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (RabbitMQ exchange). Read-only. readOnly: true example: "events-exchange" target_url: type: string format: url nullable: true # No direct URL for an exchange description: A URL link to the destination target (not applicable for RabbitMQ exchange). Read-only. readOnly: true example: null example: id: "des_rmq_789" type: "rabbitmq" topics: ["inventory.updated"] disabled_at: null created_at: "2024-01-10T09:00:00Z" updated_at: "2024-01-10T09:00:00Z" config: server_url: "amqp.cloudamqp.com:5671" exchange: "events-exchange" tls: "true" credentials: username: "app_user" password: "secure_password_123" DestinationHookdeck: type: object x-docs-type: "Hookdeck Event Gateway" # Properties duplicated from DestinationBase required: [id, type, topics, credentials, created_at, disabled_at] # No config properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [hookdeck] example: "hookdeck" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: {} # Empty config credentials: $ref: "#/components/schemas/HookdeckCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (Hookdeck). Read-only. readOnly: true example: "Hookdeck" target_url: type: string format: url nullable: true # Link to Hookdeck dashboard? TBD description: A URL link to the destination target (e.g., Hookdeck dashboard). Read-only. readOnly: true example: "https://dashboard.hookdeck.com/sources/src_xxxyyyzzz" example: id: "des_hkd_abc" type: "hookdeck" topics: ["*"] disabled_at: null created_at: "2024-04-01T10:00:00Z" updated_at: "2024-04-01T10:00:00Z" config: {} credentials: token: "hd_token_..." DestinationAWSKinesis: type: object x-docs-type: "AWS Kinesis" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [aws_kinesis] example: "aws_kinesis" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/AWSKinesisConfig" credentials: $ref: "#/components/schemas/AWSKinesisCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (Kinesis stream name). Read-only. readOnly: true example: "production-events" target_url: type: string format: url nullable: true # Can construct AWS console URL description: A URL link to the destination target (AWS Console link to the stream). Read-only. readOnly: true example: "https://eu-west-1.console.aws.amazon.com/kinesis/home?region=eu-west-1#/streams/details/production-events/details" example: id: "des_kns_xyz" type: "aws_kinesis" topics: ["user.created", "user.updated"] disabled_at: null created_at: "2024-03-10T15:30:00Z" updated_at: "2024-03-10T15:30:00Z" config: stream_name: "production-events" region: "eu-west-1" credentials: key: "AKIAIOSFODNN7EXAMPLE" secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" DestinationAzureServiceBus: type: object x-docs-type: "Azure Service Bus" required: [id, type, topics, config, credentials, created_at, disabled_at] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [azure_servicebus] example: "azure_servicebus" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/AzureServiceBusConfig" credentials: $ref: "#/components/schemas/AzureServiceBusCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (Azure Service Bus queue/topic name). Read-only. readOnly: true example: "my-queue-or-topic" target_url: type: string format: url nullable: true # Can construct Azure portal URL description: A URL link to the destination target (Azure Portal link to the Service Bus). Read-only. readOnly: true example: "https://portal.azure.com/#@tenant-id/resource/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.ServiceBus/namespaces/namespace-name/queues/queue-name" example: id: "des_azuresb_123" type: "azure_servicebus" topics: ["*"] disabled_at: null created_at: "2024-05-01T10:00:00Z" updated_at: "2024-05-01T10:00:00Z" config: name: "my-queue-or-topic" credentials: connection_string: "Endpoint=sb://namespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=abc123" DestinationAWSS3: type: object x-docs-type: "AWS S3" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [aws_s3] example: "aws_s3" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/AWSS3Config" credentials: $ref: "#/components/schemas/AWSS3Credentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (bucket and region). Read-only. readOnly: true example: "my-bucket in us-east-1" target_url: type: string format: url nullable: true description: A URL link to the destination target (AWS Console link to the bucket). Read-only. readOnly: true example: null example: id: "des_s3_789" type: "aws_s3" topics: ["*"] disabled_at: null created_at: "2024-03-20T12:00:00Z" updated_at: "2024-03-20T12:00:00Z" config: bucket: "my-bucket" region: "us-east-1" credentials: key: "AKIAIOSFODNN7EXAMPLE" secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" DestinationGCPPubSub: type: object x-docs-type: "GCP PubSub" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [gcp_pubsub] example: "gcp_pubsub" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/GCPPubSubConfig" credentials: $ref: "#/components/schemas/GCPPubSubCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (project/topic). Read-only. readOnly: true example: "my-project-123/events-topic" target_url: type: string format: url nullable: true description: A URL link to the destination target (GCP Console link to the topic). Read-only. readOnly: true example: "https://console.cloud.google.com/cloudpubsub/topic/detail/events-topic?project=my-project-123" example: id: "des_gcp_pubsub_123" type: "gcp_pubsub" topics: ["order.created", "order.updated"] disabled_at: null created_at: "2024-03-10T14:30:00Z" updated_at: "2024-03-10T14:30:00Z" config: project_id: "my-project-123" topic: "events-topic" credentials: service_account_json: '{"type":"service_account","project_id":"my-project-123",...}' DestinationKafka: type: object x-docs-type: "Apache Kafka" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [kafka] example: "kafka" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/KafkaConfig" credentials: $ref: "#/components/schemas/KafkaCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (broker and topic). Read-only. readOnly: true example: "broker1.example.com:9092 / events" target_url: type: string format: url nullable: true description: A URL link to the destination target. Read-only. readOnly: true example: null example: id: "des_kafka_123" type: "kafka" topics: ["order.created", "order.updated"] disabled_at: null created_at: "2024-03-10T14:30:00Z" updated_at: "2024-03-10T14:30:00Z" config: brokers: "broker1.example.com:9092,broker2.example.com:9092" topic: "events" sasl_mechanism: "scram-sha-256" tls: "true" credentials: username: "outpost" password: "secure_password_123" DestinationCloudflareQueues: type: object x-docs-type: "Cloudflare Queues" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [cloudflare_queues] example: "cloudflare_queues" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/CloudflareQueuesConfig" credentials: $ref: "#/components/schemas/CloudflareQueuesCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (Cloudflare Queue ID). Read-only. readOnly: true example: "9d7d4cf8a3a14d9aaeb50c3e74e2f4b1" target_url: type: string format: url nullable: true description: A URL link to the Cloudflare dashboard queues list for the account. Read-only. readOnly: true example: "https://dash.cloudflare.com/023e105f4ecef8ad9ca31a8372d0c353/workers/queues" example: id: "des_cf_queues_123" type: "cloudflare_queues" topics: ["*"] disabled_at: null created_at: "2024-03-10T14:30:00Z" updated_at: "2024-03-10T14:30:00Z" config: account_id: "023e105f4ecef8ad9ca31a8372d0c353" queue_id: "9d7d4cf8a3a14d9aaeb50c3e74e2f4b1" credentials: api_token: "v1.0-1234567890abcdef..." DestinationAWSEventBridge: type: object x-docs-type: "AWS EventBridge" # Properties duplicated from DestinationBase required: [ id, type, topics, config, credentials, created_at, updated_at, disabled_at, ] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" type: type: string description: Type of the destination. enum: [aws_eventbridge] example: "aws_eventbridge" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" config: $ref: "#/components/schemas/AWSEventBridgeConfig" credentials: $ref: "#/components/schemas/AWSEventBridgeCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } target: type: string description: A human-readable representation of the destination target (event bus name and region, or the event bus ARN). Read-only. readOnly: true example: "my-event-bus in us-east-1" target_url: type: string format: url nullable: true description: A URL link to the destination target (AWS Console link to the event bus). Null when the event bus is given as an ARN. Read-only. readOnly: true example: "https://us-east-1.console.aws.amazon.com/events/home?region=us-east-1#/eventbus/my-event-bus" example: id: "des_evb_123" type: "aws_eventbridge" topics: ["*"] disabled_at: null created_at: "2024-03-10T14:30:00Z" updated_at: "2024-03-10T14:30:00Z" config: event_bus_name: "my-event-bus" region: "us-east-1" credentials: key: "AKIAIOSFODNN7EXAMPLE" secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" # Polymorphic Destination Schema (for Responses) Destination: oneOf: - $ref: "#/components/schemas/DestinationWebhook" - $ref: "#/components/schemas/DestinationHookdeck" - $ref: "#/components/schemas/DestinationAWSSQS" - $ref: "#/components/schemas/DestinationAWSKinesis" - $ref: "#/components/schemas/DestinationAWSS3" - $ref: "#/components/schemas/DestinationRabbitMQ" - $ref: "#/components/schemas/DestinationAzureServiceBus" - $ref: "#/components/schemas/DestinationGCPPubSub" - $ref: "#/components/schemas/DestinationKafka" - $ref: "#/components/schemas/DestinationCloudflareQueues" - $ref: "#/components/schemas/DestinationAWSEventBridge" discriminator: propertyName: type mapping: webhook: "#/components/schemas/DestinationWebhook" aws_sqs: "#/components/schemas/DestinationAWSSQS" rabbitmq: "#/components/schemas/DestinationRabbitMQ" hookdeck: "#/components/schemas/DestinationHookdeck" aws_kinesis: "#/components/schemas/DestinationAWSKinesis" azure_servicebus: "#/components/schemas/DestinationAzureServiceBus" aws_s3: "#/components/schemas/DestinationAWSS3" gcp_pubsub: "#/components/schemas/DestinationGCPPubSub" kafka: "#/components/schemas/DestinationKafka" cloudflare_queues: "#/components/schemas/DestinationCloudflareQueues" aws_eventbridge: "#/components/schemas/DestinationAWSEventBridge" DestinationCreateWebhook: type: object x-docs-type: "Webhook" required: [type, topics, config] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'webhook'. enum: [webhook] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/WebhookConfig" credentials: # Secret is optional on create for admin, forbidden for tenant $ref: "#/components/schemas/WebhookCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateAWSSQS: type: object x-docs-type: "AWS SQS" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'aws_sqs'. enum: [aws_sqs] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSSQSConfig" credentials: $ref: "#/components/schemas/AWSSQSCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateRabbitMQ: type: object x-docs-type: "RabbitMQ" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'rabbitmq'. enum: [rabbitmq] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/RabbitMQConfig" credentials: $ref: "#/components/schemas/RabbitMQCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateHookdeck: type: object x-docs-type: "Hookdeck Event Gateway" required: [type, topics, credentials] # No config properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'hookdeck'. enum: [hookdeck] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: {} credentials: $ref: "#/components/schemas/HookdeckCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateAWSKinesis: type: object x-docs-type: "AWS Kinesis" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'aws_kinesis'. enum: [aws_kinesis] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSKinesisConfig" credentials: $ref: "#/components/schemas/AWSKinesisCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateAzureServiceBus: type: object x-docs-type: "Azure Service Bus" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'azure_servicebus'. enum: [azure_servicebus] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AzureServiceBusConfig" credentials: $ref: "#/components/schemas/AzureServiceBusCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateAWSS3: type: object x-docs-type: "AWS S3" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'aws_s3'. enum: [aws_s3] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSS3Config" credentials: $ref: "#/components/schemas/AWSS3Credentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateGCPPubSub: type: object x-docs-type: "GCP PubSub" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'gcp_pubsub'. enum: [gcp_pubsub] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/GCPPubSubConfig" credentials: $ref: "#/components/schemas/GCPPubSubCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateKafka: type: object x-docs-type: "Apache Kafka" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'kafka'. enum: [kafka] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/KafkaConfig" credentials: $ref: "#/components/schemas/KafkaCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateCloudflareQueues: type: object x-docs-type: "Cloudflare Queues" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'cloudflare_queues'. enum: [cloudflare_queues] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/CloudflareQueuesConfig" credentials: $ref: "#/components/schemas/CloudflareQueuesCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null DestinationCreateAWSEventBridge: type: object x-docs-type: "AWS EventBridge" required: [type, topics, config, credentials] properties: id: type: string description: Optional user-provided ID. An ID will be generated if empty. example: "user-provided-id" type: type: string description: Type of the destination. Must be 'aws_eventbridge'. enum: [aws_eventbridge] topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSEventBridgeConfig" credentials: $ref: "#/components/schemas/AWSEventBridgeCredentials" delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } created_at: type: string format: date-time nullable: true description: >- Optional override for the creation timestamp. Intended for importing destinations from another system. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to the current time when omitted. example: "2024-02-15T10:00:00Z" updated_at: type: string format: date-time nullable: true description: >- Optional override for the last-updated timestamp. Intended for importing destinations. Must not be in the future. **Admin (API key) auth only — sending this with JWT auth returns 403.** Defaults to created_at when omitted. example: "2024-02-15T10:00:00Z" disabled_at: type: string format: date-time nullable: true description: >- If set, the destination is created in a disabled state with this timestamp. Must not be in the future. Defaults to null (enabled). example: null # Polymorphic Destination Creation Schema (for Request Bodies) DestinationCreate: oneOf: - $ref: "#/components/schemas/DestinationCreateWebhook" - $ref: "#/components/schemas/DestinationCreateHookdeck" - $ref: "#/components/schemas/DestinationCreateAWSSQS" - $ref: "#/components/schemas/DestinationCreateAWSKinesis" - $ref: "#/components/schemas/DestinationCreateAWSS3" - $ref: "#/components/schemas/DestinationCreateAzureServiceBus" - $ref: "#/components/schemas/DestinationCreateRabbitMQ" - $ref: "#/components/schemas/DestinationCreateGCPPubSub" - $ref: "#/components/schemas/DestinationCreateKafka" - $ref: "#/components/schemas/DestinationCreateCloudflareQueues" - $ref: "#/components/schemas/DestinationCreateAWSEventBridge" discriminator: propertyName: type mapping: webhook: "#/components/schemas/DestinationCreateWebhook" aws_sqs: "#/components/schemas/DestinationCreateAWSSQS" rabbitmq: "#/components/schemas/DestinationCreateRabbitMQ" hookdeck: "#/components/schemas/DestinationCreateHookdeck" aws_kinesis: "#/components/schemas/DestinationCreateAWSKinesis" azure_servicebus: "#/components/schemas/DestinationCreateAzureServiceBus" aws_s3: "#/components/schemas/DestinationCreateAWSS3" gcp_pubsub: "#/components/schemas/DestinationCreateGCPPubSub" kafka: "#/components/schemas/DestinationCreateKafka" cloudflare_queues: "#/components/schemas/DestinationCreateCloudflareQueues" aws_eventbridge: "#/components/schemas/DestinationCreateAWSEventBridge" # Type-Specific Destination Update Schemas (for Request Bodies) # Type-Specific Partial Schemas for PATCH Request Bodies # All fields are optional — RFC 7396 JSON merge-patch semantics apply: # omit a field to leave it unchanged; include a field to update it in place. WebhookConfigUpdate: type: object description: Partial Webhook config for PATCH updates (RFC 7396 merge-patch). properties: url: type: string format: url description: The URL to send the webhook events to. example: "https://example.com/webhooks/user" custom_headers: type: string description: JSON string of custom HTTP headers to include with every webhook request. example: '{"x-api-key":"secret123","x-tenant-id":"customer-456"}' WebhookCredentialsUpdate: type: object description: Partial Webhook credentials for PATCH updates (RFC 7396 merge-patch). properties: secret: type: string description: New secret (only allowed for admin). previous_secret: type: string description: Previous secret for rotation (only allowed for admin). previous_secret_invalid_at: type: string format: date-time description: Invalidation time for previous secret (only allowed for admin). rotate_secret: type: boolean description: Set to true to rotate the secret. The current secret becomes the previous_secret, and a new secret is generated. `previous_secret_invalid_at` defaults to 24h if not provided. AWSSQSConfigUpdate: type: object description: Partial AWS SQS config for PATCH updates (RFC 7396 merge-patch). properties: endpoint: type: string format: url description: Optional. Custom AWS endpoint URL (e.g., for LocalStack or specific regions). example: "https://sqs.us-east-1.amazonaws.com" queue_url: type: string format: url description: The URL of the SQS queue. example: "https://sqs.us-east-1.amazonaws.com/123456789012/my-queue" AWSSQSCredentialsUpdate: type: object description: Partial AWS SQS credentials for PATCH updates (RFC 7396 merge-patch). properties: key: type: string description: AWS Access Key ID. secret: type: string description: AWS Secret Access Key. session: type: string description: Optional AWS Session Token (for temporary credentials). RabbitMQConfigUpdate: type: object description: Partial RabbitMQ config for PATCH updates (RFC 7396 merge-patch). properties: server_url: type: string description: RabbitMQ server address (host:port). exchange: type: string description: The exchange to publish messages to. tls: type: string enum: ["true", "false"] description: Whether to use TLS connection (amqps). RabbitMQCredentialsUpdate: type: object description: Partial RabbitMQ credentials for PATCH updates (RFC 7396 merge-patch). properties: username: type: string description: RabbitMQ username. password: type: string description: RabbitMQ password. HookdeckCredentialsUpdate: type: object description: Partial Hookdeck credentials for PATCH updates (RFC 7396 merge-patch). properties: token: type: string description: Hookdeck authentication token. AWSKinesisConfigUpdate: type: object description: Partial AWS Kinesis config for PATCH updates (RFC 7396 merge-patch). properties: stream_name: type: string description: The name of the AWS Kinesis stream. region: type: string description: The AWS region where the Kinesis stream is located. endpoint: type: string format: url description: Optional. Custom AWS endpoint URL (e.g., for LocalStack or VPC endpoints). partition_key_template: type: string description: Optional. JMESPath template to extract the partition key from the event payload. AWSKinesisCredentialsUpdate: type: object description: Partial AWS Kinesis credentials for PATCH updates (RFC 7396 merge-patch). properties: key: type: string description: AWS Access Key ID. secret: type: string description: AWS Secret Access Key. session: type: string description: Optional AWS Session Token (for temporary credentials). AzureServiceBusConfigUpdate: type: object description: Partial Azure Service Bus config for PATCH updates (RFC 7396 merge-patch). properties: name: type: string description: The name of the Azure Service Bus queue or topic to publish messages to. AzureServiceBusCredentialsUpdate: type: object description: Partial Azure Service Bus credentials for PATCH updates (RFC 7396 merge-patch). properties: connection_string: type: string description: The connection string for the Azure Service Bus namespace. AWSS3ConfigUpdate: type: object description: Partial AWS S3 config for PATCH updates (RFC 7396 merge-patch). properties: bucket: type: string description: The name of your AWS S3 bucket. region: type: string pattern: "^[a-z]{2}-[a-z]+-[0-9]+$" description: The AWS region where your bucket is located. key_template: type: string description: JMESPath expression for generating S3 object keys. storage_class: type: string description: The storage class for the S3 objects. AWSS3CredentialsUpdate: type: object description: Partial AWS S3 credentials for PATCH updates (RFC 7396 merge-patch). properties: key: type: string description: AWS Access Key ID. secret: type: string description: AWS Secret Access Key. session: type: string description: Optional AWS Session Token (for temporary credentials). GCPPubSubConfigUpdate: type: object description: Partial GCP Pub/Sub config for PATCH updates (RFC 7396 merge-patch). properties: project_id: type: string description: The GCP project ID. topic: type: string description: The Pub/Sub topic name. endpoint: type: string description: Optional. Custom endpoint URL (e.g., localhost:8085 for emulator). GCPPubSubCredentialsUpdate: type: object description: Partial GCP Pub/Sub credentials for PATCH updates (RFC 7396 merge-patch). properties: service_account_json: type: string description: Service account key JSON. The entire JSON key file content as a string. KafkaConfigUpdate: type: object description: Partial Kafka config for PATCH updates (RFC 7396 merge-patch). properties: brokers: type: string description: Comma-separated list of Kafka broker addresses. topic: type: string description: The Kafka topic to publish messages to. sasl_mechanism: type: string enum: [plain, scram-sha-256, scram-sha-512] description: SASL authentication mechanism. tls: type: string enum: ["true", "false"] description: Whether to enable TLS for the connection. partition_key_template: type: string description: Optional JMESPath template to extract the partition key from the event payload. KafkaCredentialsUpdate: type: object description: Partial Kafka credentials for PATCH updates (RFC 7396 merge-patch). properties: username: type: string description: SASL username for authentication. password: type: string description: SASL password for authentication. CloudflareQueuesConfigUpdate: type: object description: Partial Cloudflare Queues config for PATCH updates (RFC 7396 merge-patch). properties: account_id: type: string description: Cloudflare Account ID (32-character hex string). pattern: "^[0-9a-f]{32}$" queue_id: type: string description: Cloudflare Queue ID (32-character hex string, not the queue name). pattern: "^[0-9a-f]{32}$" CloudflareQueuesCredentialsUpdate: type: object description: Partial Cloudflare Queues credentials for PATCH updates (RFC 7396 merge-patch). properties: api_token: type: string description: Cloudflare API Token with the Account > Queues > Edit (Queues Write) permission, scoped to the target account. AWSEventBridgeConfigUpdate: type: object description: Partial AWS EventBridge config for PATCH updates (RFC 7396 merge-patch). properties: event_bus_name: type: string description: Optional. The name or ARN of the EventBridge event bus. Defaults to the account's default event bus. region: type: string description: The AWS region where the event bus is located. endpoint: type: string format: url description: Optional. Custom AWS endpoint URL (e.g., for LocalStack or VPC endpoints). AWSEventBridgeCredentialsUpdate: type: object description: Partial AWS EventBridge credentials for PATCH updates (RFC 7396 merge-patch). properties: key: type: string description: AWS Access Key ID. secret: type: string description: AWS Secret Access Key. session: type: string description: Optional AWS Session Token (for temporary credentials). DestinationUpdateWebhook: type: object x-docs-type: "Webhook" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [webhook] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "webhook" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/WebhookConfigUpdate" credentials: $ref: "#/components/schemas/WebhookCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateAWSSQS: type: object x-docs-type: "AWS SQS" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [aws_sqs] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "aws_sqs" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSSQSConfigUpdate" credentials: $ref: "#/components/schemas/AWSSQSCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateRabbitMQ: type: object x-docs-type: "RabbitMQ" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [rabbitmq] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "rabbitmq" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/RabbitMQConfigUpdate" credentials: $ref: "#/components/schemas/RabbitMQCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateHookdeck: type: object x-docs-type: "Hookdeck Event Gateway" # Properties duplicated from DestinationUpdateBase # Hookdeck has no updatable `config`. required: [type] properties: type: type: string enum: [hookdeck] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "hookdeck" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" credentials: $ref: "#/components/schemas/HookdeckCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateAWSKinesis: type: object x-docs-type: "AWS Kinesis" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [aws_kinesis] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "aws_kinesis" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSKinesisConfigUpdate" credentials: $ref: "#/components/schemas/AWSKinesisCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateAzureServiceBus: type: object x-docs-type: "Azure Service Bus" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [azure_servicebus] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "azure_servicebus" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AzureServiceBusConfigUpdate" credentials: $ref: "#/components/schemas/AzureServiceBusCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateAWSS3: type: object x-docs-type: "AWS S3" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [aws_s3] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "aws_s3" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSS3ConfigUpdate" credentials: $ref: "#/components/schemas/AWSS3CredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateGCPPubSub: type: object x-docs-type: "GCP PubSub" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [gcp_pubsub] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "gcp_pubsub" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/GCPPubSubConfigUpdate" credentials: $ref: "#/components/schemas/GCPPubSubCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateKafka: type: object x-docs-type: "Apache Kafka" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [kafka] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "kafka" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/KafkaConfigUpdate" credentials: $ref: "#/components/schemas/KafkaCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateCloudflareQueues: type: object x-docs-type: "Cloudflare Queues" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [cloudflare_queues] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "cloudflare_queues" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/CloudflareQueuesConfigUpdate" credentials: $ref: "#/components/schemas/CloudflareQueuesCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null DestinationUpdateAWSEventBridge: type: object x-docs-type: "AWS EventBridge" # Properties duplicated from DestinationUpdateBase required: [type] properties: type: type: string enum: [aws_eventbridge] description: Destination type discriminator. Must equal the existing destination's type — type itself cannot be changed via PATCH. example: "aws_eventbridge" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: $ref: "#/components/schemas/AWSEventBridgeConfigUpdate" credentials: $ref: "#/components/schemas/AWSEventBridgeCredentialsUpdate" delivery_metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Static key-value pairs merged into event metadata on every attempt. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: oneOf: - type: string - type: "null" nullable: true description: >- Arbitrary contextual information stored with the destination. Uses JSON merge-patch semantics (RFC 7396): send keys to add/update, null values to delete keys, null for entire field to clear all. Omit or send {} for no change. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: >- Update the disabled state of the destination. Send a timestamp (must not be in the future) to disable, null to enable, or omit to leave unchanged. example: null # Polymorphic Destination Update Schema (for Request Bodies) DestinationUpdate: oneOf: - $ref: "#/components/schemas/DestinationUpdateWebhook" - $ref: "#/components/schemas/DestinationUpdateHookdeck" - $ref: "#/components/schemas/DestinationUpdateAWSSQS" - $ref: "#/components/schemas/DestinationUpdateAWSKinesis" - $ref: "#/components/schemas/DestinationUpdateAWSS3" - $ref: "#/components/schemas/DestinationUpdateAzureServiceBus" - $ref: "#/components/schemas/DestinationUpdateGCPPubSub" - $ref: "#/components/schemas/DestinationUpdateRabbitMQ" - $ref: "#/components/schemas/DestinationUpdateKafka" - $ref: "#/components/schemas/DestinationUpdateCloudflareQueues" - $ref: "#/components/schemas/DestinationUpdateAWSEventBridge" discriminator: propertyName: type mapping: webhook: "#/components/schemas/DestinationUpdateWebhook" aws_sqs: "#/components/schemas/DestinationUpdateAWSSQS" rabbitmq: "#/components/schemas/DestinationUpdateRabbitMQ" hookdeck: "#/components/schemas/DestinationUpdateHookdeck" aws_kinesis: "#/components/schemas/DestinationUpdateAWSKinesis" azure_servicebus: "#/components/schemas/DestinationUpdateAzureServiceBus" aws_s3: "#/components/schemas/DestinationUpdateAWSS3" gcp_pubsub: "#/components/schemas/DestinationUpdateGCPPubSub" kafka: "#/components/schemas/DestinationUpdateKafka" cloudflare_queues: "#/components/schemas/DestinationUpdateCloudflareQueues" aws_eventbridge: "#/components/schemas/DestinationUpdateAWSEventBridge" # Event Schemas PublishRequest: type: object required: - data properties: id: type: string description: Optional. A unique identifier for the event. If not provided, a ID will be generated. example: "evt_custom_123" tenant_id: type: string description: The ID of the tenant to publish for. example: "" destination_id: type: string description: Optional. Route event to a specific destination. example: "" topic: type: string description: Topic name for the event. Required if Outpost has been configured with topics. example: "topic.name" eligible_for_retry: type: boolean description: Should event delivery be retried on failure. time: type: string format: date-time description: Optional. Custom timestamp for the event. If not provided, defaults to the current time. example: "2024-01-15T10:30:00Z" metadata: type: object description: Any key-value string pairs for metadata. additionalProperties: type: string example: { "source": "crm" } data: type: object description: Any JSON payload for the event data. additionalProperties: true example: { "user_id": "userid", "status": "active" } PublishResponse: type: object required: - id - duplicate - destination_ids properties: id: type: string description: The ID of the event that was accepted for publishing. This will be the ID provided in the request's `id` field if present, otherwise it's a server-generated ID. example: "evt_abc123xyz789" duplicate: type: boolean description: Whether this event was already processed (idempotency hit). If true, the event was not queued again. example: false destination_ids: type: array items: type: string description: The IDs of destinations that matched this event. Empty array if no destinations matched. example: ["des_456", "des_789"] RetryRequest: type: object description: Request body for retrying event delivery to a destination. required: - event_id - destination_id properties: event_id: type: string description: The ID of the event to retry. example: "evt_123" destination_id: type: string description: The ID of the destination to deliver to. example: "des_456" Event: type: object properties: id: type: string example: "evt_123" tenant_id: type: string description: The tenant this event belongs to. example: "tnt_123" matched_destination_ids: type: array items: type: string description: The destination IDs that this event was routed to based on topic and filter matching. example: ["des_456", "des_789"] topic: type: string example: "user.created" time: type: string format: date-time description: Time the event was received/processed. example: "2024-01-01T00:00:00Z" eligible_for_retry: type: boolean description: Whether this event can be retried. example: true metadata: type: object nullable: true description: Key-value string pairs of metadata associated with the event. additionalProperties: type: string example: { "source": "crm" } data: type: object description: Freeform JSON data of the event. additionalProperties: true example: { "user_id": "userid", "status": "active" } # Attempt schemas for attempts-first API AttemptDestination: type: object description: The destination an attempt was sent to, without credentials. Use the destination endpoints to retrieve credentials. required: [id, tenant_id, type, topics, config, created_at, updated_at, disabled_at, target] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" tenant_id: type: string description: The tenant the destination belongs to. example: "tenant_123" type: type: string description: Type of the destination. example: "webhook" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: type: object additionalProperties: type: string description: Type-specific destination configuration. example: { "url": "https://my-service.com/webhook/handler" } delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" target: type: string description: A human-readable representation of the destination target (e.g., URL host). Read-only. readOnly: true example: "my-service.com" target_url: type: string format: url nullable: true description: A URL link to the destination target. Read-only. readOnly: true example: "https://my-service.com/webhook/handler" Attempt: type: object description: An attempt represents a single delivery attempt of an event to a destination. properties: id: type: string description: Unique identifier for this attempt. example: "atm_123" tenant_id: type: string description: The tenant this attempt belongs to. example: "tnt_123" status: type: string enum: [success, failed] description: The attempt status. example: "success" time: type: string format: date-time description: Time the attempt was made. example: "2024-01-01T00:00:05Z" code: type: string description: Response status code or error code. example: "200" response_data: type: object nullable: true description: Response data from the attempt. Only included when include=response_data. additionalProperties: true example: { "status_code": 200, "body": '{"status":"ok"}', "headers": { "content-type": "application/json" } } attempt_number: type: integer description: The attempt number (1 for first attempt, 2+ for retries). example: 1 manual: type: boolean description: Whether this attempt was manually triggered (e.g., a retry initiated by a user). example: false latency_ms: type: integer nullable: true description: Time in milliseconds from sending the attempt to receiving the destination's response (or the error), measured around the provider's publish call. Null for attempts that never reached the provider and for attempts recorded before latency was tracked. example: 212 event_id: type: string description: The ID of the associated event. example: "evt_123" destination_id: type: string description: The destination ID this attempt was sent to. example: "des_456" event: nullable: true oneOf: - $ref: "#/components/schemas/EventFull" - $ref: "#/components/schemas/EventSummary" description: The associated event object. Only present when include=event or include=event.data. destination: nullable: true $ref: "#/components/schemas/AttemptDestination" description: The destination object, without credentials. Only present when include=destination. EventSummary: type: object description: Event object without data (returned when include=event). properties: id: type: string example: "evt_123" tenant_id: type: string description: The tenant this event belongs to. example: "tnt_123" destination_id: type: string description: The destination this event was delivered to. example: "des_456" topic: type: string example: "user.created" time: type: string format: date-time description: Time the event was received. example: "2024-01-01T00:00:00Z" eligible_for_retry: type: boolean description: Whether this event can be retried. example: true metadata: type: object additionalProperties: type: string nullable: true example: { "source": "crm" } EventFull: type: object description: Full event object with data (returned when include=event.data). properties: id: type: string example: "evt_123" tenant_id: type: string description: The tenant this event belongs to. example: "tnt_123" destination_id: type: string description: The destination this event was delivered to. example: "des_456" topic: type: string example: "user.created" time: type: string format: date-time description: Time the event was received. example: "2024-01-01T00:00:00Z" eligible_for_retry: type: boolean description: Whether this event can be retried. example: true metadata: type: object additionalProperties: type: string nullable: true example: { "source": "crm" } data: type: object additionalProperties: true description: The event payload data. example: { "user_id": "userid", "status": "active" } AttemptPaginatedResult: type: object description: Paginated list of attempts. properties: pagination: $ref: "#/components/schemas/SeekPagination" models: type: array items: $ref: "#/components/schemas/Attempt" description: Array of attempt objects. EventPaginatedResult: type: object description: Paginated list of events. properties: pagination: $ref: "#/components/schemas/SeekPagination" models: type: array items: $ref: "#/components/schemas/Event" description: Array of event objects. # Destination Type Schema (for Metadata endpoint) DestinationType: type: string enum: - webhook - aws_sqs - rabbitmq - hookdeck - aws_kinesis - azure_servicebus - aws_s3 - gcp_pubsub - kafka - cloudflare_queues - aws_eventbridge description: Type of destination. example: "webhook" DestinationTypeSchema: type: object properties: type: type: string example: "webhook" label: type: string example: "Webhook" description: type: string example: "Send event via an HTTP POST request to a URL" icon: type: string description: SVG icon string. example: "" instructions: type: string description: Markdown instructions. example: "Some *markdown*" setup_link: type: object # Property is optional, not nullable description: >- Some destinations may have an OAuth flow or other managed-setup flow that can be triggered with a link. If a `setup_link` is set then the user should be prompted to follow the link to configure the destination. See the [building your own UI guide](https://outpost.hookdeck.com/guides/building-your-own-ui.mdx) for recommended UI patterns and wireframes for implementation in your own app. properties: href: type: string format: url description: The URL to direct the user to for setup. example: "https://dashboard.hookdeck.com/connect" cta: type: string description: The call-to-action button text to display to the user. example: "Generate Hookdeck Token" required: - href - cta config_fields: type: array description: Config fields are non-secret values that can be stored and displayed to the user in plain text. items: $ref: "#/components/schemas/DestinationSchemaField" credential_fields: type: array description: Credential fields are secret values that will be AES encrypted and obfuscated to the user. Some credentials may not be obfuscated; the destination type dictates the obfuscation logic. items: $ref: "#/components/schemas/DestinationSchemaField" DestinationSchemaField: type: object required: [type, required, key] properties: key: type: string description: >- Property name for this value inside the destination `config` or `credentials` object on create/update (for example `url` for a webhook endpoint URL). This is the key used to store and retrieve the field value in the destination's config or credentials object. example: "url" type: type: string enum: [text, checkbox, key_value_map, select] example: "text" label: type: string example: "URL" description: type: string example: "The URL to send the event to" required: type: boolean example: true sensitive: type: boolean description: Indicates if the field contains sensitive information. example: false default: type: string description: Default value for the field. example: "default_value" minlength: type: integer description: Minimum length for a text input. example: 0 maxlength: type: integer description: Maximum length for a text input. example: 255 pattern: type: string description: Regex pattern for validation (compatible with HTML5 pattern attribute). example: "^[a-zA-Z0-9_]+$" options: type: array description: Available options for select fields. items: type: object required: [label, value] properties: label: type: string example: "PLAIN" value: type: string example: "plain" MetricsDataPoint: type: object properties: time_bucket: type: string format: date-time description: Start of the time bucket. Absent when no granularity is specified. example: "2026-03-02T14:00:00Z" dimensions: type: object additionalProperties: type: string description: Dimension values for this data point. Empty object when no dimensions are requested. example: destination_id: "dest_abc" topic: "user.created" metrics: type: object additionalProperties: {} description: Requested measure values for this data point. example: count: 1423 error_rate: 0.02 MetricsMetadata: type: object properties: granularity: type: string description: The granularity used for time bucketing. Absent when none was specified. example: "1h" query_time_ms: type: integer description: Query execution time in milliseconds. example: 42 row_count: type: integer description: Number of data points returned. example: 2 row_limit: type: integer description: Maximum number of rows the query will return. example: 100000 truncated: type: boolean description: Whether the results were truncated due to hitting the row limit. example: false MetricsResponse: type: object properties: data: type: array items: $ref: "#/components/schemas/MetricsDataPoint" description: Array of aggregated data points. metadata: $ref: "#/components/schemas/MetricsMetadata" ManagedConfig: type: object description: | Configuration values for managed Outpost. This API is only available on managed Outpost. Self-hosted deployments configure these values using environment variables. properties: ALERT_AUTO_DISABLE_DESTINATION: type: string description: >- If "true", automatically disables a destination once ALERT_CONSECUTIVE_FAILURE_COUNT is reached. Has no effect when consecutive-failure alerting is disabled. ALERT_CONSECUTIVE_FAILURE_COUNT: type: string description: >- Consecutive delivery failures before alerting on a destination (and disabling it when ALERT_AUTO_DISABLE_DESTINATION is "true"). Omit for the default of 100; set to an empty string to disable consecutive-failure alerting entirely. ALERT_EXHAUSTED_RETRIES_WINDOW_SECONDS: type: string description: >- Suppression window in seconds for exhausted_retries alerts: the first exhaustion per destination alerts and subsequent ones within the window are suppressed ("0" = no suppression). Omit for the default of 3600; set to an empty string to disable exhausted_retries alerting entirely. DELIVERY_TIMEOUT_SECONDS: type: string DESTINATIONS_AWS_KINESIS_METADATA_IN_PAYLOAD: type: string DESTINATIONS_INCLUDE_MILLISECOND_TIMESTAMP: type: string DESTINATIONS_WEBHOOK_COMPAT_HEADERS: type: string description: >- Additional headers sent with the compat signature, as comma-separated "name=template" pairs. Available variables: {{.EventID}}, {{.Topic}}, {{.Timestamp}}. Use "\," for a literal comma in a template. DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ALGORITHM: type: string description: >- Algorithm for the compat signature. Defaults to "hmac-sha256". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_CONTENT_TEMPLATE: type: string description: >- Go template for the content signed by the compat signature. Same variables as DESTINATIONS_WEBHOOK_SIGNATURE_CONTENT_TEMPLATE. Defaults to "{{.Body}}". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ENCODING: type: string description: >- Encoding for the compat signature ("hex" or "base64"). Defaults to "hex". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_NAME: type: string description: >- Complete name of the compat signature header. Setting it sends a second signature, in a previous scheme, alongside the primary one. DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_TEMPLATE: type: string description: >- Go template for the value of the compat signature header. Same variables as DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_TEMPLATE. Defaults to "v0={{.Signatures | join ","}}". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_ENCODING: type: string description: >- How the compat signature derives its HMAC key from the destination secret: "raw", "base64" or "hex". Defaults to "raw". A destination whose secret can't be decoded doesn't receive the compat signature. DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_PREFIX: type: string description: >- Prefix stripped from the destination secret before decoding for the compat signature (e.g., "whsec_"). DESTINATIONS_WEBHOOK_EVENT_ID_HEADER_NAME: type: string description: >- Complete name of the event ID header. Unset uses the default "event-id"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. DESTINATIONS_WEBHOOK_HEADER_PREFIX: type: string DESTINATIONS_WEBHOOK_MODE: type: string DESTINATIONS_WEBHOOK_PROXY_URL: type: string DESTINATIONS_WEBHOOK_SIGNATURE_ALGORITHM: type: string DESTINATIONS_WEBHOOK_SIGNATURE_CONTENT_TEMPLATE: type: string DESTINATIONS_WEBHOOK_SIGNATURE_ENCODING: type: string DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_NAME: type: string description: >- Complete name of the signature header. Unset uses the default "signature"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_TEMPLATE: type: string DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_ENCODING: type: string description: >- How the signature derives its HMAC key from the destination secret: "raw" uses the secret as-is, "base64" and "hex" decode it. Defaults to "raw". DESTINATIONS_WEBHOOK_SIGNING_SECRET_TEMPLATE must generate secrets this encoding can decode. Only applies to "default" mode. DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_PREFIX: type: string description: >- Prefix stripped from the destination secret before decoding (e.g., "whsec_"). Ignored when DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_ENCODING is "raw". Only applies to "default" mode. DESTINATIONS_WEBHOOK_SIGNING_SECRET_TEMPLATE: type: string DESTINATIONS_WEBHOOK_TIMESTAMP_FORMAT: type: string description: >- Format of the timestamp header: "rfc3339" or "unix". Defaults to "rfc3339". Only applies to "default" mode. DESTINATIONS_WEBHOOK_TIMESTAMP_HEADER_NAME: type: string description: >- Complete name of the timestamp header. Unset uses the default "timestamp"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. DESTINATIONS_WEBHOOK_TOPIC_HEADER_NAME: type: string description: >- Complete name of the topic header. Unset uses the default "topic"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. HTTP_USER_AGENT: type: string IDGEN_ATTEMPT_PREFIX: type: string IDGEN_DESTINATION_PREFIX: type: string IDGEN_EVENT_PREFIX: type: string IDGEN_TYPE: type: string MAX_DESTINATIONS_PER_TENANT: type: string PORTAL_BRAND_COLOR: type: string PORTAL_DISABLE_OUTPOST_BRANDING: type: string PORTAL_FAVICON_URL: type: string PORTAL_FORCE_THEME: type: string PORTAL_LOGO: type: string PORTAL_LOGO_DARK: type: string PORTAL_ORGANIZATION_NAME: type: string PORTAL_REFERER_URL: type: string PORTAL_REFRESH_URL: type: string PORTAL_ENABLE_DESTINATION_FILTER: type: string PORTAL_ENABLE_WEBHOOK_CUSTOM_HEADERS: type: string RETRY_INTERVAL_SECONDS: type: string MAX_RETRY_LIMIT: type: string RETRY_SCHEDULE: type: string OTEL_EXPORTER_OTLP_ENDPOINT: type: string OTEL_EXPORTER_OTLP_HEADERS: type: string OTEL_EXPORTER_OTLP_PROTOCOL: type: string OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: type: string OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: type: string OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: type: string OTEL_SERVICE_NAME: type: string PUBLISH_AWS_SQS_ACCESS_KEY_ID: type: string PUBLISH_AWS_SQS_ENDPOINT: type: string PUBLISH_AWS_SQS_QUEUE: type: string PUBLISH_AWS_SQS_REGION: type: string PUBLISH_AWS_SQS_SECRET_ACCESS_KEY: type: string PUBLISH_AZURE_SERVICEBUS_CONNECTION_STRING: type: string PUBLISH_AZURE_SERVICEBUS_SUBSCRIPTION: type: string PUBLISH_AZURE_SERVICEBUS_TOPIC: type: string PUBLISH_GCP_PUBSUB_PROJECT: type: string PUBLISH_GCP_PUBSUB_SERVICE_ACCOUNT_CREDENTIALS: type: string PUBLISH_GCP_PUBSUB_SUBSCRIPTION: type: string PUBLISH_GCP_PUBSUB_TOPIC: type: string PUBLISH_RABBITMQ_EXCHANGE: type: string PUBLISH_RABBITMQ_QUEUE: type: string PUBLISH_RABBITMQ_SERVER_URL: type: string TOPICS: type: string TOPICS_ALLOW_WILDCARDS: type: string additionalProperties: false example: TOPICS: "user.created,user.updated" DESTINATIONS_WEBHOOK_MODE: "default" # Operator Events (managed only) OperatorEventDestinationCreate: type: object required: [type, topics, config] properties: type: type: string description: >- Type of the destination. `GET /operator-events/destination-types` lists the types this deployment accepts and the `config` and `credentials` fields each one takes. example: "webhook" topics: type: array items: type: string description: >- Operator event topics to subscribe to. Use `["*"]` to subscribe to every topic. See the Operator Events tag description for the available topics. example: ["alert.destination.disabled", "alert.destination.consecutive_failure"] config: type: object additionalProperties: type: string description: >- Configuration for the chosen destination type, with the same fields as a tenant destination of that type. Send `{}` for a type with no config fields. example: { "url": "https://alerts.acme.com/outpost" } credentials: type: object additionalProperties: type: string description: >- Credentials for the chosen destination type, with the same fields as a tenant destination of that type. For `webhook` this is optional: set `secret` to supply the signing secret, or omit it and Outpost generates one. example: { "secret": "whsec_abc123" } OperatorEventDestinationUpdate: type: object description: Fields to change. Omitted fields are left as they are. properties: topics: type: array items: type: string description: >- Replacement list of operator event topics. Use `["*"]` to subscribe to every topic. Full-replacement semantics: the list sent becomes the subscription. example: ["alert.destination.disabled", "alert.attempt.exhausted_retries"] config: type: object additionalProperties: true description: >- Config fields to change for the destination's type. Merge-patch semantics: fields that are not sent keep their value. example: { "url": "https://alerts.acme.com/outpost" } credentials: type: object additionalProperties: true description: >- Credential fields to change for the destination's type. Merge-patch semantics: fields that are not sent keep their value. For `webhook`, set `secret` to replace the signing secret, or send `rotate_secret: true` to have Outpost generate a new one and keep the current one valid as `previous_secret`. example: { "rotate_secret": true } OperatorEventRetryRequest: type: object required: [event_id, destination_id] properties: event_id: type: string description: The ID of the operator event to redeliver. example: "F1JKYUvykB5grOoE6Bnm6jztlF" destination_id: type: string description: The ID of the operator event destination to redeliver it to. example: "des_12345" # Security is applied per-operation based on AuthScope # `x-outpost-deployment` marks an operation or tag that exists in only one # deployment model: `managed` or `self-hosted`. **Its absence means the # operation is available in both** — the key is present only where # availability is restricted, so adding an endpoint that works everywhere # needs nothing here. # # It carries the same fact as the "only available for..." sentences in the # descriptions beside it, in a form a generator, a validator or an agent can # read without parsing English. The prose stays, because it is what a human # reading the reference sees. tags: - name: Health x-outpost-deployment: self-hosted description: | This endpoint is only available for **self-hosted** Outpost deployments. Managed Outpost health is monitored by Hookdeck. - name: Configuration x-outpost-deployment: managed description: | The Configuration API is only available on managed Outpost. It allows you to read and update instance-level settings, the same settings available as environment variables in self-hosted deployments. - name: Operator Events x-outpost-deployment: managed description: | Operator events are Outpost's own lifecycle and alerting stream: delivery failures, destinations being auto-disabled, retry exhaustion and tenant subscription changes. They are about the deployment, not about a tenant's traffic, so they are delivered to **operator event destinations** rather than to tenant destinations. An operator event destination is deployment-wide, is not owned by any tenant you create, and has the same shape as a tenant destination: any destination type listed by `GET /operator-events/destination-types`, with that type's `config` and `credentials`. The Operator Events API is only available on managed Outpost, and requires the Admin API Key. Self-hosted deployments configure the same thing through environment variables and a single sink. See the [Operator Events](https://hookdeck.com/docs/outpost/features/operator-events) feature page. **Available topics** | Topic | Trigger | |-------|---------| | `alert.destination.consecutive_failure` | Consecutive failure count reaches 50%, 70%, 90%, or 100% of `ALERT_CONSECUTIVE_FAILURE_COUNT` | | `alert.destination.disabled` | Destination auto-disabled at the 100% failure threshold | | `alert.attempt.exhausted_retries` | Delivery exhausts all retry attempts | | `attempt.success` | Every successful delivery attempt | | `attempt.failed` | Every failed delivery attempt, including retries | | `tenant.subscription.updated` | A destination was created, updated or deleted and the tenant's topics or destination count changed | A destination may subscribe to every topic with `["*"]`, but `attempt.success` and `attempt.failed` fire once per delivery attempt and will dominate volume. Prefer an explicit topic list. **Topics are derived from these destinations.** The union of every enabled operator event destination's `topics` is what the deployment subscribes to, which is why `PATCH /config` rejects `OPERATOR_EVENTS_TOPICS` with a 422: change the destinations and the configuration follows. - name: Tenants description: | The API segments resources per `tenant`. A tenant represents a user/team/organization in your product. The provided value determines the tenant's ID, which can be any string representation. If your system is not multi-tenant, create a single tenant with a hard-code tenant ID upon initialization. If your system has a single tenant but multiple environments, create a tenant per environment, like `live` and `test`. - name: Destinations description: | Destinations are the endpoints where events are sent. Each destination is associated with a tenant and can be configured to receive specific event topics. The `topics` array can contain either a list of topics or a wildcard `*` implying that all topics are supported. If you do not wish to implement topics for your application, you set all destination topics to `*`. By default all destination `credentials` are obfuscated and the values cannot be read. This does not apply to the `webhook` type destination secret and each destination can expose their own obfuscation logic. - name: Publish description: Use the Publish endpoint to send events into Outpost. Events are matched against all destinations whose topic subscriptions and filters match the event. Requires Admin API Key. - name: Retry description: Triggers a retry for delivering an event to a destination. The event must exist, and the destination must be enabled, match the event's topic and filter, and already have a delivery attempt for the event. - name: Schemas description: | Destination types describe the available event delivery targets and their configuration schemas. Use these endpoints to render UI forms and list available destination types with their configuration schemas. - name: Topics description: | Returns the list of topics configured for this Outpost deployment. Tenants subscribe their destinations to topics from this list. Topics are defined via your configuration file and not a specific Create Topic API. - name: Attempts description: | Attempts represent individual delivery attempts of events to destinations. The attempts API provides an attempt-centric view of event processing. Use the `include` query parameter to include related data: - `include=event`: Include event summary (id, topic, time, eligible_for_retry, metadata) - `include=event.data`: Include full event with payload data - `include=response_data`: Include response body and headers from the attempt - `include=destination`: Include the destination object with target information, without credentials - name: Events description: | An event represents a payload published to Outpost. Events are matched against all destinations whose topic subscriptions match the event topic, then delivered. - name: Metrics description: | Aggregated metrics for events and delivery attempts. Supports time bucketing, dimensional grouping, and filtering. paths: /healthz: get: tags: [Health] summary: Health Check description: | Health check endpoint that reports the status of all workers. > This endpoint is only available for **self-hosted** Outpost deployments. Managed Outpost health is monitored by Hookdeck. Worker status is one of: - `healthy`: running. - `degraded`: failing and being restarted, within its restart budget. The service keeps serving. Only reported for workers listed in `SUPERVISOR_RESTART_WORKERS`. - `failed`: failed, or failing past its restart budget. With restarts enabled, Outpost keeps restarting it, and it returns to `healthy` once it recovers. Returns HTTP 200 when no worker has failed (the overall status is `degraded` if any worker is degraded), or HTTP 503 if any worker has failed. Note: Error details are not exposed for security reasons. Check application logs for detailed error information. operationId: healthCheck x-outpost-deployment: self-hosted security: [] responses: "200": description: Service is healthy or degraded - no worker has failed. content: application/json: schema: type: object required: - status - timestamp - workers properties: status: type: string enum: [healthy, degraded] example: healthy timestamp: type: string format: date-time description: When this health check was performed example: "2025-11-11T10:30:00Z" workers: type: object additionalProperties: type: object required: - status properties: status: type: string enum: [healthy, degraded] example: healthy since: type: string format: date-time description: Start of the worker's current failure episode. Present when the status is `degraded` or `failed`. example: "2025-11-11T10:29:45Z" reason: type: string enum: [startup_failed, recovery_failed] description: | Present when the status is `degraded` or `failed`. `startup_failed`: the worker has not been healthy since the process started (usually configuration or a dependency that is not up yet). `recovery_failed`: the worker was healthy and then failed (e.g. a broker restart or failover). example: recovery_failed example: status: degraded timestamp: "2025-11-11T10:30:00Z" workers: http-server: status: healthy publishmq-consumer: status: degraded since: "2025-11-11T10:29:45Z" reason: recovery_failed "503": description: Service is unhealthy - one or more workers have failed. content: application/json: schema: type: object required: - status - timestamp - workers properties: status: type: string enum: [failed] example: failed timestamp: type: string format: date-time description: When this health check was performed example: "2025-11-11T10:30:15Z" workers: type: object additionalProperties: type: object required: - status properties: status: type: string enum: [healthy, degraded, failed] example: failed since: type: string format: date-time description: Start of the worker's current failure episode. Present when the status is `degraded` or `failed`. example: "2025-11-11T10:29:45Z" reason: type: string enum: [startup_failed, recovery_failed] description: | Present when the status is `degraded` or `failed`. `startup_failed`: the worker has not been healthy since the process started (usually configuration or a dependency that is not up yet). `recovery_failed`: the worker was healthy and then failed (e.g. a broker restart or failover). example: recovery_failed example: status: failed timestamp: "2025-11-11T10:30:15Z" workers: http-server: status: healthy publishmq-consumer: status: failed since: "2025-11-11T10:29:44Z" reason: startup_failed /config: get: tags: [Configuration] summary: Get Managed Configuration description: | Returns managed Outpost configuration values. This endpoint is only available on managed Outpost. In self-hosted deployments, configuration is controlled through environment variables instead. operationId: getManagedConfig x-outpost-deployment: managed responses: "200": description: Managed configuration. content: application/json: schema: $ref: "#/components/schemas/ManagedConfig" example: TOPICS: "user.created,user.updated" TOPICS_ALLOW_WILDCARDS: "false" DESTINATIONS_WEBHOOK_MODE: "default" "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" patch: tags: [Configuration] summary: Update Managed Configuration description: | Updates one or more managed Outpost configuration values. Null values clear the configuration and reverts to Outpost default behavior. This endpoint is only available on managed Outpost. In self-hosted deployments, configuration is controlled through environment variables instead. Only the supported configuration keys are accepted. operationId: updateManagedConfig x-outpost-deployment: managed requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ManagedConfig" example: TOPICS: "user.created,user.updated" TOPICS_ALLOW_WILDCARDS: "false" DESTINATIONS_WEBHOOK_MODE: "default" responses: "200": description: Updated managed configuration. content: application/json: schema: $ref: "#/components/schemas/ManagedConfig" example: TOPICS: "user.created,user.updated" TOPICS_ALLOW_WILDCARDS: "false" DESTINATIONS_WEBHOOK_MODE: "default" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" # Operator Events /operator-events/destination-types: get: tags: [Operator Events] summary: List Operator Event Destination Type Schemas description: | Returns the destination types an operator event destination may use, with the `config` and `credentials` fields each type takes. This endpoint is only available on managed Outpost. operationId: listOperatorEventDestinationTypeSchemas x-outpost-deployment: managed responses: "200": description: A list of destination type schemas. content: application/json: schema: type: array items: $ref: "#/components/schemas/DestinationTypeSchema" examples: OperatorEventDestinationTypesExample: value: - type: "webhook" label: "Webhook" description: "Send events as webhooks (HTTP POST)." icon: "" config_fields: - key: "url" type: "text" label: "Webhook URL" description: "The URL to send webhook events to via HTTP POST" required: true pattern: "^https?:\\/\\/[^\\s]+$" - key: "custom_headers" type: "key_value_map" label: "Custom Headers" description: "Additional HTTP headers to include with every webhook request" required: false credential_fields: [] - type: "hookdeck" label: "Hookdeck" description: "Send events to Hookdeck Event Gateway." icon: "" setup_link: href: "https://dashboard.hookdeck.com/connect" cta: "Generate Hookdeck Token" config_fields: [] credential_fields: - key: "token" type: "text" label: "Hookdeck Token" description: "The Hookdeck authentication token" required: true sensitive: true "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" /operator-events/destinations: get: tags: [Operator Events] summary: List Operator Event Destinations description: | Returns every operator event destination configured for this deployment. The response is a plain array, not a paginated result. A project that has never had an operator event destination may answer 404 `tenant not found` instead of an empty array. This endpoint is only available on managed Outpost. operationId: listOperatorEventDestinations x-outpost-deployment: managed responses: "200": description: A list of operator event destinations. content: application/json: schema: type: array items: $ref: "#/components/schemas/Destination" examples: OperatorEventDestinationsExample: value: - id: "des_12345" type: "webhook" topics: ["alert.destination.disabled", "alert.destination.consecutive_failure"] config: url: "https://alerts.acme.com/outpost" credentials: secret: "whsec_abc123" created_at: "2024-01-01T00:00:00Z" updated_at: "2024-01-01T00:00:00Z" disabled_at: null target: "https://alerts.acme.com/outpost" - id: "des_67890" type: "hookdeck" topics: ["*"] config: source_name: "outpost-alerts" source_id: "src_xxxyyyzzz" credentials: token: "hd_token_..." created_at: "2024-01-02T00:00:00Z" updated_at: "2024-01-02T00:00:00Z" disabled_at: null target: "outpost-alerts" target_url: "https://dashboard.hookdeck.com/sources/src_xxxyyyzzz" "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" post: tags: [Operator Events] summary: Create Operator Event Destination description: | Creates an operator event destination of any type listed by `GET /operator-events/destination-types`. `config` and `credentials` take the same fields as a tenant destination of that type. For a `webhook` destination, set `credentials.secret` to supply the signing secret. When it is omitted, Outpost generates one. Either way the secret is returned in `credentials`. Creating or changing a destination changes which topics the deployment subscribes to, which is why `OPERATOR_EVENTS_TOPICS` cannot be set through `PATCH /config`. This endpoint is only available on managed Outpost. operationId: createOperatorEventDestination x-outpost-deployment: managed requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/OperatorEventDestinationCreate" examples: Webhook: value: type: "webhook" topics: ["alert.destination.disabled", "alert.destination.consecutive_failure"] config: url: "https://alerts.acme.com/outpost" Hookdeck: value: type: "hookdeck" topics: ["*"] config: {} credentials: token: "hd_token_..." responses: "200": description: The created operator event destination. content: application/json: schema: $ref: "#/components/schemas/Destination" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /operator-events/destinations/{destination_id}: parameters: - name: destination_id in: path required: true schema: type: string description: The ID of the operator event destination. get: tags: [Operator Events] summary: Get Operator Event Destination description: | Retrieves a single operator event destination. Returns 404 `destination not found` if no operator event destination has this ID, or 404 `tenant not found` if the project has never had one. This endpoint is only available on managed Outpost. operationId: getOperatorEventDestination x-outpost-deployment: managed responses: "200": description: The operator event destination. content: application/json: schema: $ref: "#/components/schemas/Destination" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" patch: tags: [Operator Events] summary: Update Operator Event Destination description: | Updates an operator event destination. `topics` uses full-replacement semantics: the list sent becomes the subscription. `config` and `credentials` take the fields of the destination's type; fields that are not sent keep their value. The type itself cannot be changed. To change the signing secret of a `webhook` destination, set `credentials.secret`, or send `credentials.rotate_secret: true` to have Outpost generate a new one. On rotation the current secret stays valid as `previous_secret`, for 24 hours by default. Returns 404 `destination not found` if no operator event destination has this ID, or 404 `tenant not found` if the project has never had one. This endpoint is only available on managed Outpost. operationId: updateOperatorEventDestination x-outpost-deployment: managed requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/OperatorEventDestinationUpdate" example: topics: [ "alert.destination.disabled", "alert.destination.consecutive_failure", "alert.attempt.exhausted_retries", ] responses: "200": description: The updated operator event destination. content: application/json: schema: $ref: "#/components/schemas/Destination" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" delete: tags: [Operator Events] summary: Delete Operator Event Destination description: | Deletes an operator event destination. Deleting the last one leaves the deployment with no operator event delivery, and therefore silent. Returns 404 `destination not found` if no operator event destination has this ID, or 404 `tenant not found` if the project has never had one. This endpoint is only available on managed Outpost. operationId: deleteOperatorEventDestination x-outpost-deployment: managed responses: "200": description: Operator event destination deleted. content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" examples: OperatorEventDestinationDeleted: value: success: true "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /operator-events/destinations/{destination_id}/enable: parameters: - name: destination_id in: path required: true schema: type: string description: The ID of the operator event destination. put: tags: [Operator Events] summary: Enable Operator Event Destination description: | Enables a previously disabled operator event destination. Returns the destination with `disabled_at` set to null. Returns 404 `destination not found` if no operator event destination has this ID, or 404 `tenant not found` if the project has never had one. This endpoint is only available on managed Outpost. operationId: enableOperatorEventDestination x-outpost-deployment: managed responses: "200": description: Operator event destination enabled. content: application/json: schema: $ref: "#/components/schemas/Destination" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /operator-events/destinations/{destination_id}/disable: parameters: - name: destination_id in: path required: true schema: type: string description: The ID of the operator event destination. put: tags: [Operator Events] summary: Disable Operator Event Destination description: | Disables an operator event destination. A disabled destination receives nothing, so disabling the only one leaves the deployment configured and silent. Returns 404 `destination not found` if no operator event destination has this ID, or 404 `tenant not found` if the project has never had one. This endpoint is only available on managed Outpost. operationId: disableOperatorEventDestination x-outpost-deployment: managed responses: "200": description: Operator event destination disabled. content: application/json: schema: $ref: "#/components/schemas/Destination" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /operator-events/events: get: tags: [Operator Events] summary: List Operator Events description: | Returns the 100 most recent operator events emitted by this deployment, newest first. Paging is not available yet: this operation takes no query parameters, so `pagination.next` cannot be passed back. Each row is an Outpost event whose `topic` is the operator event topic, whose `matched_destination_ids` are operator event destinations, and whose `tenant_id` is the ID of your Outpost project. The topic-specific payload is nested under `data`, which carries the same envelope the sink receives: `id`, `topic`, `time`, `tenant_id` and a `data` object described on the [Operator Events](https://hookdeck.com/docs/outpost/features/operator-events) feature page. This endpoint is only available on managed Outpost. operationId: listOperatorEvents x-outpost-deployment: managed responses: "200": description: A paginated list of operator events. content: application/json: schema: $ref: "#/components/schemas/EventPaginatedResult" examples: OperatorEventsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: null prev: null models: - id: "F1JKYUvykB5grOoE6Bnm6jztlF" tenant_id: "tm_12345" matched_destination_ids: ["des_12345"] topic: "attempt.failed" time: "2024-01-01T00:00:00Z" eligible_for_retry: true data: id: "F1JKYUvykB5grOoE6Bnm6jztlF" topic: "attempt.failed" time: "2024-01-01T00:00:00Z" tenant_id: "tenant_123" data: tenant_id: "tenant_123" event: {} attempt: {} destination: {} "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" /operator-events/events/{event_id}: parameters: - name: event_id in: path required: true schema: type: string description: The ID of the operator event. get: tags: [Operator Events] summary: Get Operator Event description: | Retrieves a single operator event. This endpoint is only available on managed Outpost. operationId: getOperatorEvent x-outpost-deployment: managed responses: "200": description: Operator event details. content: application/json: schema: $ref: "#/components/schemas/Event" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /operator-events/events/{event_id}/attempts: parameters: - name: event_id in: path required: true schema: type: string description: The ID of the operator event. get: tags: [Operator Events] summary: List Attempts for an Operator Event description: | Returns the 100 most recent delivery attempts made for one operator event, newest first. Paging is not available yet: this operation takes no query parameters, so `pagination.next` cannot be passed back. This endpoint is only available on managed Outpost. operationId: listOperatorEventAttemptsByEvent x-outpost-deployment: managed responses: "200": description: A paginated list of delivery attempts for the operator event. content: application/json: schema: $ref: "#/components/schemas/AttemptPaginatedResult" "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" /operator-events/attempts: get: tags: [Operator Events] summary: List Operator Event Attempts description: | Returns the delivery attempts made to operator event destinations, newest first. The response holds one page of up to `limit` attempts. Paging is not available yet: `pagination.next` cannot be passed back. This endpoint is only available on managed Outpost. operationId: listOperatorEventAttempts x-outpost-deployment: managed parameters: - name: event_id in: query required: false schema: type: string description: Filter attempts by operator event ID. - name: destination_id in: query required: false schema: type: string description: Filter attempts by operator event destination ID. - name: status in: query required: false schema: type: string enum: [success, failed] description: Filter attempts by status. - name: topic in: query required: false schema: type: string description: Filter attempts by operator event topic. - name: time in: query required: false style: deepObject explode: true schema: $ref: "#/components/schemas/Operator" description: Filter attempts by the time of the attempt, using comparison operators (e.g., `time[gte]=2024-01-01T00:00:00Z`). - name: limit in: query required: false schema: type: integer default: 100 minimum: 1 maximum: 1000 description: Number of items per page (1-1000, default 100). A value outside this range returns a 400. responses: "200": description: A paginated list of operator event delivery attempts. content: application/json: schema: $ref: "#/components/schemas/AttemptPaginatedResult" examples: OperatorEventAttemptsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: null prev: null models: - id: "atm_12345" tenant_id: "tm_12345" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 manual: false latency_ms: 11 event_id: "F1JKYUvykB5grOoE6Bnm6jztlF" destination_id: "des_12345" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /operator-events/attempts/{attempt_id}: parameters: - name: attempt_id in: path required: true schema: type: string description: The ID of the operator event delivery attempt. get: tags: [Operator Events] summary: Get Operator Event Attempt description: | Retrieves a single operator event delivery attempt. This endpoint is only available on managed Outpost. operationId: getOperatorEventAttempt x-outpost-deployment: managed responses: "200": description: Operator event delivery attempt details. content: application/json: schema: $ref: "#/components/schemas/Attempt" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /operator-events/retry: post: tags: [Operator Events] summary: Retry Operator Event Delivery description: | Redelivers an operator event to one operator event destination. The event must exist, and the destination must be enabled, match the event's topic and filter, and already have a delivery attempt for the event. Returns 404 `event not found` if the event does not exist. Returns 404 `destination not found` if the destination does not exist or has been deleted. Unlike `POST /retry`, which answers `202`, this answers `200` with `{"success": true}`. This endpoint is only available on managed Outpost. operationId: retryOperatorEvent x-outpost-deployment: managed requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/OperatorEventRetryRequest" example: event_id: "F1JKYUvykB5grOoE6Bnm6jztlF" destination_id: "des_12345" responses: "200": description: Retry accepted. content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" examples: OperatorEventRetryAccepted: value: success: true "400": description: | Bad request. This can happen when: - The destination is disabled - The destination does not match the event's topic or filter - The event has no delivery attempt for the destination "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" # Tenants /tenants: get: tags: [Tenants] summary: List Tenants description: | List all tenants with cursor-based pagination. > When self-hosting this endpoint requires Redis with RediSearch module (e.g., `redis/redis-stack-server`). If RediSearch is not available, this endpoint returns `501 Not Implemented`. When authenticated with a Tenant JWT, returns only the authenticated tenant. operationId: listTenants security: - AdminApiKey: [] - TenantJwt: [] parameters: - name: id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter tenants by ID(s). Use bracket notation for multiple values (e.g., `id[0]=t1&id[1]=t2` or `id[]=t1&id[]=t2`). - name: limit in: query required: false schema: type: integer minimum: 1 maximum: 100 default: 20 description: Number of tenants to return per page (1-100, default 20). - name: dir in: query required: false schema: type: string enum: [asc, desc] default: desc description: Sort direction. - name: next in: query required: false schema: type: string description: Cursor for the next page of results. Mutually exclusive with `prev`. - name: prev in: query required: false schema: type: string description: Cursor for the previous page of results. Mutually exclusive with `next`. responses: "200": description: List of tenants. content: application/json: schema: $ref: "#/components/schemas/TenantPaginatedResult" example: pagination: order_by: "created_at" dir: "desc" limit: 20 next: "MTcwNDA2NzIwMA==" prev: null count: 2 models: - id: "tenant_123" metadata: plan: "pro" created_at: "2024-01-15T10:30:00Z" updated_at: "2024-01-15T10:30:00Z" - id: "tenant_456" metadata: null created_at: "2024-01-14T09:00:00Z" updated_at: "2024-01-14T09:00:00Z" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" "501": description: List Tenants feature is not available. Requires Redis with RediSearch module. content: application/json: schema: type: object properties: error: type: string example: "list tenant not supported" /tenants/{tenant_id}: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. put: tags: [Tenants] summary: Create or Update Tenant description: Idempotently creates or updates a tenant. Required before associating destinations. operationId: upsertTenant requestBody: description: Optional tenant metadata required: false content: application/json: schema: $ref: "#/components/schemas/TenantUpsert" example: metadata: name: "Acme Inc." responses: "200": description: Tenant updated details. content: application/json: schema: $ref: "#/components/schemas/Tenant" example: id: "tenant_123" destinations_count: 5 topics: ["user.created", "user.deleted"] metadata: name: "Acme Inc." created_at: "2024-01-01T00:00:00Z" updated_at: "2024-01-15T10:30:00Z" "201": description: Tenant created details. content: application/json: schema: $ref: "#/components/schemas/Tenant" example: id: "tenant_123" destinations_count: 0 topics: [] metadata: name: "Acme Inc." created_at: "2024-01-15T10:30:00Z" updated_at: "2024-01-15T10:30:00Z" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" get: tags: [Tenants] summary: Get Tenant description: Retrieves details for a specific tenant. operationId: getTenant responses: "200": description: Tenant details. content: application/json: schema: $ref: "#/components/schemas/Tenant" example: id: "tenant_123" destinations_count: 5 topics: ["user.created", "user.deleted"] metadata: name: "Acme Inc." created_at: "2024-01-01T00:00:00Z" updated_at: "2024-01-15T10:30:00Z" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" delete: tags: [Tenants] summary: Delete Tenant description: Deletes the tenant and all associated destinations. operationId: deleteTenant responses: "200": description: Success confirmation. content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" examples: SuccessExample: value: success: true "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /events: get: tags: [Events] summary: List Events description: | Retrieves a list of events. When authenticated with a Tenant JWT, returns only events belonging to that tenant. When authenticated with Admin API Key, returns events across all tenants. Use `tenant_id` query parameter to filter by tenant. operationId: listEvents security: - AdminApiKey: [] - TenantJwt: [] parameters: - name: id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter events by ID(s). Use bracket notation for multiple values (e.g., `id[0]=abc&id[1]=def`). - name: tenant_id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: | Filter events by tenant ID(s). Use bracket notation for multiple values (e.g., `tenant_id[0]=t1&tenant_id[1]=t2`). When authenticated with a Tenant JWT, this parameter is ignored and the JWT's tenant is used. If not provided with API key auth, returns events from all tenants. - name: destination_id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter events by matched destination ID(s). Returns events that were routed to the specified destination(s). Use bracket notation for multiple values (e.g., `destination_id[0]=d1&destination_id[1]=d2`). - name: topic in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter events by topic(s). Use bracket notation for multiple values (e.g., `topic[0]=user.created&topic[1]=user.updated`). - name: time in: query required: false style: deepObject explode: true schema: $ref: "#/components/schemas/Operator" description: Filter events by time range using comparison operators. - name: limit in: query required: false schema: type: integer default: 100 minimum: 1 maximum: 1000 description: Number of items per page (1-1000, default 100). A value outside this range, or one that is not an integer, returns a 400. - name: next in: query required: false schema: type: string description: Cursor for the next page of results, from `pagination.next` of a previous response. Mutually exclusive with `prev`. A cursor that cannot be read returns a 400. - name: prev in: query required: false schema: type: string description: Cursor for the previous page of results, from `pagination.prev` of a previous response. Mutually exclusive with `next`. A cursor that cannot be read returns a 400. - name: order_by in: query required: false schema: type: string enum: [time] default: time description: Field to sort by. - name: dir in: query required: false schema: type: string enum: [asc, desc] default: desc description: Sort direction. responses: "200": description: A paginated list of events. content: application/json: schema: $ref: "#/components/schemas/EventPaginatedResult" examples: AdminEventsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: "MTcwNDA2NzIwMA==" prev: null models: - id: "evt_123" topic: "user.created" matched_destination_ids: ["des_456"] time: "2024-01-01T00:00:00Z" eligible_for_retry: false metadata: { "source": "crm" } data: { "user_id": "userid", "status": "active" } - id: "evt_789" topic: "order.shipped" matched_destination_ids: ["des_456", "des_789"] time: "2024-01-02T10:00:00Z" eligible_for_retry: true metadata: { "source": "oms" } data: { "order_id": "orderid", "tracking": "1Z..." } "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /events/{event_id}: parameters: - name: event_id in: path required: true schema: type: string description: The ID of the event. get: tags: [Events] summary: Get Event description: | Retrieves details for a specific event. When authenticated with a Tenant JWT, only events belonging to that tenant can be accessed. When authenticated with Admin API Key, events from any tenant can be accessed. operationId: getEvent parameters: - name: tenant_id in: query required: false schema: type: string description: Filter by tenant ID. Returns 404 if the event does not belong to the specified tenant. Ignored when using Tenant JWT authentication. responses: "200": description: Event details. content: application/json: schema: $ref: "#/components/schemas/Event" examples: EventExample: value: id: "evt_123" topic: "user.created" matched_destination_ids: ["des_456"] time: "2024-01-01T00:00:00Z" eligible_for_retry: false metadata: { "source": "crm" } data: { "user_id": "userid", "status": "active" } "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /attempts: get: tags: [Attempts] summary: List Attempts description: | Retrieves a paginated list of attempts. When authenticated with a Tenant JWT, returns only attempts belonging to that tenant. When authenticated with Admin API Key, returns attempts across all tenants. Use `tenant_id` query parameter to filter by tenant. operationId: listAttempts security: - AdminApiKey: [] - TenantJwt: [] parameters: - name: tenant_id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: | Filter attempts by tenant ID(s). Use bracket notation for multiple values (e.g., `tenant_id[0]=t1&tenant_id[1]=t2`). When authenticated with a Tenant JWT, this parameter is ignored and the JWT's tenant is used. If not provided with API key auth, returns attempts from all tenants. - name: event_id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter attempts by event ID(s). Use bracket notation for multiple values (e.g., `event_id[0]=e1&event_id[1]=e2`). - name: destination_id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter attempts by destination ID(s). Use bracket notation for multiple values (e.g., `destination_id[0]=d1&destination_id[1]=d2`). - name: destination_type in: query required: false schema: oneOf: - $ref: "#/components/schemas/DestinationType" - type: array items: $ref: "#/components/schemas/DestinationType" description: Filter attempts by destination type(s). Use bracket notation for multiple values (e.g., `destination_type[0]=webhook&destination_type[1]=aws_sqs`). - name: status in: query required: false schema: type: string enum: [success, failed] description: Filter attempts by status. - name: topic in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter attempts by event topic(s). Use bracket notation for multiple values (e.g., `topic[0]=user.created&topic[1]=user.updated`). - name: time in: query required: false style: deepObject explode: true schema: $ref: "#/components/schemas/Operator" description: Filter attempts by event time range using comparison operators. - name: limit in: query required: false schema: type: integer default: 100 minimum: 1 maximum: 1000 description: Number of items per page (1-1000, default 100). A value outside this range, or one that is not an integer, returns a 400. - name: next in: query required: false schema: type: string description: Cursor for the next page of results, from `pagination.next` of a previous response. Mutually exclusive with `prev`. A cursor that cannot be read returns a 400. - name: prev in: query required: false schema: type: string description: Cursor for the previous page of results, from `pagination.prev` of a previous response. Mutually exclusive with `next`. A cursor that cannot be read returns a 400. - name: include in: query required: false schema: oneOf: - type: string - type: array items: type: string description: | Fields to include in the response. Use bracket notation for multiple values (e.g., `include[0]=event&include[1]=response_data`). - `event`: Include event summary (id, topic, time, eligible_for_retry, metadata) - `event.data`: Include full event with payload data - `response_data`: Include response body and headers - `destination`: Include the destination object, without credentials - name: order_by in: query required: false schema: type: string enum: [time] default: time description: Field to sort by. - name: dir in: query required: false schema: type: string enum: [asc, desc] default: desc description: Sort direction. responses: "200": description: A paginated list of attempts. content: application/json: schema: $ref: "#/components/schemas/AttemptPaginatedResult" examples: AdminAttemptsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: "MTcwNDA2NzIwMA==" prev: null models: - id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" - id: "att_124" status: "failed" time: "2024-01-02T10:00:01Z" code: "503" attempt_number: 2 latency_ms: 1502 event_id: "evt_789" destination_id: "des_789" AdminAttemptsWithIncludeExample: summary: Response with include=event value: pagination: order_by: "time" dir: "desc" limit: 100 next: null prev: null models: - id: "del_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" event: id: "evt_123" topic: "user.created" time: "2024-01-01T00:00:00Z" eligible_for_retry: false metadata: { "source": "crm" } "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /attempts/{attempt_id}: parameters: - name: attempt_id in: path required: true schema: type: string description: The ID of the attempt. get: tags: [Attempts] summary: Get Attempt description: | Retrieves details for a specific attempt. When authenticated with a Tenant JWT, only attempts belonging to that tenant can be accessed. When authenticated with Admin API Key, attempts from any tenant can be accessed. operationId: getAttempt parameters: - name: tenant_id in: query required: false schema: type: string description: Filter by tenant ID. Returns 404 if the attempt does not belong to the specified tenant. Ignored when using Tenant JWT authentication. - name: include in: query required: false schema: oneOf: - type: string - type: array items: type: string description: | Fields to include in the response. Use bracket notation for multiple values (e.g., `include[0]=event&include[1]=response_data`). - `event`: Include event summary (id, topic, time, eligible_for_retry, metadata) - `event.data`: Include full event with payload data - `response_data`: Include response body and headers - `destination`: Include the destination object, without credentials responses: "200": description: Attempt details. content: application/json: schema: $ref: "#/components/schemas/Attempt" examples: AttemptExample: value: id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" AttemptWithIncludeExample: summary: Response with include=event.data,response_data value: id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" response_data: status_code: 200 body: '{"status":"ok"}' headers: { "content-type": "application/json" } attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" event: id: "evt_123" topic: "user.created" time: "2024-01-01T00:00:00Z" eligible_for_retry: false metadata: { "source": "crm" } data: { "user_id": "userid", "status": "active" } "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/portal: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. get: tags: [Tenants] summary: Get Portal Redirect URL description: Returns a redirect URL containing a JWT to authenticate the user with the portal. Requires Admin API Key. operationId: getTenantPortalUrl security: - AdminApiKey: [] parameters: - name: theme in: query required: false schema: type: string enum: [light, dark] description: Optional theme preference for the portal. responses: "200": description: Portal redirect URL. content: application/json: schema: $ref: "#/components/schemas/PortalRedirect" examples: PortalRedirectExample: value: redirect_url: "https://webhooks.acme.com/?token=JWT_TOKEN&tenant_id=tenant_123" tenant_id: "tenant_123" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/token: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. get: tags: [Tenants] summary: Get Tenant JWT Token description: Returns a JWT token scoped to the tenant for safe browser API calls. Requires Admin API Key. operationId: getTenantToken security: - AdminApiKey: [] responses: "200": description: Tenant JWT token. content: application/json: schema: $ref: "#/components/schemas/TenantToken" examples: TenantTokenExample: value: token: "SOME_JWT_TOKEN" tenant_id: "tenant_123" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" # Destinations /tenants/{tenant_id}/destinations: description: | Manage destinations for a specific tenant. Destinations determine where events are sent. The structure of `config` and `credentials` depends on the destination `type`. parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. get: tags: [Destinations] summary: List Destinations description: Return a list of the destinations for the tenant. The endpoint is not paged. operationId: listTenantDestinations parameters: - name: type in: query required: false schema: oneOf: - $ref: "#/components/schemas/DestinationType" - type: array items: $ref: "#/components/schemas/DestinationType" description: Filter destinations by type(s). Use bracket notation for multiple values (e.g., `type[0]=webhook&type[1]=aws_sqs`). - name: topics in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter destinations by supported topic(s). Use bracket notation for multiple values (e.g., `topics[0]=user.created&topics[1]=user.deleted`). responses: "200": description: A list of destinations. content: application/json: schema: type: array items: $ref: "#/components/schemas/Destination" examples: DestinationsListExample: value: - id: "des_webhook_123" type: "webhook" topics: ["user.created", "order.shipped"] disabled_at: null created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/handler" credentials: secret: "whsec_abc123def456" previous_secret: "whsec_prev789xyz012" previous_secret_invalid_at: "2024-02-16T10:00:00Z" - id: "des_sqs_456" type: "aws_sqs" topics: ["*"] disabled_at: "2024-03-01T12:00:00Z" created_at: "2024-02-20T11:30:00Z" updated_at: "2024-02-20T11:30:00Z" config: queue_url: "https://sqs.us-west-2.amazonaws.com/123456789012/my-app-queue" endpoint: "https://sqs.us-west-2.amazonaws.com" credentials: key: "AKIAIOSFODNN7EXAMPLE" secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" - id: "des_s3_789" type: "aws_s3" topics: ["*"] disabled_at: null created_at: "2024-03-20T12:00:00Z" updated_at: "2024-03-20T12:00:00Z" config: bucket: "my-bucket" region: "us-east-1" credentials: key: "AKIAIOSFODNN7EXAMPLE" secret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" post: tags: [Destinations] summary: Create Destination description: Creates a new destination for the tenant. The request body structure depends on the `type`. operationId: createTenantDestination requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/DestinationCreate" examples: WebhookCreateExample: summary: Create a webhook destination value: type: "webhook" topics: ["user.created", "order.shipped"] config: url: "https://my-service.com/webhook/handler" responses: "201": description: Destination created successfully. content: application/json: schema: $ref: "#/components/schemas/Destination" examples: WebhookCreatedExample: # Example for one type, others similar summary: Webhook destination created value: id: "des_webhook_123" type: "webhook" topics: ["user.created", "order.shipped"] disabled_at: null created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/handler" credentials: secret: "whsec_abc123def456" # previous_secret and previous_secret_invalid_at are absent on creation "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/destinations/{destination_id}: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. - name: destination_id in: path required: true schema: type: string description: The ID of the destination. get: tags: [Destinations] summary: Get Destination description: Retrieves details for a specific destination. operationId: getTenantDestination responses: "200": description: Destination details. content: application/json: schema: $ref: "#/components/schemas/Destination" examples: WebhookGetExample: # Example for one type, others similar value: id: "des_webhook_123" type: "webhook" topics: ["user.created", "order.shipped"] disabled_at: null created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/handler" credentials: secret: "whsec_abc123def456" previous_secret: "whsec_prev789xyz012" previous_secret_invalid_at: "2024-02-16T10:00:00Z" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" patch: tags: [Destinations] summary: Update Destination description: Updates the configuration of an existing destination. The request body structure depends on the destination's `type`. Type itself cannot be updated. May return an OAuth redirect URL for certain types. operationId: updateTenantDestination requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/DestinationUpdate" examples: WebhookUpdateExample: summary: Update a webhook destination's topics and URL value: topics: ["user.created"] config: url: "https://my-service.com/webhook/new-handler" responses: "200": description: Destination updated successfully or OAuth redirect needed. content: application/json: schema: oneOf: - $ref: "#/components/schemas/Destination" examples: DestinationUpdatedExample: summary: Webhook destination updated value: id: "des_webhook_123" type: "webhook" topics: ["user.created"] disabled_at: null created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/new-handler" credentials: secret: "whsec_abc123def456" previous_secret: "whsec_prev789xyz012" previous_secret_invalid_at: "2024-02-16T10:00:00Z" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" delete: tags: [Destinations] summary: Delete Destination description: Deletes a specific destination. operationId: deleteTenantDestination responses: "200": description: Success confirmation. content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" examples: SuccessExample: value: success: true "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/destinations/{destination_id}/enable: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. - name: destination_id in: path required: true schema: type: string description: The ID of the destination. put: tags: [Destinations] summary: Enable Destination description: Enables a previously disabled destination. operationId: enableTenantDestination responses: "200": description: Destination enabled successfully. content: application/json: schema: $ref: "#/components/schemas/Destination" examples: WebhookEnabledExample: # Example for one type, others similar value: id: "des_webhook_123" type: "webhook" topics: ["user.created", "order.shipped"] disabled_at: null # Now enabled created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/handler" credentials: secret: "whsec_abc123def456" previous_secret: "whsec_prev789xyz012" previous_secret_invalid_at: "2024-02-16T10:00:00Z" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/destinations/{destination_id}/disable: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. - name: destination_id in: path required: true schema: type: string description: The ID of the destination. put: tags: [Destinations] summary: Disable Destination description: Disables a previously enabled destination. operationId: disableTenantDestination responses: "200": description: Destination disabled successfully. content: application/json: schema: $ref: "#/components/schemas/Destination" examples: WebhookDisabledExample: # Example for one type, others similar value: id: "des_webhook_123" type: "webhook" topics: ["user.created", "order.shipped"] disabled_at: "2024-04-11T21:00:00Z" # Now disabled created_at: "2024-02-15T10:00:00Z" updated_at: "2024-02-15T10:00:00Z" config: url: "https://my-service.com/webhook/handler" credentials: secret: "whsec_abc123def456" previous_secret: "whsec_prev789xyz012" previous_secret_invalid_at: "2024-02-16T10:00:00Z" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" # Destination-scoped Attempts /tenants/{tenant_id}/destinations/{destination_id}/attempts: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. - name: destination_id in: path required: true schema: type: string description: The ID of the destination. get: tags: [Destinations] summary: List Destination Attempts description: | Retrieves a paginated list of attempts scoped to a specific destination. Returns `404` if the destination does not exist or has been deleted. The attempts of a deleted destination remain available from `GET /attempts?destination_id=`. operationId: listTenantDestinationAttempts parameters: - name: event_id in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter attempts by event ID(s). Use bracket notation for multiple values (e.g., `event_id[0]=e1&event_id[1]=e2`). - name: status in: query required: false schema: type: string enum: [success, failed] description: Filter attempts by status. - name: topic in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter attempts by event topic(s). Use bracket notation for multiple values (e.g., `topic[0]=user.created&topic[1]=user.updated`). - name: time in: query required: false style: deepObject explode: true schema: $ref: "#/components/schemas/Operator" description: Filter attempts by event time range using comparison operators. - name: limit in: query required: false schema: type: integer default: 100 minimum: 1 maximum: 1000 description: Number of items per page (1-1000, default 100). A value outside this range, or one that is not an integer, returns a 400. - name: next in: query required: false schema: type: string description: Cursor for the next page of results, from `pagination.next` of a previous response. Mutually exclusive with `prev`. A cursor that cannot be read returns a 400. - name: prev in: query required: false schema: type: string description: Cursor for the previous page of results, from `pagination.prev` of a previous response. Mutually exclusive with `next`. A cursor that cannot be read returns a 400. - name: include in: query required: false schema: oneOf: - type: string - type: array items: type: string description: | Fields to include in the response. Use bracket notation for multiple values (e.g., `include[0]=event&include[1]=response_data`). - `event`: Include event summary (id, topic, time, eligible_for_retry, metadata) - `event.data`: Include full event with payload data - `response_data`: Include response body and headers - `destination`: Include the destination object, without credentials - name: order_by in: query required: false schema: type: string enum: [time] default: time description: Field to sort by. - name: dir in: query required: false schema: type: string enum: [asc, desc] default: desc description: Sort direction. responses: "200": description: A paginated list of attempts for the destination. content: application/json: schema: $ref: "#/components/schemas/AttemptPaginatedResult" examples: DestinationAttemptsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: "MTcwNDA2NzIwMA==" prev: null models: - id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" - id: "atm_124" status: "failed" time: "2024-01-02T10:00:01Z" code: "503" attempt_number: 2 latency_ms: 1502 event_id: "evt_789" destination_id: "des_456" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/destinations/{destination_id}/attempts/{attempt_id}: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. - name: destination_id in: path required: true schema: type: string description: The ID of the destination. - name: attempt_id in: path required: true schema: type: string description: The ID of the attempt. get: tags: [Destinations] summary: Get Destination Attempt description: | Retrieves details for a specific attempt scoped to a destination. Returns `404` if the destination does not exist or has been deleted, or if the destination has no attempt with this ID. An attempt of a deleted destination remains available from `GET /attempts/{attempt_id}`. operationId: getTenantDestinationAttempt parameters: - name: include in: query required: false schema: oneOf: - type: string - type: array items: type: string description: | Fields to include in the response. Use bracket notation for multiple values (e.g., `include[0]=event&include[1]=response_data`). - `event`: Include event summary - `event.data`: Include full event with payload data - `response_data`: Include response body and headers - `destination`: Include the destination object, without credentials responses: "200": description: Attempt details. content: application/json: schema: $ref: "#/components/schemas/Attempt" examples: DestinationAttemptExample: value: id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" # Publish (Admin Only) /publish: post: tags: [Publish] summary: Publish Event description: Publishes an event to the specified topic, potentially routed to a specific destination. Requires Admin API Key. operationId: publishEvent security: - AdminApiKey: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PublishRequest" example: id: "evt_abc123xyz789" tenant_id: "tenant_123" topic: "user.created" eligible_for_retry: true metadata: source: "crm" data: user_id: "userid" status: "active" responses: "202": description: Event accepted for publishing. Returns the event ID. content: application/json: schema: $ref: "#/components/schemas/PublishResponse" example: id: "evt_abc123xyz789" duplicate: false destination_ids: ["des_webhook_123"] "401": $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" "409": description: Conflict. Another request with the same event `id` is in progress or has just failed. Retry the request. content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" "422": description: The event topic was either required or was invalid. "500": $ref: "#/components/responses/InternalServerError" # Retry /retry: post: tags: [Retry] summary: Retry Event Delivery description: | Triggers a retry for delivering an event to a destination. The event must exist, and the destination must be enabled, match the event's topic and filter, and already have a delivery attempt for the event. A retry never sends an event to a destination that has no earlier attempt for it. Returns 404 `event not found` if the event does not exist, or belongs to another tenant when authenticated with a Tenant JWT. Returns 404 `destination not found` if the destination does not exist for the event's tenant or has been deleted. When authenticated with a Tenant JWT, only events belonging to that tenant can be retried. When authenticated with Admin API Key, events from any tenant can be retried. operationId: retryEvent requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/RetryRequest" example: event_id: "evt_abc123xyz789" destination_id: "des_webhook_123" responses: "202": description: Retry accepted for processing. content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" examples: RetryAccepted: value: success: true "400": description: | Bad request. This can happen when: - The destination is disabled - The destination does not match the event's topic or filter - The event has no delivery attempt for the destination "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "422": $ref: "#/components/responses/ValidationError" "500": $ref: "#/components/responses/InternalServerError" /destination-types: get: tags: [Schemas] summary: List Destination Type Schemas description: Returns a list of JSON-based input schemas for each available destination type. operationId: listDestinationTypeSchemas responses: "200": description: A list of destination type schemas. content: application/json: schema: type: array items: $ref: "#/components/schemas/DestinationTypeSchema" examples: DestinationTypesExample: # Same as /{tenant_id}/destination-types example value: - type: "webhook" label: "Webhook" description: "Send event via an HTTP POST request to a URL" icon: "" instructions: "Enter the URL..." config_fields: [ { key: "url", type: "text", label: "URL", description: "The URL to send the webhook to.", pattern: "^https?://.*", # Example pattern required: true, }, ] credential_fields: [ { key: "secret", type: "text", label: "Secret", description: "Optional signing secret.", required: false, sensitive: true, # Added sensitive }, ] - type: "kafka" label: "Apache Kafka" description: "Send events to Apache Kafka topics for real-time event streaming" icon: "" config_fields: [ { key: "brokers", type: "text", label: "Brokers", description: "Comma-separated list of Kafka broker addresses.", required: true, }, { key: "topic", type: "text", label: "Topic", description: "The Kafka topic to publish messages to.", required: true, }, { key: "tls", type: "checkbox", label: "TLS", description: "Enable TLS for the connection.", default: "true", }, { key: "partition_key_template", type: "text", label: "Partition Key Template", description: "JMESPath template to extract the partition key from the event payload.", required: false, }, { key: "sasl_mechanism", type: "select", label: "SASL Mechanism", description: "SASL authentication mechanism.", required: true, options: [ { label: "PLAIN", value: "plain" }, { label: "SCRAM-SHA-256", value: "scram-sha-256" }, { label: "SCRAM-SHA-512", value: "scram-sha-512" }, ], }, ] credential_fields: [ { key: "username", type: "text", label: "Username", description: "SASL username for authentication.", required: true, }, { key: "password", type: "text", label: "Password", description: "SASL password for authentication.", required: true, sensitive: true, }, ] - type: "aws_sqs" label: "AWS SQS" description: "Send event to an AWS SQS queue" icon: "" instructions: "Enter Queue URL..." config_fields: [ { key: "queue_url", type: "text", label: "Queue URL", description: "The URL of the SQS queue.", required: true, }, { key: "endpoint", type: "text", label: "Endpoint", description: "Optional custom AWS endpoint URL.", required: false, }, ] credential_fields: [ { key: "key", type: "text", label: "Key", description: "AWS Access Key ID.", required: true, sensitive: true, }, { key: "secret", type: "text", label: "Secret", description: "AWS Secret Access Key.", required: true, sensitive: true, }, { key: "session", type: "text", label: "Session", description: "Optional AWS Session Token.", required: false, sensitive: true, }, ] "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" /destination-types/{type}: parameters: - name: type in: path required: true schema: type: string enum: [webhook, aws_sqs, rabbitmq, hookdeck, aws_kinesis, azure_servicebus, aws_s3, gcp_pubsub, kafka, cloudflare_queues, aws_eventbridge] description: The type of the destination. get: tags: [Schemas] summary: Get Destination Type Schema description: Returns the input schema for a specific destination type. operationId: getDestinationTypeSchema responses: "200": description: The schema for the specified destination type. content: application/json: schema: $ref: "#/components/schemas/DestinationTypeSchema" examples: WebhookSchemaExample: # Same as /{tenant_id}/destination-types/{type} example value: type: "webhook" label: "Webhook" description: "Send event via an HTTP POST request to a URL" icon: "" instructions: "Enter the URL..." # setup_link is optional, omitted here config_fields: [ { key: "url", type: "text", label: "URL", description: "The URL to send the webhook to.", pattern: "^https?://.*", # Example pattern required: true, }, ] credential_fields: [ { key: "secret", type: "text", label: "Secret", description: "Optional signing secret.", required: false, sensitive: true, # Added sensitive }, ] "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /topics: get: tags: [Topics] summary: List Available Topics description: Returns a list of available event topics configured in the Outpost instance. operationId: listTopics responses: "200": description: A list of topic names. content: application/json: schema: type: array items: type: string examples: TopicsListExample: # Same as /{tenant_id}/topics example value: [ "user.created", "user.updated", "order.shipped", "inventory.updated", ] "401": $ref: "#/components/responses/Unauthorized" "500": $ref: "#/components/responses/InternalServerError" /metrics/events: get: tags: [Metrics] summary: Get Event Metrics description: | Returns aggregated event publish metrics. Supports time bucketing via granularity, dimensional grouping, and filtering. **Measures:** `count`, `rate` **Dimensions:** `tenant_id` (admin-only), `topic`, `destination_id` **Filters:** `tenant_id` (admin-only), `topic`, `destination_id` operationId: getEventMetrics parameters: - name: time in: query required: true style: deepObject explode: true schema: type: object required: - start - end properties: start: type: string format: date-time description: Start of the time range (inclusive). ISO 8601 timestamp. example: "2026-03-02T00:00:00Z" end: type: string format: date-time description: End of the time range (exclusive). ISO 8601 timestamp. example: "2026-03-03T00:00:00Z" description: Time range for the metrics query. - name: granularity in: query required: false schema: type: string description: | Time bucketing granularity. Pattern: ``. Units: `s` (1-60), `m` (1-60), `h` (1-24), `d` (1-31), `w` (1-4), `M` (1-12). When omitted, returns a single aggregate row per dimension combination. example: "1h" - name: measures in: query required: true schema: oneOf: - type: string enum: [count, rate] - type: array items: type: string enum: [count, rate] description: Measures to compute. At least one required. `rate` is events/second throughput. Use bracket notation for multiple values (e.g., `measures[0]=count`). example: ["count"] - name: dimensions in: query required: false schema: oneOf: - type: string enum: [tenant_id, topic, destination_id] - type: array items: type: string enum: [tenant_id, topic, destination_id] description: Dimensions to group results by. Use bracket notation for multiple values (e.g., `dimensions[0]=topic&dimensions[1]=destination_id`). - name: filters[topic] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by topic name(s). Use bracket notation for multiple values (e.g., `filters[topic][0]=user.created&filters[topic][1]=user.updated`). - name: filters[destination_id] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by destination ID(s). Use bracket notation for multiple values (e.g., `filters[destination_id][0]=d1&filters[destination_id][1]=d2`). - name: filters[tenant_id] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by tenant ID(s). Admin-only — rejected with 403 for JWT callers. Use bracket notation for multiple values (e.g., `filters[tenant_id][0]=t1&filters[tenant_id][1]=t2`). responses: "200": description: Aggregated event metrics. content: application/json: schema: $ref: "#/components/schemas/MetricsResponse" examples: HourlyEventCount: value: data: - time_bucket: "2026-03-02T14:00:00Z" dimensions: topic: "user.created" metrics: count: 1423 - time_bucket: "2026-03-02T15:00:00Z" dimensions: topic: "user.created" metrics: count: 1891 metadata: granularity: "1h" query_time_ms: 42 row_count: 2 row_limit: 100000 truncated: false "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": description: JWT caller attempted to use admin-only dimension or filter (tenant_id). content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" "500": $ref: "#/components/responses/InternalServerError" /metrics/attempts: get: tags: [Metrics] summary: Get Attempt Metrics description: | Returns aggregated delivery attempt metrics. Supports time bucketing via granularity, dimensional grouping, and filtering. **Measures:** `count`, `successful_count`, `failed_count`, `error_rate`, `first_attempt_count`, `retry_count`, `manual_retry_count`, `avg_attempt_number`, `rate`, `successful_rate`, `failed_rate`, `avg_latency`, `p50_latency`, `p95_latency`, `p99_latency` Latency measures are in milliseconds and computed over attempts that recorded a latency (see `latency_ms` on the attempt object). They are `null` for a bucket with no such attempts, rather than `0`. **Dimensions:** `tenant_id` (admin-only), `destination_id`, `destination_type`, `topic`, `status`, `code`, `manual`, `attempt_number` **Filters:** `tenant_id` (admin-only), `destination_id`, `destination_type`, `topic`, `status`, `code`, `manual`, `attempt_number` operationId: getAttemptMetrics parameters: - name: time in: query required: true style: deepObject explode: true schema: type: object required: - start - end properties: start: type: string format: date-time description: Start of the time range (inclusive). ISO 8601 timestamp. example: "2026-03-02T00:00:00Z" end: type: string format: date-time description: End of the time range (exclusive). ISO 8601 timestamp. example: "2026-03-03T00:00:00Z" description: Time range for the metrics query. - name: granularity in: query required: false schema: type: string description: | Time bucketing granularity. Pattern: ``. Units: `s` (1-60), `m` (1-60), `h` (1-24), `d` (1-31), `w` (1-4), `M` (1-12). When omitted, returns a single aggregate row per dimension combination. example: "1h" - name: measures in: query required: true schema: oneOf: - type: string enum: [count, successful_count, failed_count, error_rate, first_attempt_count, retry_count, manual_retry_count, avg_attempt_number, rate, successful_rate, failed_rate, avg_latency, p50_latency, p95_latency, p99_latency] - type: array items: type: string enum: [count, successful_count, failed_count, error_rate, first_attempt_count, retry_count, manual_retry_count, avg_attempt_number, rate, successful_rate, failed_rate, avg_latency, p50_latency, p95_latency, p99_latency] description: Measures to compute. At least one required. Rate measures (`rate`, `successful_rate`, `failed_rate`) are throughput in events/second. Latency measures (`avg_latency`, `p50_latency`, `p95_latency`, `p99_latency`) are destination response times in milliseconds, `null` when no attempt in the bucket recorded a latency. Use bracket notation for multiple values (e.g., `measures[0]=count&measures[1]=error_rate`). example: ["count", "error_rate", "p95_latency"] - name: dimensions in: query required: false schema: oneOf: - type: string enum: [tenant_id, destination_id, destination_type, topic, status, code, manual, attempt_number] - type: array items: type: string enum: [tenant_id, destination_id, destination_type, topic, status, code, manual, attempt_number] description: Dimensions to group results by. Use bracket notation for multiple values (e.g., `dimensions[0]=status&dimensions[1]=destination_id`). - name: filters[destination_id] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by destination ID(s). Use bracket notation for multiple values (e.g., `filters[destination_id][0]=d1&filters[destination_id][1]=d2`). - name: filters[destination_type] in: query required: false schema: oneOf: - $ref: "#/components/schemas/DestinationType" - type: array items: $ref: "#/components/schemas/DestinationType" description: Filter by destination type(s). Use bracket notation for multiple values (e.g., `filters[destination_type][0]=webhook&filters[destination_type][1]=aws_sqs`). - name: filters[topic] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by topic name(s). Use bracket notation for multiple values (e.g., `filters[topic][0]=user.created&filters[topic][1]=user.updated`). - name: filters[status] in: query required: false schema: oneOf: - type: string enum: [success, failed] - type: array items: type: string enum: [success, failed] description: Filter by attempt status(es). Use bracket notation for multiple values (e.g., `filters[status][0]=success&filters[status][1]=failed`). - name: filters[code] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by HTTP status code(s). Use bracket notation for multiple values (e.g., `filters[code][0]=200&filters[code][1]=500`). - name: filters[manual] in: query required: false schema: type: string enum: ["true", "false"] description: Filter by manual retry flag. - name: filters[attempt_number] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by attempt number(s). Use bracket notation for multiple values (e.g., `filters[attempt_number][0]=1&filters[attempt_number][1]=2`). - name: filters[tenant_id] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by tenant ID(s). Admin-only — rejected with 403 for JWT callers. Use bracket notation for multiple values (e.g., `filters[tenant_id][0]=t1&filters[tenant_id][1]=t2`). responses: "200": description: Aggregated attempt metrics. content: application/json: schema: $ref: "#/components/schemas/MetricsResponse" examples: DailyAttemptCounts: value: data: - time_bucket: "2026-03-02T00:00:00Z" dimensions: destination_id: "dest_abc" metrics: count: 1423 successful_count: 1393 failed_count: 30 error_rate: 0.0211 avg_latency: 212.4 p95_latency: 810 metadata: granularity: "1d" query_time_ms: 38 row_count: 1 row_limit: 100000 truncated: false "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": description: JWT caller attempted to use admin-only dimension or filter (tenant_id). content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" "500": $ref: "#/components/responses/InternalServerError"