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

# Update the workspace's first webhook endpoint.

> Saves the workspace's FIRST outbound webhook endpoint and marks it connected. It overwrites that endpoint's URL, events, channel scope and secret rather than registering an additional endpoint, so it can silently replace an endpoint someone configured in the dashboard. To run more than one endpoint, manage them under Configurations → Integrations → Webhooks instead. `url` (alias `endpoint`) must be a public https URL — private/internal/unreachable hosts are rejected with 422. `events` must be a non-empty array of topics from the catalogue (GET /webhooks/events); unknown topics are rejected with 422 and message-lifecycle events the selected channel cannot deliver are silently dropped (if every submitted event is dropped the request 422s). `channel` scopes message events to a single channel (default "all"). A signing secret is generated automatically on first connect and preserved on subsequent updates unless you pass a new `secret`. Use the secret to verify the signature on delivered payloads. Returns the saved subscription (without the secret value).



## OpenAPI

````yaml /api-reference/openapi.json put /webhooks
openapi: 3.1.0
info:
  title: DMLY REST API
  version: 1.0.0
  description: >-
    DMLY's public REST API — contacts/CRM, the unified inbox, broadcasts and
    automations,

    appointments and classes, the commerce catalogue, finance, webhooks and
    media.


    ## Authentication


    Every request carries a **workspace API key**, which both authenticates the
    caller and

    selects the workspace — so there is no workspace id in the URL.


    ```

    x-api-key: dmly_xxxxxxxx…

    ```


    `Authorization: Bearer dmly_xxxxxxxx…` is also accepted.


    Mint keys from the DMLY dashboard (Salesbot → Integrations → API), or from
    the CLI with

    `php artisan dmly:api-key create`. The plaintext key is shown **once** on
    creation; only

    its sha256 hash is stored.


    ## Conventions


    - Resources are identified by their public `uuid`, returned as `id`.

    - Lists are paginated with `?per_page` (alias `?limit`) — default 25, hard
    cap 100 — and
      return `{ "data": [...], "links": {...}, "meta": {...} }`.
    - Single resources return `{ "data": { ... } }`.


    ## Rate limiting


    **60 requests per minute, per API key.** Each key gets its own budget, so
    two integrations

    calling from the same server or office network do not compete, as long as
    they use separate

    keys. Requests without a valid key (missing, mistyped, or revoked) share one
    60/minute

    budget per IP address instead; they fail with `401` regardless.


    Exceeding the limit returns `429` with a `Retry-After` header and a JSON
    body:

    `{"message": "Too many requests. Retry after 42 seconds."}`. Full detail:

    [Rate limits](/api-reference/rate-limits).
  contact:
    name: DMLY
    url: https://dmly.io
servers:
  - url: https://dash.dmly.io/api/v1
    description: DMLY
security:
  - apiKeyAuth: []
  - bearerAuth: []
tags:
  - name: Account
    description: Endpoints for Account.
  - name: Channels
    description: Endpoints for Channels.
  - name: Contacts
    description: Endpoints for Contacts.
  - name: Tags
    description: Endpoints for Tags.
  - name: Segments
    description: Endpoints for Segments.
  - name: Conversations & Messages
    description: Endpoints for Conversations & Messages.
  - name: Broadcasts
    description: Endpoints for Broadcasts.
  - name: Automations
    description: Endpoints for Automations.
  - name: Appointments
    description: Endpoints for Appointments.
  - name: Services & Service Categories
    description: Endpoints for Services & Service Categories.
  - name: Staff
    description: Endpoints for Staff.
  - name: Classes
    description: Endpoints for Classes.
  - name: Offerings — Products & Plans
    description: Endpoints for Offerings — Products & Plans.
  - name: Finance — Invoices
    description: Endpoints for Finance — Invoices.
  - name: Finance — Orders
    description: Endpoints for Finance — Orders.
  - name: Finance — Payments & Coupons
    description: Endpoints for Finance — Payments & Coupons.
  - name: Finance — Subscriptions
    description: Endpoints for Finance — Subscriptions.
  - name: Gift Cards
    description: Endpoints for Gift Cards.
  - name: Webhooks
    description: Endpoints for Webhooks.
  - name: Media
    description: Endpoints for Media.
  - name: Webhooks Contacts and clients
    description: 'Webhook events: Contacts & clients.'
  - name: Webhooks Conversations
    description: 'Webhook events: Conversations.'
  - name: Webhooks Calls
    description: 'Webhook events: Calls.'
  - name: Webhooks Message lifecycle
    description: 'Webhook events: Message lifecycle.'
  - name: Webhooks Appointments
    description: 'Webhook events: Appointments.'
  - name: Webhooks Classes
    description: 'Webhook events: Classes.'
  - name: Webhooks Invoices
    description: 'Webhook events: Invoices.'
  - name: Webhooks Orders
    description: 'Webhook events: Orders.'
  - name: Webhooks Payments
    description: 'Webhook events: Payments.'
  - name: Webhooks Subscriptions
    description: 'Webhook events: Subscriptions.'
  - name: Webhooks Offerings and credits
    description: 'Webhook events: Offerings & credits.'
  - name: Webhooks Store e commerce
    description: 'Webhook events: Store (e-commerce).'
  - name: Webhooks Automations
    description: 'Webhook events: Automations.'
  - name: Webhooks Broadcasts
    description: 'Webhook events: Broadcasts.'
paths:
  /webhooks:
    put:
      tags:
        - Webhooks
      summary: Update the workspace's first webhook endpoint.
      description: >-
        Saves the workspace's FIRST outbound webhook endpoint and marks it
        connected. It overwrites that endpoint's URL, events, channel scope and
        secret rather than registering an additional endpoint, so it can
        silently replace an endpoint someone configured in the dashboard. To run
        more than one endpoint, manage them under Configurations → Integrations
        → Webhooks instead. `url` (alias `endpoint`) must be a public https URL
        — private/internal/unreachable hosts are rejected with 422. `events`
        must be a non-empty array of topics from the catalogue (GET
        /webhooks/events); unknown topics are rejected with 422 and
        message-lifecycle events the selected channel cannot deliver are
        silently dropped (if every submitted event is dropped the request 422s).
        `channel` scopes message events to a single channel (default "all"). A
        signing secret is generated automatically on first connect and preserved
        on subsequent updates unless you pass a new `secret`. Use the secret to
        verify the signature on delivered payloads. Returns the saved
        subscription (without the secret value).
      operationId: webhooks.update.put
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  format: uri
                events:
                  type: array
                  items:
                    type: string
                channel:
                  type: string
                secret:
                  type: string
            example:
              url: https://hooks.example.com/dmly/incoming
              events:
                - contact.created
                - booking.created
                - invoice.paid
              channel: all
              secret: whsec_my_own_signing_secret_optional
      responses:
        '200':
          description: Success.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  responses:
    Unauthorized:
      description: The API key is missing, invalid, or its workspace no longer exists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: >-
        The workspace for this API key has been suspended, either directly or
        because its agency is no longer active.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: No such resource in this workspace.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ValidationError:
      description: Validation failed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'
    RateLimited:
      description: >-
        Rate limit exceeded: 60 requests per minute per API key. Requests
        without a valid key share a per-IP budget instead.
      headers:
        Retry-After:
          description: Seconds until the limit resets.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      properties:
        message:
          type: string
    ValidationError:
      type: object
      properties:
        message:
          type: string
        errors:
          type: object
          description: Field name → array of messages.
          additionalProperties:
            type: array
            items:
              type: string
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your workspace API key. It both authenticates the caller and selects the
        workspace.
    bearerAuth:
      type: http
      scheme: bearer
      description: 'The same workspace API key, sent as `Authorization: Bearer <key>`.'

````