Xbow Webhooks API

Manage webhook subscriptions and receive event notifications. When creating an organization, you may provide an HTTPS webhook URL to receive events related to the organization's resources. We implement _best-effort_ delivery of events, soon after they occur. We will not retry delivery if it fails for any reason. ## Webhook Versioning Webhook payloads follow the API version of the subscription. When a version reaches its end-of-life date, webhook subscriptions for that version will stop emitting events. Ensure your integration is updated to a supported version before the EOL date. ## Signature Verification Each request will be a `POST` request sent with the following headers: * `X-Signature-Timestamp`: A Unix timestamp in seconds. * `X-Signature-Ed25519`: An hex string representing an Ed25519 signature of the concatenation of the timestamp and the request body, signed with XBOW's private key. You must verify the signature using the public key from the `GET /api/v1/meta/webhooks-signing-keys` endpoint. You must verify that the timestamp is within a valid range from the current time to prevent replay attacks. An example of a valid range might be +/-5 minutes. You should respond with a 2xx status code if the signature is valid, and a 401 status code otherwise. Before organization creation, we will send two test `ping` events. One signed with XBOW's private key, and one signed with an invalid key. This allows you to verify that your signature verification is working correctly. For example, if you're using Node.js: ```javascript import consumers from "node:stream/consumers"; // Fetch the public key from the API (cache this - it rarely changes) const keysResponse = await fetch("https://console.xbow.com/api/v1/meta/webhooks-signing-keys", { headers: { Authorization: "Bearer your-api-key", "X-XBOW-API-Version": "2026-02-01" } }); const keys = await keysResponse.json(); const publicKeyBase64 = keys[0].publicKey; // Import the public key (SPKI format, base64-encoded) const publicKey = await crypto.subtle.importKey( "spki", Buffer.from(publicKeyBase64, "base64"), { name: "Ed25519" }, false, ["verify"], ); const timestamp = req.headers["x-signature-timestamp"]; const timestampTime = parseInt(timestamp, 10); const now = Math.floor(Date.now() / 1000); const isValidTimestamp = (Math.abs(now - timestampTime) 2026-04-01. Skip "next". const BASE = "https://console.xbow.com"; const ORG_ID = "your-organization-id"; const API_KEY = "your-api-key"; const OLD = "2026-02-01"; const NEW = "2026-04-01"; const headers = { Authorization: `Bearer ${API_KEY}`, "X-XBOW-API-Version": NEW }; async function* paginate(url: string): AsyncGenerator { let cursor: string | null = null; do { const u = new URL(url); if (cursor) u.searchParams.set("cursor", cursor); const res = await fetch(u, { headers }); if (!res.ok) throw new Error(`${res.status} ${await res.text()}`); const page = (await res.json()) as { items: T[]; nextCursor: string | null }; yield* page.items; cursor = page.nextCursor; } while (cursor); } type Sub = { id: string; apiVersion: string }; for await (const wh of paginate(`${BASE}/api/v1/organizations/${ORG_ID}/webhooks`)) { if (wh.apiVersion === "next") { console.log(`skip ${wh.id} (next)`); continue; } if (wh.apiVersion !== OLD) { console.log(`skip ${wh.id} (${wh.apiVersion})`); continue; } const res = await fetch(`${BASE}/api/v1/webhooks/${wh.id}`, { method: "PATCH", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify({ apiVersion: NEW }), }); if (!res.ok) throw new Error(`${res.status} ${await res.text()}`); console.log(`bump ${wh.id} ${OLD} -> ${NEW}`); } ``` An `apiVersion`-only `PATCH` does not re-validate your endpoint, so the upgrade is cheap and safe to run for many subscriptions at once. A `PATCH` that changes `targetUrl` does re-send the validation pings described above, and must receive a 2xx for the valid ping to succeed.

OpenAPI Specification

xbow-webhooks-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  description: "\n# Versioning\n\nThe API is in public preview. This is a stable version that exposes the most common functionality of the platform. If your use case is not covered, tell us so that we can prioritize work for future releases.\n\nAll API endpoints require the `X-XBOW-API-Version` header to be set to a supported version. Requests without a version header will be rejected with a `400 Bad Request` response.\n\n## Version Lifecycle\n\nAPI versions follow a `YYYY-MM-DD` naming convention (for example, `2026-04-01`). During the public preview, each version is supported, without breaking changes, for a minimum of 4 months from its release date. The support window for new versions will increase as the API matures.\n\n| Version    | Release Date | End of Life |\n|------------|--------------|-------------|\n| next       | Rolling      | N/A         |\n| 2026-07-01 | 2026-07-01   | 2026-11-01  |\n| 2026-06-01 | 2026-06-01   | 2026-10-01  |\n| 2026-04-01 | 2026-04-01   | 2026-07-01  |\n\n## The \"next\" Version\n\nThe `next` version provides early access to upcoming API changes. Use it in non-production environments to test and prepare for the next stable release.\n\n- Changes are pushed to `next` as they stabilize\n- `next` becomes the next stable version upon release\n- Breaking changes may occur in `next` before a stable release\n\n## End of Life (EOL)\n\nWhen a version reaches its end-of-life date:\n\n- **API requests** to that version will fail with a `400 Bad Request` response\n- **Webhook subscriptions** for that version will stop emitting events\n\nMigrate to a supported version before the EOL date to avoid service disruption. Also update webhooks to a supported version.\n\n## Changes from 2026-06-01 to 2026-07-01\n\n### Finding workflow metadata\n\nFindings now carry customer-controlled workflow metadata, independent of the XBOW-owned lifecycle fields (state, severity, CVSS):\n\n- `externalWorkflowState`: your own tracking state for the finding.\n- `externalTicketReference`: a reference to an external ticket. May only be present alongside an `externalWorkflowState`.\n\nA new endpoint updates these fields:\n\n- `PATCH /api/v1/findings/:findingId` — Update a finding's `externalWorkflowState` and `externalTicketReference`. Omitted fields are left unchanged; send `null` to clear a field.\n\nThese fields also appear in `GET /api/v1/findings/{findingId}`, `GET /api/v1/assets/{assetId}/findings`, and `finding.changed` webhook payloads for subscriptions pinned to `2026-07-01`.\n\n# Accessing the API\n\nThe API is available at `https://console.xbow.com/api/v1/`. All endpoints require authentication via an API key provided in the `Authorization: Bearer <token>` header.\n\n**Note:** For Lightspeed organizations, the API is available in read-only mode. That is, only `GET` endpoints are available.\n\n## Generate a personal access token (PAT)\n\n1. Log into your XBOW dashboard at https://console.xbow.com with administrator access to the organization you want to generate an API key for.\n1. Click your profile icon in the top right corner and select **Settings**.\n1. In the left sidebar, click **Personal Access Tokens**.\n1. Click **Generate new token**.\n1. Provide a name and select the scope for the token, that is, the organization you want to use it with.\n1. Click **Create**.\n1. Copy and securely store your key (it won't be shown again).\n\nStore API keys securely using environment variables or secret managers. Never commit keys to version control. Rotate keys periodically and revoke compromised keys immediately.\n\n## API request headers\n\nAll API requests require two headers: your API key for authentication and the API version you want to use. For example:\n\n```curl\ncurl -X GET \"https://console.xbow.com/api/v1/assets/{assetId}/findings\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"X-XBOW-API-Version: 2026-07-01\" \\\n  -H \"Content-Type: application/json\"\n```\n\n## Error responses\n\nIn addition to the responses described with each endpoint, the API may also return the following responses:\n\n- `400 Bad Request`: the request was malformed or contained invalid parameters, including missing version header.\n- `401 Unauthorized`: missing an API key or the provided API key is invalid.\n- `403 Forbidden`: the API key is valid, but the user does not have permission to access the requested resource.\n- `429 Too Many Requests`: exceeded rate limit, try again with exponential backoff.\n- `500 Internal Server Error`: an unexpected error occurred, try again with exponential backoff.\n\nThe error response body will be in the following format:\n\n```json\n{\n  \"code\": \"ERR_ERROR_TYPE\",\n  \"error\": \"Error Type\",\n  \"message\": \"Detailed error message\"\n}\n```\n\n# Pagination & Rate Limiting\n\n## Pagination\n\nList endpoints use cursor-based pagination. Use the `limit` query parameter to control page size (1-100, default 20) and the `after` parameter to fetch subsequent pages using the cursor from a previous response.\n\nResponses include an `items` array and a `nextCursor` field:\n\n```json\n{\n  \"items\": [...],\n  \"nextCursor\": \"eyJpZCI6IjEyMyJ9\"\n}\n```\n\nTo fetch the next page, pass the `nextCursor` value as the `after` parameter in your next request. When `nextCursor` is `null`, there are no more results.\n\n## Rate Limiting\n\nAPI requests are subject to rate limiting. If you receive a `429 Too Many Requests` response, implement exponential backoff before retrying.\n\n"
  title: XBOW Assessments Webhooks API
  version: '2026-07-01'
servers:
- description: Default
  url: https://console.xbow.com/
- description: Multi SAAS - Europe data resident instance
  url: https://console.eu.xbow.com/
- description: Multi SAAS - Asia Pacific data resident instance
  url: https://console.sg.xbow.com/
tags:
- description: "Manage webhook subscriptions and receive event notifications.\n\nWhen creating an organization, you may provide an HTTPS webhook URL to receive events related to the organization's resources.\n\nWe implement _best-effort_ delivery of events, soon after they occur. We will not retry delivery if it fails for any reason.\n\n## Webhook Versioning\n\nWebhook payloads follow the API version of the subscription. When a version reaches its end-of-life date, webhook subscriptions for that version will stop emitting events. Ensure your integration is updated to a supported version before the EOL date.\n\n## Signature Verification\n\nEach request will be a `POST` request sent with the following headers:\n* `X-Signature-Timestamp`: A Unix timestamp in seconds.\n* `X-Signature-Ed25519`: An hex string representing an Ed25519 signature of the concatenation of the timestamp and the request body, signed with XBOW's private key.\n\nYou must verify the signature using the public key from the `GET /api/v1/meta/webhooks-signing-keys` endpoint.\nYou must verify that the timestamp is within a valid range from the current time to prevent replay attacks. An example of a valid range might be +/-5 minutes.\nYou should respond with a 2xx status code if the signature is valid, and a 401 status code otherwise.\nBefore organization creation, we will send two test `ping` events. One signed with XBOW's private key, and one signed with an invalid key. This allows you to verify that your signature verification is working correctly.\n\nFor example, if you're using Node.js:\n\n```javascript\nimport consumers from \"node:stream/consumers\";\n\n// Fetch the public key from the API (cache this - it rarely changes)\nconst keysResponse = await fetch(\"https://console.xbow.com/api/v1/meta/webhooks-signing-keys\", {\n  headers: { Authorization: \"Bearer your-api-key\", \"X-XBOW-API-Version\": \"2026-02-01\" }\n});\nconst keys = await keysResponse.json();\nconst publicKeyBase64 = keys[0].publicKey;\n\n// Import the public key (SPKI format, base64-encoded)\nconst publicKey = await crypto.subtle.importKey(\n  \"spki\",\n  Buffer.from(publicKeyBase64, \"base64\"),\n  { name: \"Ed25519\" },\n  false,\n  [\"verify\"],\n);\n\nconst timestamp = req.headers[\"x-signature-timestamp\"];\nconst timestampTime = parseInt(timestamp, 10);\nconst now = Math.floor(Date.now() / 1000);\nconst isValidTimestamp = (Math.abs(now - timestampTime) < 300);\n\nif (!isValidTimestamp) {\n  throw new Error(\"Invalid timestamp\");\n}\n\nconst signature = req.headers[\"x-signature-ed25519\"];\nconst body = await consumers.text(req.body);\nconst isVerified = await crypto.subtle.verify(\n  { name: \"Ed25519\" },\n  publicKey,\n  Buffer.from(signature, \"hex\"),\n  Buffer.from(timestamp + body),\n);\n\nif (!isVerified) {\n  throw new Error(\"Invalid request signature\");\n}\n```\n\n## Upgrading webhook subscriptions\n\nEach subscription is pinned to an API version. When we release a new version, you should plan to migrate your subscriptions to it. Once a version reaches its end-of-life date we stop emitting events for subscriptions on that version, so an unmigrated subscription will silently stop receiving deliveries.\n\nUpgrading is a single `PATCH` per subscription. The snippet below lists every subscription on your organization, bumps any pinned to a given older version to a specified newer one, and skips subscriptions on `next` (which track the latest stable version automatically). It uses cursor pagination so it works for organizations with any number of subscriptions.\n\n```typescript\n// Upgrade webhook subscriptions from 2026-02-01 -> 2026-04-01. Skip \"next\".\nconst BASE = \"https://console.xbow.com\";\nconst ORG_ID = \"your-organization-id\";\nconst API_KEY = \"your-api-key\";\nconst OLD = \"2026-02-01\";\nconst NEW = \"2026-04-01\";\n\nconst headers = { Authorization: `Bearer ${API_KEY}`, \"X-XBOW-API-Version\": NEW };\n\nasync function* paginate<T>(url: string): AsyncGenerator<T> {\n  let cursor: string | null = null;\n  do {\n    const u = new URL(url);\n    if (cursor) u.searchParams.set(\"cursor\", cursor);\n    const res = await fetch(u, { headers });\n    if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);\n    const page = (await res.json()) as { items: T[]; nextCursor: string | null };\n    yield* page.items;\n    cursor = page.nextCursor;\n  } while (cursor);\n}\n\ntype Sub = { id: string; apiVersion: string };\nfor await (const wh of paginate<Sub>(`${BASE}/api/v1/organizations/${ORG_ID}/webhooks`)) {\n  if (wh.apiVersion === \"next\") { console.log(`skip   ${wh.id} (next)`); continue; }\n  if (wh.apiVersion !== OLD)    { console.log(`skip   ${wh.id} (${wh.apiVersion})`); continue; }\n  const res = await fetch(`${BASE}/api/v1/webhooks/${wh.id}`, {\n    method: \"PATCH\",\n    headers: { ...headers, \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({ apiVersion: NEW }),\n  });\n  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);\n  console.log(`bump   ${wh.id} ${OLD} -> ${NEW}`);\n}\n```\n\nAn `apiVersion`-only `PATCH` does not re-validate your endpoint, so the upgrade is cheap and safe to run for many subscriptions at once. A `PATCH` that changes `targetUrl` does re-send the validation pings described above, and must receive a 2xx for the valid ping to succeed.\n"
  name: Webhooks
paths:
  /api/v1/organizations/{organizationId}/webhooks:
    get:
      description: 'Lists all webhook subscriptions for an organization.


        Supports pagination via `limit` and `after` query parameters.


        Requires an _organization_ API key.'
      parameters:
      - in: query
        name: limit
        required: false
        schema:
          default: 20
          maximum: 100
          minimum: 1
          type: integer
      - in: query
        name: after
        required: false
        schema:
          type: string
      - in: path
        name: organizationId
        required: true
        schema:
          type: string
      - description: API version to use for this request
        in: header
        name: X-XBOW-API-Version
        required: true
        schema:
          enum:
          - '2026-07-01'
          example: '2026-07-01'
          type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                example:
                  items:
                  - apiVersion: next
                    createdAt: '2025-01-01T00:00:00Z'
                    events:
                    - asset.changed
                    - assessment.changed
                    id: 123e4567-e89b-12d3-a456-426614174000
                    targetUrl: https://example.com/webhook
                    updatedAt: '2025-01-01T00:00:00Z'
                  nextCursor: eyJjcmVhdGVkQXQiOiIyMDI1LTAxLTAxVDAwOjAwOjAwWiIsImlkIjoiMTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDAwIn0=
                properties:
                  items:
                    items:
                      properties:
                        apiVersion:
                          enum:
                          - '2026-02-01'
                          - '2026-04-01'
                          - '2026-06-01'
                          - '2026-07-01'
                          - '2026-08-01'
                          - next
                          type: string
                        createdAt:
                          format: date-time
                          type: string
                        events:
                          items:
                            anyOf:
                            - enum:
                              - ping
                              type: string
                            - enum:
                              - target.changed
                              type: string
                            - enum:
                              - asset.changed
                              type: string
                            - enum:
                              - assessment.changed
                              type: string
                            - enum:
                              - finding.changed
                              type: string
                            - enum:
                              - challenge.changed
                              type: string
                            - enum:
                              - '*'
                              type: string
                          minItems: 1
                          type: array
                        id:
                          type: string
                        targetUrl:
                          format: uri
                          type: string
                        updatedAt:
                          format: date-time
                          type: string
                      required:
                      - apiVersion
                      - createdAt
                      - events
                      - id
                      - targetUrl
                      - updatedAt
                      type: object
                    type: array
                  nextCursor:
                    type: string
                required:
                - items
                type: object
          description: Default Response
        '400':
          content:
            application/json:
              schema:
                properties:
                  code:
                    description: A constant for machines
                    enum:
                    - FST_ERR_VALIDATION
                    type: string
                  error:
                    description: A human readable string for the constant
                    enum:
                    - Bad Request
                    type: string
                  message:
                    description: A human readable message
                    type: string
                  requestId:
                    description: A unique identifier for the request
                    type: string
                required:
                - code
                - error
                - message
                - requestId
                type: object
          description: Default Response
      security:
      - Authorization: []
      summary: List webhook subscriptions
      tags:
      - Webhooks
    post:
      description: 'Creates a new webhook subscription for an organization. Upon completion XBOW will deliver 2 `ping` events, one with a valid and one with an invalid signature.


        Requires an _organization_ API key.'
      parameters:
      - in: path
        name: organizationId
        required: true
        schema:
          type: string
      - description: API version to use for this request
        in: header
        name: X-XBOW-API-Version
        required: true
        schema:
          enum:
          - '2026-07-01'
          example: '2026-07-01'
          type: string
      requestBody:
        content:
          application/json:
            schema:
              example:
                apiVersion: next
                events:
                - asset.changed
                - assessment.changed
                targetUrl: https://example.com/webhook
              properties:
                apiVersion:
                  enum:
                  - '2026-04-01'
                  - '2026-06-01'
                  - '2026-07-01'
                  - next
                  type: string
                events:
                  items:
                    anyOf:
                    - enum:
                      - ping
                      type: string
                    - enum:
                      - asset.changed
                      type: string
                    - enum:
                      - assessment.changed
                      type: string
                    - enum:
                      - finding.changed
                      type: string
                    - enum:
                      - challenge.changed
                      type: string
                    - enum:
                      - '*'
                      type: string
                  minItems: 1
                  type: array
                targetUrl:
                  format: uri
                  type: string
              required:
              - apiVersion
              - events
              - targetUrl
              type: object
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                example:
                  apiVersion: next
                  createdAt: '2025-01-01T00:00:00Z'
                  events:
                  - asset.changed
                  - assessment.changed
                  id: 123e4567-e89b-12d3-a456-426614174000
                  targetUrl: https://example.com/webhook
                  updatedAt: '2025-01-01T00:00:00Z'
                properties:
                  apiVersion:
                    enum:
                    - '2026-02-01'
                    - '2026-04-01'
                    - '2026-06-01'
                    - '2026-07-01'
                    - '2026-08-01'
                    - next
                    type: string
                  createdAt:
                    format: date-time
                    type: string
                  events:
                    items:
                      anyOf:
                      - enum:
                        - ping
                        type: string
                      - enum:
                        - target.changed
                        type: string
                      - enum:
                        - asset.changed
                        type: string
                      - enum:
                        - assessment.changed
                        type: string
                      - enum:
                        - finding.changed
                        type: string
                      - enum:
                        - challenge.changed
                        type: string
                      - enum:
                        - '*'
                        type: string
                    minItems: 1
                    type: array
                  id:
                    type: string
                  targetUrl:
                    format: uri
                    type: string
                  updatedAt:
                    format: date-time
                    type: string
                required:
                - apiVersion
                - createdAt
                - events
                - id
                - targetUrl
                - updatedAt
                type: object
          description: Default Response
        '400':
          content:
            application/json:
              schema:
                properties:
                  code:
                    description: A constant for machines
                    enum:
                    - FST_ERR_VALIDATION
                    type: string
                  error:
                    description: A human readable string for the constant
                    enum:
                    - Bad Request
                    type: string
                  message:
                    description: A human readable message
                    type: string
                  requestId:
                    description: A unique identifier for the request
                    type: string
                required:
                - code
                - error
                - message
                - requestId
                type: object
          description: Default Response
      security:
      - Authorization: []
      summary: Create webhook subscription
      tags:
      - Webhooks
  /api/v1/webhooks/{webhookId}:
    delete:
      description: 'Deletes a webhook subscription.


        Requires an _organization_ API key.'
      parameters:
      - in: path
        name: webhookId
        required: true
        schema:
          type: string
      - description: API version to use for this request
        in: header
        name: X-XBOW-API-Version
        required: true
        schema:
          enum:
          - '2026-07-01'
          example: '2026-07-01'
          type: string
      responses:
        '204':
          description: Default Response
        '400':
          content:
            application/json:
              schema:
                properties:
                  code:
                    description: A constant for machines
                    enum:
                    - FST_ERR_VALIDATION
                    type: string
                  error:
                    description: A human readable string for the constant
                    enum:
                    - Bad Request
                    type: string
                  message:
                    description: A human readable message
                    type: string
                  requestId:
                    description: A unique identifier for the request
                    type: string
                required:
                - code
                - error
                - message
                - requestId
                type: object
          description: Default Response
        '404':
          content:
            application/json:
              schema:
                properties:
                  code:
                    description: A constant for machines
                    enum:
                    - ERR_NOT_FOUND
                    type: string
                  error:
                    description: A human readable string for the constant
                    enum:
                    - Not Found
                    type: string
                  message:
                    description: A human readable message
                    type: string
                  requestId:
                    description: A unique identifier for the request
                    type: string
                required:
                - code
                - error
                - message
                - requestId
                type: object
          description: The requested resource was not found
      security:
      - Authorization: []
      summary: Delete webhook subscription
      tags:
      - Webhooks
    get:
      description: 'Gets a specific webhook subscription by ID.


        Requires an _organization_ API key.'
      parameters:
      - in: path
        name: webhookId
        required: true
        schema:
          type: string
      - description: API version to use for this request
        in: header
        name: X-XBOW-API-Version
        required: true
        schema:
          enum:
          - '2026-07-01'
          example: '2026-07-01'
          type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                example:
                  apiVersion: next
                  createdAt: '2025-01-01T00:00:00Z'
                  events:
                  - asset.changed
                  - assessment.changed
                  id: 123e4567-e89b-12d3-a456-426614174000
                  targetUrl: https://example.com/webhook
                  updatedAt: '2025-01-01T00:00:00Z'
                properties:
                  apiVersion:
                    enum:
                    - '2026-02-01'
                    - '2026-04-01'
                    - '2026-06-01'
                    - '2026-07-01'
                    - '2026-08-01'
                    - next
                    type: string
                  createdAt:
                    format: date-time
                    type: string
                  events:
                    items:
                      anyOf:
                      - enum:
                        - ping
                        type: string
                      - enum:
                        - target.changed
                        type: string
                      - enum:
                        - asset.changed
                        type: string
                      - enum:
                        - assessment.changed
                        type: string
                      - enum:
                        - finding.changed
                        type: string
                      - enum:
                        - challenge.changed
                        type: string
                      - enum:
                        - '*'
                        type: string
                    minItems: 1
                    type: array
                  id:
                    type: string
                  targetUrl:
                    format: uri
                    type: string
                  updatedAt:
                    format: date-time
                    type: string
                required:
                - apiVersion
                - createdAt
                - events
                - id
                - targetUrl
                - updatedAt
                type: object
          description: Default Response
        '400':
          content:
            application/json:
              schema:
                properties:
                  code:
                    description: A constant for machines
                    enum:
                    - FST_ERR_VALIDATION
                    type: string
                  error:
                    description: A human readable string for the constant
                    enum:
                    - Bad Request
                    type: string
                  message:
                    description: A human readable message
                    type: string
                  requestId:
                    description: A unique identifier for the request
                    type: string
                required:
                - code
                - error
                - message
                - requestId
                type: object
          description: Default Response
        '404':
          content:
            application/json:
              schema:
                properties:
                  code:
                    description: A constant for machines
                    enum:
                    - ERR_NOT_FOUND
                    type: string
                  error:
                    description: A human readable string for the constant
                    enum:
                    - Not Found
                    type: string
                  message:
                    description: A human readable message
                    type: string
                  requestId:
                    description: A unique identifier for the request
                    type: string
                required:
                - code
                - error
                - message
                - requestId
                type: object
          description: The requested resource was not found
      security:
      - Authorization: []
      summary: Get webhook subscription
      tags:
      - Webhooks
    patch:
      description: 'Updates an existing webhook subscription.


        Requires an _organization_ API key.'
      parameters:
      - in: path
        name: webhookId
        required: true
        schema:
          type: string
      - description: API version to use for this request
        in: header
        name: X-XBOW-API-Version
        required: true
        schema:
          enum:
          - '2026-07-01'
          example: '2026-07-01'
          type: string
      requestBody:
        content:
          application/json:
            schema:
              example:
                targetUrl: https://example.com/new-webhook
              properties:
                apiVersion:
                  enum:
                  - '2026-04-01'
                  - '2026-06-01'
                  - '2026-07-01'
                  - next
                  type: string
                events:
                  items:
                    anyOf:
                    - enum:
                      - ping
                      type: string
                    - enum:
                      - asset.changed
                      type: string
                    - enum:
                      - assessment.changed
                      type: string
                    - enum:
                      - finding.changed
                      type: string
                    - enum:
                      - challenge.changed
                      type: string
                    - enum:
                      - '*'
                      type: string
                  minItems: 1
                  type: array
                targetUrl:
                  format: uri
                  type: string
              type: object
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                example:
                  apiVersion: next
                  createdAt: '2025-01-01T00:00:00Z'
                  events:
                  - asset.changed
                  - assessment.changed
                  id: 123e4567-e89b-12d3-a456-426614174000
                  targetUrl: https://example.com/webhook
                  updatedAt: '2025-01-01T00:00:00Z'
                properties:
                  apiVersion:
                    enum:
                    - '2026-02-01'
                    - '2026-04-01'
                    - '2026-06-01'
                    - '2026-07-01'
                    - '2026-08-01'
                    - next
                    type: string
                  createdAt:
                    format: date-time
                    type: string
                  events:
                    items:
                      anyOf:
                      - enum:
                        - ping
                        type: string
                      - enum:
                        - target.changed
                        type: string
                      - enum:
                        - asset.changed
                        type: string
                      - enum:
                        - assessment.changed
                        type: string
                      - enum:
                        - finding.changed
                        type: string
                      - enum:
                        - challenge.changed
                        type: string
                      - enum:
                        - '*'
                        type: string
                    minItems: 1
                    type: array
                  id:
                    type: string
                  targetUrl:
                    format: uri
                    type: string
                  updatedAt:
                    format

# --- truncated at 32 KB (44 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/xbow/refs/heads/main/openapi/xbow-webhooks-api-openapi.yml