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

# Create or update a webhook

> Register a public HTTPS receiver or replace an existing subscription's configuration. Requires `webhooks:manage` plus the read scope for every selected event's resource. Choose and persist the subscription UUID before sending. At most 100 subscriptions can belong to one key.

The response never includes a signing secret. New subscriptions start inactive; rotate the secret once, configure your receiver, then verify it. Any new configuration write also pauses the receiver, cancels queued deliveries and requires verification again. New subscriptions start after the latest published workspace cursor; earlier pending events may arrive later. Include `call.updated` for a broad call lifecycle: `call.completed` only marks the stored `Completed` status, not every unsuccessful terminal outcome.

Persist an `Idempotency-Key`; an identical retry recovers the original response without repeating the configuration change. `400 invalid_webhook_url` requires HTTPS on port 443 without credentials/fragments. `403 insufficient_scope` requires the missing resource-read permission. `409 subscription_limit` requires using an existing subscription; `404 not_found` means the UUID belongs outside this credential.

See [registration and verification](/guides/webhooks#register-and-verify-a-receiver).



## OpenAPI

````yaml /api/openapi.json put /webhooks/{id}
openapi: 3.1.0
info:
  title: PowerDialer API v2
  version: 2.0.0
  description: >-
    Connect your CRM, sales workspace or reporting tools to PowerDialer using
    scoped API keys. Manage contacts and calling lists, read call evidence and
    analytics, and receive signed events. All example records and IDs are
    synthetic; replace them with values from your workspace. Shared-key v1 is
    retired. API availability was verified on 2026-10-08; see /availability for
    historical data coverage. Legacy outbound webhooks use a separate contract.
servers:
  - url: https://api.migration.powerdialer.ai/api/public/v2
    description: Production API v2; availability verified on 2026-10-08.
security:
  - ApiKey: []
tags:
  - name: Authentication
  - name: Contacts
  - name: Calling lists
  - name: Imports
  - name: Calls
  - name: Synchronization
  - name: Analytics
  - name: Webhooks
  - name: Webhook deliveries
  - name: Incoming webhook payloads
paths:
  /webhooks/{id}:
    put:
      tags:
        - Webhooks
      summary: Create or update a webhook
      description: >-
        Register a public HTTPS receiver or replace an existing subscription's
        configuration. Requires `webhooks:manage` plus the read scope for every
        selected event's resource. Choose and persist the subscription UUID
        before sending. At most 100 subscriptions can belong to one key.


        The response never includes a signing secret. New subscriptions start
        inactive; rotate the secret once, configure your receiver, then verify
        it. Any new configuration write also pauses the receiver, cancels queued
        deliveries and requires verification again. New subscriptions start
        after the latest published workspace cursor; earlier pending events may
        arrive later. Include `call.updated` for a broad call lifecycle:
        `call.completed` only marks the stored `Completed` status, not every
        unsuccessful terminal outcome.


        Persist an `Idempotency-Key`; an identical retry recovers the original
        response without repeating the configuration change. `400
        invalid_webhook_url` requires HTTPS on port 443 without
        credentials/fragments. `403 insufficient_scope` requires the missing
        resource-read permission. `409 subscription_limit` requires using an
        existing subscription; `404 not_found` means the UUID belongs outside
        this credential.


        See [registration and
        verification](/guides/webhooks#register-and-verify-a-receiver).
      operationId: putWebhooksById
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: >-
            Subscription UUID that you generate and persist before registration.
            Reuse this ID to manage the same receiver.
          example: 00000000-0000-4000-8000-000000000001
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            pattern: ^[A-Za-z0-9._:-]{1,200}$
          description: >-
            Persist one key for this logical operation before sending it. Reuse
            the same value only with the same method, path and body after a
            timeout. A changed request returns 409 idempotency_conflict; a
            matching retry returns the original response.
          example: 9d6b623c-c132-4d2f-b8cf-7c65d4760dbe
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookWrite'
            example:
              name: CRM updates
              url: https://receiver.example.com/powerdialer
              events:
                - call.completed
                - call.disposition_updated
      responses:
        '200':
          description: >-
            Existing subscription configuration was replaced and paused, or that
            response was replayed.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
            RateLimit-Limit:
              schema:
                type: integer
            RateLimit-Remaining:
              schema:
                type: integer
            Idempotency-Replayed:
              schema:
                type: string
                enum:
                  - 'true'
                  - 'false'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
              example:
                name: CRM updates
                url: https://receiver.example.com/powerdialer
                events:
                  - call.completed
                  - call.disposition_updated
                id: 00000000-0000-4000-8000-000000000001
                active: false
                verifiedAt: null
                createdAt: '2026-10-08T12:00:00.000Z'
        '201':
          description: >-
            The inactive subscription was created, or its original creation
            response was replayed. No signing secret is returned.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
            RateLimit-Limit:
              schema:
                type: integer
            RateLimit-Remaining:
              schema:
                type: integer
            Idempotency-Replayed:
              schema:
                type: string
                enum:
                  - 'true'
                  - 'false'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
              example:
                name: CRM updates
                url: https://receiver.example.com/powerdialer
                events:
                  - call.completed
                  - call.disposition_updated
                id: 00000000-0000-4000-8000-000000000001
                active: false
                verifiedAt: null
                createdAt: '2026-10-08T12:00:00.000Z'
        default:
          description: >-
            Error. 400 invalid request; 401 invalid credential; 403 insufficient
            access; 404 not found; 409 state/idempotency conflict; 413 size
            limit; 422 verification failure; 429 rate limit (Retry-After
            seconds); 503 temporary service failure.
          headers:
            Retry-After:
              schema:
                type: integer
            X-Request-Id:
              schema:
                type: string
                format: uuid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: invalid_api_key
                  message: API key is invalid, expired or revoked
                  requestId: 00000000-0000-4000-8000-000000000004
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >-
            # Replace example resource IDs and ownerId with values from your
            workspace.

            : "${POWERDIALER_API_KEY:?Set POWERDIALER_API_KEY to your scoped API
            key}"

            # Set this once per operation; reuse it with the same request after
            a timeout.

            : "${POWERDIALER_REQUEST_ID:?Set POWERDIALER_REQUEST_ID to a new
            UUID for this operation}"

            curl --request PUT \
              --url 'https://api.migration.powerdialer.ai/api/public/v2/webhooks/00000000-0000-4000-8000-000000000001' \
              --header "Authorization: Bearer $POWERDIALER_API_KEY" \
              --header "Idempotency-Key: $POWERDIALER_REQUEST_ID" \
              --header 'Content-Type: application/json' \
              --data '{
              "name": "CRM updates",
              "url": "https://receiver.example.com/powerdialer",
              "events": [
                "call.completed",
                "call.disposition_updated"
              ]
            }'
components:
  schemas:
    WebhookWrite:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
          description: A label that helps you identify the integration.
        url:
          type: string
          format: uri
          maxLength: 2000
          description: >-
            HTTPS receiver on port 443, without URL credentials or fragments. On
            verification and delivery, it must resolve exclusively to public IP
            addresses; redirects are not followed. Saving an inactive
            configuration does not establish reachability.
        events:
          type: array
          items:
            $ref: '#/components/schemas/EventType'
          minItems: 1
          maxItems: 16
          description: >-
            Event types to deliver. The key must also have the read permission
            for every selected resource type.
      required:
        - name
        - url
        - events
      additionalProperties: false
      examples:
        - name: CRM updates
          url: https://receiver.example.com/powerdialer
          events:
            - call.completed
            - call.disposition_updated
    Webhook:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Subscription UUID chosen by the client when creating it.
        name:
          type: string
          description: Integration label.
        url:
          type: string
          description: HTTPS receiver URL.
        events:
          type: array
          items:
            $ref: '#/components/schemas/EventType'
          description: Subscribed event types.
        active:
          type: boolean
          description: >-
            Whether delivery is enabled. Creating or replacing configuration
            pauses delivery until verification.
        verifiedAt:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: Time of the most recent successful verification, or null.
        createdAt:
          type: string
          format: date-time
          description: Subscription creation time in UTC.
      required:
        - id
        - name
        - url
        - events
        - active
        - verifiedAt
        - createdAt
      examples:
        - name: CRM updates
          url: https://receiver.example.com/powerdialer
          events:
            - call.completed
            - call.disposition_updated
          id: 00000000-0000-4000-8000-000000000001
          active: false
          verifiedAt: null
          createdAt: '2026-10-08T12:00:00.000Z'
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Stable machine-readable error code.
            message:
              type: string
              description: Human-readable explanation.
            requestId:
              type: string
              format: uuid
              description: Request identifier to include when investigating a failure.
            details:
              type: array
              items:
                type: object
                properties:
                  path:
                    type: string
                  message:
                    type: string
                required:
                  - path
                  - message
              description: Validation errors, when available.
          required:
            - code
            - message
            - requestId
      required:
        - error
      examples:
        - error:
            code: insufficient_scope
            message: Requires contacts:read
            requestId: 00000000-0000-4000-8000-000000000004
    EventType:
      type: string
      enum:
        - contact.created
        - contact.updated
        - contact.deleted
        - list.created
        - list.updated
        - list.deleted
        - list.membership_updated
        - call.created
        - call.updated
        - call.deleted
        - call.completed
        - call.disposition_updated
        - recording.available
        - transcript.available
        - contact.access_revoked
        - list.access_revoked
      examples:
        - call.completed
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      bearerFormat: pd_<live|test>_<credential UUID>.<random secret>
      description: >-
        Issued in Developers. Workspace/owner/scopes come from credential, never
        acting-user headers. API keys cannot manage API credentials.

````

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