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. 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: Outpost API (production) - url: http://localhost:3333/api/v1 description: Local development server base path components: securitySchemes: AdminApiKey: type: http scheme: bearer description: Admin API Key configured via API_KEY environment variable. 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" 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..." 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" # 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" 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" 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 # 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" 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" # 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. 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 # 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" 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" # 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" 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 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 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/Destination" description: The destination object. 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 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: | Managed configuration values for Outpost Cloud. This API is available only on the managed version. 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_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_SIGNING_SECRET_TEMPLATE: type: string 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" # Security is applied per-operation based on AuthScope tags: - name: Health description: | This endpoint is only available for **self-hosted** Outpost deployments. Managed Outpost health is monitored by Hookdeck. - name: Configuration description: | The Configuration API is available for **managed Outpost** deployments only. It allows you to read and update instance-level settings — the same settings available as environment variables in self-hosted deployments. - 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 and match the event's topic. - 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 full destination object with target information - 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. Returns HTTP 200 when all workers are healthy, 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 security: [] responses: "200": description: Service is healthy - all workers are operational. content: application/json: schema: type: object required: - status - timestamp - workers properties: status: type: string enum: [healthy] 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] example: healthy example: status: healthy timestamp: "2025-11-11T10:30:00Z" workers: http-server: status: healthy retrymq-consumer: status: healthy "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, failed] example: failed example: status: failed timestamp: "2025-11-11T10:30:15Z" workers: http-server: status: healthy retrymq-consumer: status: failed /config: get: tags: [Configuration] summary: Get Managed Configuration description: | Returns managed Outpost configuration values. This endpoint is only available for the managed version. In self-hosted deployments, configuration is controlled through environment variables instead. operationId: getManagedConfig 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 for the managed version. In self-hosted deployments, configuration is controlled through environment variables instead. Only the supported configuration keys are accepted. operationId: updateManagedConfig 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" # 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" "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" "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" "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" "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 (default 100, max 1000). - name: next in: query required: false schema: type: string description: Cursor for next page of results. - name: prev in: query required: false schema: type: string description: Cursor for previous page of results. - 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..." } "401": $ref: "#/components/responses/Unauthorized" "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 (default 100, max 1000). - name: next in: query required: false schema: type: string description: Cursor for next page of results. - name: prev in: query required: false schema: type: string description: Cursor for previous page of results. - 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 full destination object - 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 event_id: "evt_123" destination_id: "des_456" - id: "att_124" status: "failed" time: "2024-01-02T10:00:01Z" code: "503" attempt_number: 2 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 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" } "401": $ref: "#/components/responses/Unauthorized" "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 full destination object 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 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 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" "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" "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" "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 "401": $ref: "#/components/responses/Unauthorized" "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" "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" "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" "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" "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" "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. 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 (default 100, max 1000). - name: next in: query required: false schema: type: string description: Cursor for next page of results. - name: prev in: query required: false schema: type: string description: Cursor for previous page of results. - 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 full destination object - 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 event_id: "evt_123" destination_id: "des_456" - id: "atm_124" status: "failed" time: "2024-01-02T10:00:01Z" code: "503" attempt_number: 2 event_id: "evt_789" destination_id: "des_456" "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "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. 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 full destination object 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 event_id: "evt_123" destination_id: "des_456" "401": $ref: "#/components/responses/Unauthorized" "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" "409": description: Conflict. An event with the provided `id` already exists. "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 and match the event's topic. 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 "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "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] 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` **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] - 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] description: Measures to compute. At least one required. Rate measures (`rate`, `successful_rate`, `failed_rate`) are throughput in events/second. Use bracket notation for multiple values (e.g., `measures[0]=count&measures[1]=error_rate`). example: ["count", "error_rate"] - 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 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"