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 AttemptDestination: type: object description: The destination an attempt was sent to, without credentials. Use the destination endpoints to retrieve credentials. required: [id, tenant_id, type, topics, config, created_at, updated_at, disabled_at, target] properties: id: type: string description: Control plane generated ID or user provided ID for the destination. example: "des_12345" tenant_id: type: string description: The tenant the destination belongs to. example: "tenant_123" type: type: string description: Type of the destination. example: "webhook" topics: $ref: "#/components/schemas/Topics" filter: $ref: "#/components/schemas/Filter" config: type: object additionalProperties: type: string description: Type-specific destination configuration. example: { "url": "https://my-service.com/webhook/handler" } delivery_metadata: type: object additionalProperties: type: string nullable: true description: Static key-value pairs merged into event metadata on every attempt. example: { "app-id": "my-app", "region": "us-east-1" } metadata: type: object additionalProperties: type: string nullable: true description: Arbitrary contextual information stored with the destination. example: { "internal-id": "123", "team": "platform" } disabled_at: type: string format: date-time nullable: true description: ISO Date when the destination was disabled, or null if enabled. example: null created_at: type: string format: date-time description: ISO Date when the destination was created. example: "2024-01-01T00:00:00Z" updated_at: type: string format: date-time description: ISO Date when the destination was last updated. example: "2024-01-01T00:00:00Z" target: type: string description: A human-readable representation of the destination target (e.g., URL host). Read-only. readOnly: true example: "my-service.com" target_url: type: string format: url nullable: true description: A URL link to the destination target. Read-only. readOnly: true example: "https://my-service.com/webhook/handler" Attempt: type: object description: An attempt represents a single delivery attempt of an event to a destination. properties: id: type: string description: Unique identifier for this attempt. example: "atm_123" tenant_id: type: string description: The tenant this attempt belongs to. example: "tnt_123" status: type: string enum: [success, failed] description: The attempt status. example: "success" time: type: string format: date-time description: Time the attempt was made. example: "2024-01-01T00:00:05Z" code: type: string description: Response status code or error code. example: "200" response_data: type: object nullable: true description: Response data from the attempt. Only included when include=response_data. additionalProperties: true example: { "status_code": 200, "body": '{"status":"ok"}', "headers": { "content-type": "application/json" } } attempt_number: type: integer description: The attempt number (1 for first attempt, 2+ for retries). example: 1 manual: type: boolean description: Whether this attempt was manually triggered (e.g., a retry initiated by a user). example: false latency_ms: type: integer nullable: true description: Time in milliseconds from sending the attempt to receiving the destination's response (or the error), measured around the provider's publish call. Null for attempts that never reached the provider and for attempts recorded before latency was tracked. example: 212 event_id: type: string description: The ID of the associated event. example: "evt_123" destination_id: type: string description: The destination ID this attempt was sent to. example: "des_456" event: nullable: true oneOf: - $ref: "#/components/schemas/EventFull" - $ref: "#/components/schemas/EventSummary" description: The associated event object. Only present when include=event or include=event.data. destination: nullable: true $ref: "#/components/schemas/AttemptDestination" description: The destination object, without credentials. Only present when include=destination. EventSummary: type: object description: Event object without data (returned when include=event). properties: id: type: string example: "evt_123" tenant_id: type: string description: The tenant this event belongs to. example: "tnt_123" destination_id: type: string description: The destination this event was delivered to. example: "des_456" topic: type: string example: "user.created" time: type: string format: date-time description: Time the event was received. example: "2024-01-01T00:00:00Z" eligible_for_retry: type: boolean description: Whether this event can be retried. example: true metadata: type: object additionalProperties: type: string nullable: true example: { "source": "crm" } EventFull: type: object description: Full event object with data (returned when include=event.data). properties: id: type: string example: "evt_123" tenant_id: type: string description: The tenant this event belongs to. example: "tnt_123" destination_id: type: string description: The destination this event was delivered to. example: "des_456" topic: type: string example: "user.created" time: type: string format: date-time description: Time the event was received. example: "2024-01-01T00:00:00Z" eligible_for_retry: type: boolean description: Whether this event can be retried. example: true metadata: type: object additionalProperties: type: string nullable: true example: { "source": "crm" } data: type: object additionalProperties: true description: The event payload data. example: { "user_id": "userid", "status": "active" } AttemptPaginatedResult: type: object description: Paginated list of attempts. properties: pagination: $ref: "#/components/schemas/SeekPagination" models: type: array items: $ref: "#/components/schemas/Attempt" description: Array of attempt objects. EventPaginatedResult: type: object description: Paginated list of events. properties: pagination: $ref: "#/components/schemas/SeekPagination" models: type: array items: $ref: "#/components/schemas/Event" description: Array of event objects. # Destination Type Schema (for Metadata endpoint) DestinationType: type: string enum: - webhook - aws_sqs - rabbitmq - hookdeck - aws_kinesis - azure_servicebus - aws_s3 - gcp_pubsub 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_COMPAT_HEADERS: type: string description: >- Additional headers sent with the compat signature, as comma-separated "name=template" pairs. Available variables: {{.EventID}}, {{.Topic}}, {{.Timestamp}}. Use "\," for a literal comma in a template. DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ALGORITHM: type: string description: >- Algorithm for the compat signature. Defaults to "hmac-sha256". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_CONTENT_TEMPLATE: type: string description: >- Go template for the content signed by the compat signature. Same variables as DESTINATIONS_WEBHOOK_SIGNATURE_CONTENT_TEMPLATE. Defaults to "{{.Body}}". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_ENCODING: type: string description: >- Encoding for the compat signature ("hex" or "base64"). Defaults to "hex". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_NAME: type: string description: >- Complete name of the compat signature header. Setting it sends a second signature, in a previous scheme, alongside the primary one. DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_HEADER_TEMPLATE: type: string description: >- Go template for the value of the compat signature header. Same variables as DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_TEMPLATE. Defaults to "v0={{.Signatures | join ","}}". DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_ENCODING: type: string description: >- How the compat signature derives its HMAC key from the destination secret: "raw", "base64" or "hex". Defaults to "raw". A destination whose secret can't be decoded doesn't receive the compat signature. DESTINATIONS_WEBHOOK_COMPAT_SIGNATURE_SECRET_PREFIX: type: string description: >- Prefix stripped from the destination secret before decoding for the compat signature (e.g., "whsec_"). DESTINATIONS_WEBHOOK_EVENT_ID_HEADER_NAME: type: string description: >- Complete name of the event ID header. Unset uses the default "event-id"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. DESTINATIONS_WEBHOOK_HEADER_PREFIX: type: string DESTINATIONS_WEBHOOK_MODE: type: string DESTINATIONS_WEBHOOK_PROXY_URL: type: string DESTINATIONS_WEBHOOK_SIGNATURE_ALGORITHM: type: string DESTINATIONS_WEBHOOK_SIGNATURE_CONTENT_TEMPLATE: type: string DESTINATIONS_WEBHOOK_SIGNATURE_ENCODING: type: string DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_NAME: type: string description: >- Complete name of the signature header. Unset uses the default "signature"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_TEMPLATE: type: string DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_ENCODING: type: string description: >- How the signature derives its HMAC key from the destination secret: "raw" uses the secret as-is, "base64" and "hex" decode it. Defaults to "raw". DESTINATIONS_WEBHOOK_SIGNING_SECRET_TEMPLATE must generate secrets this encoding can decode. Only applies to "default" mode. DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_PREFIX: type: string description: >- Prefix stripped from the destination secret before decoding (e.g., "whsec_"). Ignored when DESTINATIONS_WEBHOOK_SIGNATURE_SECRET_ENCODING is "raw". Only applies to "default" mode. DESTINATIONS_WEBHOOK_SIGNING_SECRET_TEMPLATE: type: string DESTINATIONS_WEBHOOK_TIMESTAMP_FORMAT: type: string description: >- Format of the timestamp header: "rfc3339" or "unix". Defaults to "rfc3339". Only applies to "default" mode. DESTINATIONS_WEBHOOK_TIMESTAMP_HEADER_NAME: type: string description: >- Complete name of the timestamp header. Unset uses the default "timestamp"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. DESTINATIONS_WEBHOOK_TOPIC_HEADER_NAME: type: string description: >- Complete name of the topic header. Unset uses the default "topic"; an explicit value pins that exact name; an empty string disables the header. Only applies to "default" mode. HTTP_USER_AGENT: type: string IDGEN_ATTEMPT_PREFIX: type: string IDGEN_DESTINATION_PREFIX: type: string IDGEN_EVENT_PREFIX: type: string IDGEN_TYPE: type: string MAX_DESTINATIONS_PER_TENANT: type: string PORTAL_BRAND_COLOR: type: string PORTAL_DISABLE_OUTPOST_BRANDING: type: string PORTAL_FAVICON_URL: type: string PORTAL_FORCE_THEME: type: string PORTAL_LOGO: type: string PORTAL_LOGO_DARK: type: string PORTAL_ORGANIZATION_NAME: type: string PORTAL_REFERER_URL: type: string PORTAL_REFRESH_URL: type: string PORTAL_ENABLE_DESTINATION_FILTER: type: string PORTAL_ENABLE_WEBHOOK_CUSTOM_HEADERS: type: string RETRY_INTERVAL_SECONDS: type: string MAX_RETRY_LIMIT: type: string RETRY_SCHEDULE: type: string OTEL_EXPORTER_OTLP_ENDPOINT: type: string OTEL_EXPORTER_OTLP_HEADERS: type: string OTEL_EXPORTER_OTLP_PROTOCOL: type: string OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: type: string OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: type: string OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: type: string OTEL_SERVICE_NAME: type: string PUBLISH_AWS_SQS_ACCESS_KEY_ID: type: string PUBLISH_AWS_SQS_ENDPOINT: type: string PUBLISH_AWS_SQS_QUEUE: type: string PUBLISH_AWS_SQS_REGION: type: string PUBLISH_AWS_SQS_SECRET_ACCESS_KEY: type: string PUBLISH_AZURE_SERVICEBUS_CONNECTION_STRING: type: string PUBLISH_AZURE_SERVICEBUS_SUBSCRIPTION: type: string PUBLISH_AZURE_SERVICEBUS_TOPIC: type: string PUBLISH_GCP_PUBSUB_PROJECT: type: string PUBLISH_GCP_PUBSUB_SERVICE_ACCOUNT_CREDENTIALS: type: string PUBLISH_GCP_PUBSUB_SUBSCRIPTION: type: string PUBLISH_GCP_PUBSUB_TOPIC: type: string PUBLISH_RABBITMQ_EXCHANGE: type: string PUBLISH_RABBITMQ_QUEUE: type: string PUBLISH_RABBITMQ_SERVER_URL: type: string TOPICS: type: string TOPICS_ALLOW_WILDCARDS: type: string additionalProperties: false example: TOPICS: "user.created,user.updated" DESTINATIONS_WEBHOOK_MODE: "default" # 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 destination object with target information, without credentials - name: Events description: | An event represents a payload published to Outpost. Events are matched against all destinations whose topic subscriptions match the event topic, then delivered. - name: Metrics description: | Aggregated metrics for events and delivery attempts. Supports time bucketing, dimensional grouping, and filtering. paths: /healthz: get: tags: [Health] summary: Health Check description: | Health check endpoint that reports the status of all workers. > This endpoint is only available for **self-hosted** Outpost deployments. Managed Outpost health is monitored by Hookdeck. 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 destination object, without credentials - name: order_by in: query required: false schema: type: string enum: [time] default: time description: Field to sort by. - name: dir in: query required: false schema: type: string enum: [asc, desc] default: desc description: Sort direction. responses: "200": description: A paginated list of attempts. content: application/json: schema: $ref: "#/components/schemas/AttemptPaginatedResult" examples: AdminAttemptsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: "MTcwNDA2NzIwMA==" prev: null models: - id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" - id: "att_124" status: "failed" time: "2024-01-02T10:00:01Z" code: "503" attempt_number: 2 latency_ms: 1502 event_id: "evt_789" destination_id: "des_789" AdminAttemptsWithIncludeExample: summary: Response with include=event value: pagination: order_by: "time" dir: "desc" limit: 100 next: null prev: null models: - id: "del_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" event: id: "evt_123" topic: "user.created" time: "2024-01-01T00:00:00Z" eligible_for_retry: false metadata: { "source": "crm" } "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 destination object, without credentials responses: "200": description: Attempt details. content: application/json: schema: $ref: "#/components/schemas/Attempt" examples: AttemptExample: value: id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" AttemptWithIncludeExample: summary: Response with include=event.data,response_data value: id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" response_data: status_code: 200 body: '{"status":"ok"}' headers: { "content-type": "application/json" } attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" event: id: "evt_123" topic: "user.created" time: "2024-01-01T00:00:00Z" eligible_for_retry: false metadata: { "source": "crm" } data: { "user_id": "userid", "status": "active" } "401": $ref: "#/components/responses/Unauthorized" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/InternalServerError" /tenants/{tenant_id}/portal: parameters: - name: tenant_id in: path required: true schema: type: string description: The ID of the tenant. Required when using AdminApiKey authentication. get: tags: [Tenants] summary: Get Portal Redirect URL description: Returns a redirect URL containing a JWT to authenticate the user with the portal. Requires Admin API Key. operationId: getTenantPortalUrl security: - AdminApiKey: [] parameters: - name: theme in: query required: false schema: type: string enum: [light, dark] description: Optional theme preference for the portal. responses: "200": description: Portal redirect URL. content: application/json: schema: $ref: "#/components/schemas/PortalRedirect" examples: PortalRedirectExample: value: redirect_url: "https://webhooks.acme.com/?token=JWT_TOKEN&tenant_id=tenant_123" tenant_id: "tenant_123" "401": $ref: "#/components/responses/Unauthorized" "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 destination object, without credentials - name: order_by in: query required: false schema: type: string enum: [time] default: time description: Field to sort by. - name: dir in: query required: false schema: type: string enum: [asc, desc] default: desc description: Sort direction. responses: "200": description: A paginated list of attempts for the destination. content: application/json: schema: $ref: "#/components/schemas/AttemptPaginatedResult" examples: DestinationAttemptsListExample: value: pagination: order_by: "time" dir: "desc" limit: 100 next: "MTcwNDA2NzIwMA==" prev: null models: - id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" - id: "atm_124" status: "failed" time: "2024-01-02T10:00:01Z" code: "503" attempt_number: 2 latency_ms: 1502 event_id: "evt_789" destination_id: "des_456" "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 destination object, without credentials responses: "200": description: Attempt details. content: application/json: schema: $ref: "#/components/schemas/Attempt" examples: DestinationAttemptExample: value: id: "atm_123" status: "success" time: "2024-01-01T00:00:05Z" code: "200" attempt_number: 1 latency_ms: 212 event_id: "evt_123" destination_id: "des_456" "401": $ref: "#/components/responses/Unauthorized" "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`, `avg_latency`, `p50_latency`, `p95_latency`, `p99_latency` Latency measures are in milliseconds and computed over attempts that recorded a latency (see `latency_ms` on the attempt object). They are `null` for a bucket with no such attempts, rather than `0`. **Dimensions:** `tenant_id` (admin-only), `destination_id`, `destination_type`, `topic`, `status`, `code`, `manual`, `attempt_number` **Filters:** `tenant_id` (admin-only), `destination_id`, `destination_type`, `topic`, `status`, `code`, `manual`, `attempt_number` operationId: getAttemptMetrics parameters: - name: time in: query required: true style: deepObject explode: true schema: type: object required: - start - end properties: start: type: string format: date-time description: Start of the time range (inclusive). ISO 8601 timestamp. example: "2026-03-02T00:00:00Z" end: type: string format: date-time description: End of the time range (exclusive). ISO 8601 timestamp. example: "2026-03-03T00:00:00Z" description: Time range for the metrics query. - name: granularity in: query required: false schema: type: string description: | Time bucketing granularity. Pattern: ``. Units: `s` (1-60), `m` (1-60), `h` (1-24), `d` (1-31), `w` (1-4), `M` (1-12). When omitted, returns a single aggregate row per dimension combination. example: "1h" - name: measures in: query required: true schema: oneOf: - type: string enum: [count, successful_count, failed_count, error_rate, first_attempt_count, retry_count, manual_retry_count, avg_attempt_number, rate, successful_rate, failed_rate, avg_latency, p50_latency, p95_latency, p99_latency] - type: array items: type: string enum: [count, successful_count, failed_count, error_rate, first_attempt_count, retry_count, manual_retry_count, avg_attempt_number, rate, successful_rate, failed_rate, avg_latency, p50_latency, p95_latency, p99_latency] description: Measures to compute. At least one required. Rate measures (`rate`, `successful_rate`, `failed_rate`) are throughput in events/second. Latency measures (`avg_latency`, `p50_latency`, `p95_latency`, `p99_latency`) are destination response times in milliseconds, `null` when no attempt in the bucket recorded a latency. Use bracket notation for multiple values (e.g., `measures[0]=count&measures[1]=error_rate`). example: ["count", "error_rate", "p95_latency"] - name: dimensions in: query required: false schema: oneOf: - type: string enum: [tenant_id, destination_id, destination_type, topic, status, code, manual, attempt_number] - type: array items: type: string enum: [tenant_id, destination_id, destination_type, topic, status, code, manual, attempt_number] description: Dimensions to group results by. Use bracket notation for multiple values (e.g., `dimensions[0]=status&dimensions[1]=destination_id`). - name: filters[destination_id] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by destination ID(s). Use bracket notation for multiple values (e.g., `filters[destination_id][0]=d1&filters[destination_id][1]=d2`). - name: filters[destination_type] in: query required: false schema: oneOf: - $ref: "#/components/schemas/DestinationType" - type: array items: $ref: "#/components/schemas/DestinationType" description: Filter by destination type(s). Use bracket notation for multiple values (e.g., `filters[destination_type][0]=webhook&filters[destination_type][1]=aws_sqs`). - name: filters[topic] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by topic name(s). Use bracket notation for multiple values (e.g., `filters[topic][0]=user.created&filters[topic][1]=user.updated`). - name: filters[status] in: query required: false schema: oneOf: - type: string enum: [success, failed] - type: array items: type: string enum: [success, failed] description: Filter by attempt status(es). Use bracket notation for multiple values (e.g., `filters[status][0]=success&filters[status][1]=failed`). - name: filters[code] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by HTTP status code(s). Use bracket notation for multiple values (e.g., `filters[code][0]=200&filters[code][1]=500`). - name: filters[manual] in: query required: false schema: type: string enum: ["true", "false"] description: Filter by manual retry flag. - name: filters[attempt_number] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by attempt number(s). Use bracket notation for multiple values (e.g., `filters[attempt_number][0]=1&filters[attempt_number][1]=2`). - name: filters[tenant_id] in: query required: false schema: oneOf: - type: string - type: array items: type: string description: Filter by tenant ID(s). Admin-only — rejected with 403 for JWT callers. Use bracket notation for multiple values (e.g., `filters[tenant_id][0]=t1&filters[tenant_id][1]=t2`). responses: "200": description: Aggregated attempt metrics. content: application/json: schema: $ref: "#/components/schemas/MetricsResponse" examples: DailyAttemptCounts: value: data: - time_bucket: "2026-03-02T00:00:00Z" dimensions: destination_id: "dest_abc" metrics: count: 1423 successful_count: 1393 failed_count: 30 error_rate: 0.0211 avg_latency: 212.4 p95_latency: 810 metadata: granularity: "1d" query_time_ms: 38 row_count: 1 row_limit: 100000 truncated: false "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized" "403": description: JWT caller attempted to use admin-only dimension or filter (tenant_id). content: application/json: schema: $ref: "#/components/schemas/APIErrorResponse" "500": $ref: "#/components/responses/InternalServerError"