# Generated by `pnpm openapi:generate`; do not edit by hand. openapi: 3.1.0 info: title: dotpipe Control Plane API version: 0.1.0 description: Create and manage sources and poll their retained events. This contract covers the API-key-accessible control plane only. Dashboard-only API-key creation, listing, and revocation server functions are intentionally excluded. paths: /api/sources: get: tags: - Sources operationId: listSources parameters: [] security: - bearerAuth: [] responses: "200": description: The active sources. content: application/json: schema: $ref: "#/components/schemas/ListSourcesResponse" "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Lists active sources owned by the workspace associated with the API key. summary: List sources post: tags: - Sources operationId: createSource parameters: [] security: - bearerAuth: [] responses: "201": description: The source was created. The response includes its confidential webhook capability URL. content: application/json: schema: $ref: "#/components/schemas/CreatedSource" "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "403": description: The workspace already has the maximum number of sources. content: application/json: schema: $ref: "#/components/schemas/SourceLimitReachedError" "409": description: A source with the normalized name already exists. content: application/json: schema: $ref: "#/components/schemas/NameTakenError" "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error summary: Create a source requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateSourceRequest" required: true /api/sources/{sourceId}: get: tags: - Sources operationId: getSource parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true security: - bearerAuth: [] responses: "200": description: The source details. content: application/json: schema: $ref: "#/components/schemas/SourceDetails" "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Returns configuration, cursor state, storage state, and the current confidential webhook capability URL. summary: Get a source delete: tags: - Sources operationId: deleteSource parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true security: - bearerAuth: [] responses: "204": description: The source was deleted. "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Permanently deletes the source and its retained events. Its webhook URL stops accepting events. summary: Delete a source /api/sources/{sourceId}/events: get: tags: - Sources operationId: listSourceEvents parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true - name: after in: query schema: type: string pattern: ^(0|[1-9]\d*)$ description: Return events strictly after this canonical, non-negative decimal cursor. The value must fit in a JavaScript safe integer. default: "0" examples: - "42" required: false - name: limit in: query schema: type: integer minimum: 1 maximum: 1000 default: 100 examples: - 100 required: false description: Maximum number of events to return, encoded as canonical decimal digits without leading zeroes. security: - bearerAuth: [] responses: "200": description: A page of retained events and cursor state. content: application/json: schema: $ref: "#/components/schemas/ListSourceEventsResponse" "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "410": description: The requested cursor is older than the retained event boundary. Resume after expiredThrough to read the oldest available events. content: application/json: schema: $ref: "#/components/schemas/CursorExpiredError" "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Returns retained events after a cursor in ascending cursor order. summary: List retained events /api/sources/{sourceId}/events/stream: get: tags: - Sources operationId: streamSourceEvents parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true security: - bearerAuth: [] responses: "101": description: The WebSocket was accepted. Server-to-client text frames conform to the x-dotpipe-websocket-message schema on this operation. "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "426": description: UpgradeRequired headers: upgrade: schema: type: string enum: - websocket description: The required upgrade protocol. required: true content: text/plain: schema: type: string const: Upgrade Required examples: - Upgrade Required "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Upgrades to a WebSocket that sends the current high-water mark after connecting and sends another watermark after each newly retained event commits. Watermarks are monotonic state notifications, not event delivery acknowledgements. Clients must retain the greatest watermark received and use the retained-events endpoint to read events from their durable cursor. summary: Watch the event high-water mark x-dotpipe-websocket-message: $ref: "#/components/schemas/SourceEventsStreamMessage" /api/sources/{sourceId}/events/sse: get: tags: - Sources operationId: streamSourceEventsSse parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true - name: last-event-id in: header schema: type: string pattern: ^(0|[1-9]\d*)$ description: Resume after this cursor. When present, this value takes precedence over the after query parameter. examples: - "42" required: false - name: after in: query schema: type: string pattern: ^(0|[1-9]\d*)$ description: Resume after this canonical, non-negative decimal cursor when Last-Event-ID is absent. default: "0" examples: - "42" required: false security: - bearerAuth: [] responses: "200": description: Success content: text/event-stream: schema: $ref: "#/components/schemas/SourceEventSseMessage" x-effect-stream: encoding: sse causeSchema: type: array items: anyOf: - type: object properties: _tag: type: string enum: - Fail error: not: {} required: - _tag - error additionalProperties: false - type: object properties: _tag: type: string enum: - Die defect: {} required: - _tag - defect additionalProperties: false - type: object properties: _tag: type: string enum: - Interrupt fiberId: anyOf: - type: number - type: "null" required: - _tag - fiberId additionalProperties: false errorSchema: not: {} failureEvent: effect/httpapi/stream/failure "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "410": description: The requested cursor is older than the retained event boundary. Resume after expiredThrough to read the oldest available events. content: application/json: schema: $ref: "#/components/schemas/CursorExpiredError" "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Authenticates once, sends retained events after the resume cursor, and then sends new retained events as their high-water marks arrive. summary: Stream retained events /api/sources/{sourceId}/provider-secret: put: tags: - Sources operationId: replaceSourceProviderSecret parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true security: - bearerAuth: [] responses: "200": description: The provider secret was replaced. content: application/json: schema: $ref: "#/components/schemas/ReplaceProviderSecretResponse" "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "409": description: Generic sources do not have provider secrets. content: application/json: schema: $ref: "#/components/schemas/GenericSourceError" "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Immediately replaces the GitHub webhook secret or Slack signing secret without changing the webhook URL. Update the provider and dotpipe close together. Generic sources do not have provider secrets. summary: Replace a source provider secret requestBody: content: application/json: schema: $ref: "#/components/schemas/ReplaceProviderSecretRequest" required: true /api/sources/{sourceId}/rotate-webhook-url: post: tags: - Sources operationId: rotateSourceWebhookUrl parameters: - name: sourceId in: path schema: $ref: "#/components/schemas/SourceId" required: true security: - bearerAuth: [] responses: "200": description: The replacement confidential webhook capability URL. content: application/json: schema: $ref: "#/components/schemas/RotateWebhookUrlResponse" "400": description: The request path, headers, body, or query parameters are invalid. content: text/plain: schema: type: string const: Bad Request examples: - Bad Request "401": description: InvalidApiKey headers: www-authenticate: schema: type: string enum: - Bearer description: Bearer challenge returned when authentication fails. required: true content: text/plain: schema: type: string const: Unauthorized examples: - Unauthorized "404": description: The source does not exist, is no longer active, or belongs to another workspace. content: text/plain: schema: type: string const: Not Found examples: - Not Found "500": description: An internal error occurred. content: text/plain: schema: type: string const: Internal Server Error examples: - Internal Server Error description: Invalidates the current webhook capability URL and returns a replacement. summary: Rotate a source webhook URL components: schemas: SourceEventsStreamMessage: type: object properties: type: type: string enum: - watermark highWatermark: $ref: "#/components/schemas/Cursor" required: - type - highWatermark additionalProperties: false SourceId: type: string pattern: ^up_[0-9A-HJKMNP-TV-Z]{26}$ examples: - up_01K1B7D5K7Q1Q83K8T1MRBX1S0 SourceName: type: string minLength: 1 maxLength: 100 examples: - GitHub Timestamp: type: string examples: - 2026-08-03T18:30:00.000Z format: date-time SourceProviderSummary: oneOf: - type: object properties: type: type: string enum: - generic required: - type additionalProperties: false - type: object properties: type: type: string enum: - github secretConfigured: type: boolean required: - type - secretConfigured additionalProperties: false - type: object properties: type: type: string enum: - slack secretConfigured: type: boolean required: - type - secretConfigured additionalProperties: false discriminator: propertyName: type SourceSummary: type: object properties: id: $ref: "#/components/schemas/SourceId" name: $ref: "#/components/schemas/SourceName" createdAt: $ref: "#/components/schemas/Timestamp" provider: $ref: "#/components/schemas/SourceProviderSummary" required: - id - name - createdAt - provider additionalProperties: false ListSourcesResponse: type: object properties: sources: type: array items: $ref: "#/components/schemas/SourceSummary" required: - sources additionalProperties: false description: The active sources. SourceNameInput: type: string allOf: - pattern: \S x-dotpipe-normalizedMaxLength: 100 description: Leading and trailing whitespace is removed. The normalized name must contain 1 to 100 characters. examples: - GitHub RetentionSeconds: type: integer minimum: 3600 maximum: 2592000 description: How long accepted events remain available, in seconds. examples: - 86400 CreateGenericSourceProvider: type: object properties: type: type: string enum: - generic required: - type additionalProperties: false CreateGitHubSourceProvider: type: object properties: type: type: string enum: - github webhookSecret: type: string description: The secret must contain 1 to 4096 UTF-8 bytes. examples: - writeOnly: true format: password minLength: 1 allOf: - x-dotpipe-maxBytes: 4096 required: - type additionalProperties: false CreateSlackSourceProvider: type: object properties: type: type: string enum: - slack signingSecret: type: string description: The secret must contain 1 to 4096 UTF-8 bytes. examples: - writeOnly: true format: password minLength: 1 allOf: - x-dotpipe-maxBytes: 4096 required: - type additionalProperties: false CreateSourceProvider: oneOf: - $ref: "#/components/schemas/CreateGenericSourceProvider" - $ref: "#/components/schemas/CreateGitHubSourceProvider" - $ref: "#/components/schemas/CreateSlackSourceProvider" discriminator: propertyName: type mapping: generic: "#/components/schemas/CreateGenericSourceProvider" github: "#/components/schemas/CreateGitHubSourceProvider" slack: "#/components/schemas/CreateSlackSourceProvider" CreateSourceRequest: type: object properties: name: $ref: "#/components/schemas/SourceNameInput" retentionSeconds: $ref: "#/components/schemas/RetentionSeconds" provider: $ref: "#/components/schemas/CreateSourceProvider" required: - name - retentionSeconds - provider additionalProperties: false WebhookUrl: type: string allOf: - x-sensitive: true description: A confidential capability URL for event ingestion. Possession grants permission to submit events; no bearer API key is sent to this URL. examples: - https://app.dotpipe.io/v1/hooks/generic/up_01K1B7D5K7Q1Q83K8T1MRBX1S0/1/eyJhbGciOiJIUzI1NiJ9 format: uri CreatedSource: type: object properties: id: $ref: "#/components/schemas/SourceId" name: $ref: "#/components/schemas/SourceName" createdAt: $ref: "#/components/schemas/Timestamp" provider: $ref: "#/components/schemas/SourceProviderSummary" retentionSeconds: $ref: "#/components/schemas/RetentionSeconds" webhookUrl: $ref: "#/components/schemas/WebhookUrl" required: - id - name - createdAt - provider - retentionSeconds - webhookUrl additionalProperties: false description: The source was created. The response includes its confidential webhook capability URL. SourceLimitReachedError: type: object properties: error: type: string enum: - source_limit_reached required: - error additionalProperties: false NameTakenError: type: object properties: error: type: string enum: - name_taken required: - error additionalProperties: false Cursor: type: string pattern: ^(0|[1-9]\d*)$ description: A canonical decimal cursor encoded as a string to preserve integer precision. examples: - "42" SourceDetails: type: object properties: id: $ref: "#/components/schemas/SourceId" name: $ref: "#/components/schemas/SourceName" createdAt: $ref: "#/components/schemas/Timestamp" provider: $ref: "#/components/schemas/SourceProviderSummary" retentionSeconds: $ref: "#/components/schemas/RetentionSeconds" webhookUrl: $ref: "#/components/schemas/WebhookUrl" highWatermark: $ref: "#/components/schemas/Cursor" expiredThrough: $ref: "#/components/schemas/Cursor" databaseSize: type: integer allOf: - minimum: 0 description: Current Durable Object database size in bytes. format: int64 maxDatabaseSize: type: integer allOf: - const: 10737418240 description: Maximum Durable Object database size in bytes. format: int64 storageWarning: type: boolean description: Whether the database has reached the storage warning threshold. required: - id - name - createdAt - provider - retentionSeconds - webhookUrl - highWatermark - expiredThrough - databaseSize - maxDatabaseSize - storageWarning additionalProperties: false description: The source details. EventId: type: string pattern: ^evt_[0-9A-HJKMNP-TV-Z]{26}$ examples: - evt_01K1B7FW7Z33YZP8MYBQ8F83CA SourceEvent: type: object properties: id: $ref: "#/components/schemas/EventId" cursor: $ref: "#/components/schemas/Cursor" acceptedAt: $ref: "#/components/schemas/Timestamp" contentType: type: string description: The accepted JSON media type. examples: - application/json headers: type: object additionalProperties: type: string description: Retained request headers. Authorization, cookies, Cloudflare, and forwarding headers are removed during ingestion. payload: description: The accepted JSON value. required: - id - cursor - acceptedAt - contentType - headers - payload additionalProperties: false Cursor_1: type: string pattern: ^(0|[1-9]\d*)$ description: Use this value as `after` to request the following page. examples: - "42" ListSourceEventsResponse: type: object properties: events: type: array items: $ref: "#/components/schemas/SourceEvent" nextCursor: $ref: "#/components/schemas/Cursor_1" highWatermark: $ref: "#/components/schemas/Cursor" expiredThrough: $ref: "#/components/schemas/Cursor" hasMore: type: boolean description: Whether another page exists through the reported high watermark. required: - events - nextCursor - highWatermark - expiredThrough - hasMore additionalProperties: false description: A page of retained events and cursor state. CursorExpiredError: type: object properties: error: type: string enum: - cursor_expired expiredThrough: $ref: "#/components/schemas/Cursor" required: - error - expiredThrough additionalProperties: false SourceEventEncoded: type: string contentMediaType: application/json SourceEventSseMessage: type: object properties: id: $ref: "#/components/schemas/Cursor" event: type: string enum: - source-event data: $ref: "#/components/schemas/SourceEventEncoded" required: - id - event - data additionalProperties: false ReplaceProviderSecretRequest: type: object properties: secret: type: string description: The secret must contain 1 to 4096 UTF-8 bytes. examples: - writeOnly: true format: password minLength: 1 allOf: - x-dotpipe-maxBytes: 4096 required: - secret additionalProperties: false ReplaceProviderSecretResponse: type: object properties: secretConfigured: type: boolean enum: - true required: - secretConfigured additionalProperties: false description: The provider secret was replaced. GenericSourceError: type: object properties: error: type: string enum: - generic_source required: - error additionalProperties: false RotateWebhookUrlResponse: type: object properties: webhookUrl: $ref: "#/components/schemas/WebhookUrl" required: - webhookUrl additionalProperties: false description: The replacement confidential webhook capability URL. securitySchemes: bearerAuth: description: "Send an API key as Authorization: Bearer . The bearer scheme is matched case-insensitively. Missing, invalid, unknown, or revoked bearer credentials receive the same 401 response and WWW-Authenticate challenge." type: http scheme: bearer bearerFormat: dotpipe API key security: [] tags: - name: Sources description: Control-plane operations for webhook sources. servers: - url: https://app.dotpipe.io description: Production