> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runpulse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Webhook

> Add a webhook. Your organization can have up to 10. Pulse pings the new webhook at once, and the response says whether the ping got through. This is the only response that returns the signing `secret`. Jobs created 15 seconds or more after this call send each listed event, signed per Standard Webhooks and carrying only the job's id. A newer status replaces one not yet delivered. Failed deliveries are retried for about 35 hours, and a webhook that keeps failing is turned off.



## OpenAPI

````yaml /api-reference/v2/openapi.yml post /webhook
openapi: 3.1.0
info:
  title: Pulse API
  description: >-
    Agentic document infrastructure for the enterprise. The Pulse API turns
    complex documents into AI-ready data, such as Markdown, structured JSON and
    bounding boxes.
  version: '2'
servers:
  - url: https://api.runpulse.com
    description: Default Pulse API base URL
security: []
tags:
  - name: Parse
    description: Parse a document's text, tables and figures.
  - name: Batch parse
    description: Parse many documents with one config.
  - name: Extract
    description: Extract structured data from a parsed document.
  - name: Split
    description: Find each topic's pages in a parsed document.
  - name: Tables
    description: Merge a parsed document's tables across pages.
  - name: Charts
    description: Read the charts in a parsed document.
  - name: Classify
    description: Sort a document into the categories you define.
  - name: Pipeline
    description: Run a parse and its follow-on steps as one job.
  - name: Usage
    description: Check the pages and credits your organization has used.
  - name: Webhook
    description: Get notified when your organization's jobs change status.
  - name: Organization settings
    description: Read and change your organization's name, address and default API version.
paths:
  /webhook:
    post:
      tags:
        - Webhook
      summary: Create Webhook
      description: >-
        Add a webhook. Your organization can have up to 10. Pulse pings the new
        webhook at once, and the response says whether the ping got through.
        This is the only response that returns the signing `secret`. Jobs
        created 15 seconds or more after this call send each listed event,
        signed per Standard Webhooks and carrying only the job's id. A newer
        status replaces one not yet delivered. Failed deliveries are retried for
        about 35 hours, and a webhook that keeps failing is turned off.
      operationId: createWebhook
      parameters:
        - name: Pulse-Version
          in: header
          required: false
          schema:
            type: string
            default: '2'
            title: Pulse-Version
          examples:
            default:
              value: '2'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              additionalProperties: false
              description: A new webhook for your organization.
              properties:
                url:
                  description: >-
                    The URL Pulse sends events to: a public `https` URL on port
                    443, at most 2,048 characters, with no credentials in it.
                    You can't change it later.
                  minLength: 1
                  title: Url
                  type: string
                events:
                  description: >-
                    The events to send, each named `<job type>.<status>`, such
                    as `extract.completed`. Defaults to none.
                  items:
                    type: string
                    enum:
                      - parse.queued
                      - parse.processing
                      - parse.completed
                      - parse.failed
                      - parse.canceled
                      - extract.queued
                      - extract.processing
                      - extract.completed
                      - extract.failed
                      - extract.canceled
                      - split.queued
                      - split.processing
                      - split.completed
                      - split.failed
                      - split.canceled
                      - classify.queued
                      - classify.processing
                      - classify.completed
                      - classify.failed
                      - classify.canceled
                      - tables.queued
                      - tables.processing
                      - tables.completed
                      - tables.failed
                      - tables.canceled
                      - charts.queued
                      - charts.processing
                      - charts.completed
                      - charts.failed
                      - charts.canceled
                      - pipeline.queued
                      - pipeline.processing
                      - pipeline.completed
                      - pipeline.failed
                      - pipeline.canceled
                  title: Events
                  type: array
                description:
                  description: A note for your own reference.
                  maxLength: 500
                  minLength: 1
                  title: Description
                  type: string
                headers:
                  additionalProperties:
                    type: string
                  description: >-
                    Static headers to send with every delivery, such as a token
                    your gateway checks. You can set up to 5, but not Pulse's
                    own, such as `Content-Type` or `webhook-*`. Values are
                    encrypted and never returned.
                  propertyNames:
                    minLength: 1
                  title: Headers
                  type: object
                secret:
                  description: >-
                    The signing secret, as `whsec_` followed by the base64 of 24
                    to 64 random bytes. If omitted, Pulse generates one. Only
                    the create response returns it.
                  title: Secret
                  type: string
              required:
                - url
              title: WebhookRequest
              type: object
      responses:
        '201':
          description: The new webhook, its secret, and how its first ping went.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookPostResponse'
        '400':
          description: >-
            The request is invalid
            ([`REQUEST_INVALID`](https://docs.runpulse.com/errors/request-invalid)):
            the body isn't a JSON object, a field breaks its rules, or a query
            parameter isn't one this endpoint takes. `errors` names the field.
            `Pulse-Version` names a version this API doesn't serve
            ([`UNSUPPORTED_VERSION`](https://docs.runpulse.com/errors/unsupported-version)).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
          x-pulse-errors:
            - REQUEST_INVALID
            - UNSUPPORTED_VERSION
        '401':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: >-
            No valid credentials
            ([`CREDENTIALS_INVALID`](https://docs.runpulse.com/errors/credentials-invalid)),
            or an inactive API key
            ([`API_KEY_INACTIVE`](https://docs.runpulse.com/errors/api-key-inactive)).
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
          x-pulse-errors:
            - CREDENTIALS_INVALID
            - API_KEY_INACTIVE
        '403':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: >-
            Your account is suspended
            ([`ACCOUNT_SUSPENDED`](https://docs.runpulse.com/errors/account-suspended)).
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
          x-pulse-errors:
            - ACCOUNT_SUSPENDED
        '404':
          description: >-
            No endpoint answers this path
            ([`ROUTE_NOT_FOUND`](https://docs.runpulse.com/errors/route-not-found)).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
          x-pulse-errors:
            - ROUTE_NOT_FOUND
        '422':
          description: >-
            Your organization already has 10 webhooks
            ([`WEBHOOK_LIMIT_REACHED`](https://docs.runpulse.com/errors/webhook-limit-reached)).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
          x-pulse-errors:
            - WEBHOOK_LIMIT_REACHED
        '429':
          description: >-
            Your organization has created 20 webhooks this hour, the most it can
            ([`RATE_LIMIT_EXCEEDED`](https://docs.runpulse.com/errors/rate-limit-exceeded)).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: string
          x-pulse-errors:
            - RATE_LIMIT_EXCEEDED
        '500':
          description: >-
            An unexpected error on Pulse's side
            ([`SERVER_ERROR`](https://docs.runpulse.com/errors/server-error));
            retry.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
          x-pulse-errors:
            - SERVER_ERROR
        '503':
          description: >-
            Pulse couldn't complete the request just now
            ([`SERVICE_UNAVAILABLE`](https://docs.runpulse.com/errors/service-unavailable));
            try again shortly. On a self-hosted install that hasn't been
            activated yet,
            [`LICENSE_NOT_ACTIVATED`](https://docs.runpulse.com/errors/license-not-activated).
            On a self-hosted install whose license is invalid or expired,
            [`LICENSE_INVALID`](https://docs.runpulse.com/errors/license-invalid).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
          headers:
            X-Request-Id:
              description: The request's id; the problem's `request_id`.
              schema:
                type: string
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: string
          x-pulse-errors:
            - SERVICE_UNAVAILABLE
            - LICENSE_NOT_ACTIVATED
            - LICENSE_INVALID
      security:
        - ApiKey: []
components:
  schemas:
    WebhookPostResponse:
      properties:
        webhook_id:
          type: string
          title: Webhook Id
          description: The webhook's id, `webhook-<uuid>`.
        url:
          type: string
          title: Url
          description: The URL Pulse sends this webhook's events to.
        events:
          items:
            type: string
            enum:
              - parse.queued
              - parse.processing
              - parse.completed
              - parse.failed
              - parse.canceled
              - extract.queued
              - extract.processing
              - extract.completed
              - extract.failed
              - extract.canceled
              - split.queued
              - split.processing
              - split.completed
              - split.failed
              - split.canceled
              - classify.queued
              - classify.processing
              - classify.completed
              - classify.failed
              - classify.canceled
              - tables.queued
              - tables.processing
              - tables.completed
              - tables.failed
              - tables.canceled
              - charts.queued
              - charts.processing
              - charts.completed
              - charts.failed
              - charts.canceled
              - pipeline.queued
              - pipeline.processing
              - pipeline.completed
              - pipeline.failed
              - pipeline.canceled
          type: array
          title: Events
          description: The events this webhook receives. An empty list means none.
        events_from:
          additionalProperties:
            type: string
          propertyNames:
            enum:
              - parse.queued
              - parse.processing
              - parse.completed
              - parse.failed
              - parse.canceled
              - extract.queued
              - extract.processing
              - extract.completed
              - extract.failed
              - extract.canceled
              - split.queued
              - split.processing
              - split.completed
              - split.failed
              - split.canceled
              - classify.queued
              - classify.processing
              - classify.completed
              - classify.failed
              - classify.canceled
              - tables.queued
              - tables.processing
              - tables.completed
              - tables.failed
              - tables.canceled
              - charts.queued
              - charts.processing
              - charts.completed
              - charts.failed
              - charts.canceled
              - pipeline.queued
              - pipeline.processing
              - pipeline.completed
              - pipeline.failed
              - pipeline.canceled
          type: object
          title: Events From
          description: >-
            For each event, the time it takes effect. The event is sent only for
            jobs created after that time.
        enabled:
          type: boolean
          title: Enabled
          description: >-
            Whether Pulse sends events to this webhook. It's `false` when you or
            Pulse turned the webhook off.
        disabled_reason:
          anyOf:
            - type: string
              enum:
                - delivery_failures
                - gone
            - type: 'null'
          title: Disabled Reason
          description: >-
            Why Pulse turned the webhook off: `delivery_failures` (10 events in
            a row undelivered, or 3 days of failed deliveries) or `gone` (your
            endpoint returned `410`). It's `null` while on, or if you turned it
            off.
        header_names:
          items:
            type: string
          type: array
          title: Header Names
          description: >-
            The names of the webhook's static headers. Their values are never
            returned.
        created_at:
          type: string
          title: Created At
          description: When the webhook was created.
        secret:
          type: string
          title: Secret
          description: >-
            The secret Pulse signs this webhook's deliveries with, starting
            `whsec_`. Store it now, because Pulse returns it only once.
        ping:
          $ref: '#/components/schemas/WebhookPingResponse'
          description: >-
            How the first `webhook.ping` went. It waits only 5 seconds, so a
            `timeout` may mean your endpoint was starting up. Test again with
            `POST /webhook/{webhook_id}/ping`, which waits 15 seconds.
      additionalProperties: false
      type: object
      required:
        - webhook_id
        - url
        - events
        - events_from
        - enabled
        - disabled_reason
        - header_names
        - created_at
        - secret
        - ping
      title: WebhookPostResponse
      description: The new webhook, its secret, and how its first ping went.
    Problem:
      additionalProperties: false
      description: >-
        Why the request or the job failed. Branch on `code`; quote `request_id`
        to support.
      properties:
        type:
          description: 'This code''s page: what it means and what to do.'
          title: Type
          type: string
        title:
          description: A short summary of the code, the same for every occurrence.
          title: Title
          type: string
        status:
          description: The HTTP status the code answers with.
          title: Status
          type: integer
        detail:
          description: What happened this time.
          title: Detail
          type: string
        instance:
          description: 'This occurrence: the request''s URN, `urn:pulse:request:<id>`.'
          title: Instance
          type: string
        code:
          description: The stable error code, e.g. `REQUEST_INVALID`. Branch on it.
          title: Code
          type: string
        request_id:
          description: >-
            The request that failed, as `X-Request-Id` named it; for a failed
            job, the request that created it. Quote it to support.
          title: Request Id
          type: string
        retryable:
          description: Whether the same request may succeed if sent again.
          title: Retryable
          type: boolean
        retry_after:
          description: Seconds to wait before retrying, as `Retry-After` says.
          title: Retry After
          type: integer
        errors:
          description: Each refused part of the request.
          items:
            $ref: '#/components/schemas/FieldIssue'
          title: Errors
          type: array
        resource:
          description: 'What wasn''t found: `job`, `batch`, `webhook`, `config`, …'
          title: Resource
          type: string
        reason:
          description: The cause within the code.
          title: Reason
          type: string
        parse_id:
          description: The parse the request recorded.
          title: Parse Id
          type: string
        extract_id:
          description: The extraction it recorded.
          title: Extract Id
          type: string
        split_id:
          description: The split it recorded.
          title: Split Id
          type: string
        classify_id:
          description: The classification it recorded.
          title: Classify Id
          type: string
        tables_id:
          description: The tables job it recorded.
          title: Tables Id
          type: string
        charts_id:
          description: The charts job it recorded.
          title: Charts Id
          type: string
        pipeline_id:
          description: The pipeline it recorded.
          title: Pipeline Id
          type: string
        batch_id:
          description: The batch it recorded.
          title: Batch Id
          type: string
        filename:
          description: The file refused.
          title: Filename
          type: string
        declared_type:
          description: The type its name declared.
          title: Declared Type
          type: string
        detected:
          description: The type its contents are.
          title: Detected
          type: string
        supported_types:
          description: The types accepted.
          items:
            type: string
          title: Supported Types
          type: array
        supported:
          description: The values accepted.
          items:
            type: string
          title: Supported
          type: array
        max_size_mb:
          anyOf:
            - type: integer
            - type: number
          description: The largest size accepted.
          title: Max Size Mb
        file_size_mb:
          anyOf:
            - type: integer
            - type: number
          description: The file's size.
          title: File Size Mb
        plan_name:
          description: Your organization's plan.
          title: Plan Name
          type: string
        pages_used:
          anyOf:
            - type: integer
            - type: number
          description: Pages used this period.
          title: Pages Used
        page_allowance:
          anyOf:
            - type: integer
            - type: number
          description: Pages the plan allows.
          title: Page Allowance
        upgrade_url:
          description: Where to change your plan.
          title: Upgrade Url
          type: string
        action_required:
          description: What to do to continue.
          title: Action Required
          type: string
        billing_info:
          additionalProperties:
            $ref: '#/components/schemas/JsonValue'
          description: Your organization's billing state, as the gate read it.
          title: Billing Info
          type: object
      required:
        - type
        - title
        - status
        - code
        - retryable
      title: Problem
      type: object
    WebhookPingResponse:
      properties:
        delivered:
          type: boolean
          title: Delivered
          description: '`true` when your endpoint returned a 2xx status.'
        failure:
          type: string
          enum:
            - timeout
            - refused
            - tls
            - http_error
            - blocked
          title: Failure
          description: >-
            Why the ping failed. `http_error` means your endpoint returned a
            non-2xx status (redirects aren't followed). `blocked` means the
            address is one Pulse won't send to, such as a private one.
      additionalProperties: false
      type: object
      required:
        - delivered
      title: WebhookPingResponse
      description: Whether a test ping reached the webhook.
    FieldIssue:
      additionalProperties: false
      description: One refused part of the request.
      properties:
        field:
          description: >-
            The part as sent: a body field's path
            (`config.enhancements.detect[1]`), or `query.<name>` /
            `header.<name>`.
          title: Field
          type: string
        pointer:
          description: >-
            A body field as a JSON Pointer (RFC 6901), e.g.
            `#/config/enhancements/detect/1`. Absent for a query parameter or
            header.
          title: Pointer
          type: string
        issue:
          description: What is wrong with it.
          title: Issue
          type: string
      required:
        - field
        - issue
      title: FieldIssue
      type: object
    JsonValue: {}
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.