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

# Editar una URL de avisos

> Cambia la URL, la descripción, los avisos o el estado. Los avisos nuevos tienen las mismas reglas que al crear.
`status: enabled` vuelve a activar una URL desactivada (también una que Craqui desactivó por errores) y pone en cero
sus fallas; `status: disabled` la desactiva y lo que estaba pendiente no se envía. Las mismas reglas de `not_found`
que al verla.

Solo para estudios: en una academia responde `wrong_vertical`. Solo con una clave `crq_live_`: una `crq_test_`
responde `scope_required` (tu estudio de prueba no envía avisos).




## OpenAPI

````yaml /openapi.yaml patch /webhook_endpoints/{id}
openapi: 3.1.0
info:
  title: API de Craqui
  version: '2026-12-01'
  summary: Conecta tu web o tu sistema a tu estudio o academia en Craqui.
  description: >
    API REST de Craqui. Cada clave pertenece a un solo negocio (un estudio o una
    academia) y todo lo

    que devuelve es de ese negocio.


    - **Autenticación:** `Authorization: Bearer <clave>`. Las claves se crean en
    Configuración →
      Integraciones. Una clave `crq_live_` usa los datos reales del negocio; una `crq_test_` usa su
      estudio de prueba: la misma configuración (sedes, clases, packs, planes) con clientes y
      reservas de ejemplo, que no le escribe a nadie. La URL es la misma: el entorno lo decide la
      clave. Todo objeto dice en `livemode` de cuál de los dos viene.
    - **Versión:** cada clave queda fijada a la versión vigente cuando se creó.
    El header
      `Craqui-Version` la sobrescribe por pedido, y la respuesta siempre dice cuál se usó.
    - **Errores:** `application/problem+json` (RFC 9457), con un `code` estable
    para programar y un
      `request_id` para buscar el pedido en tu panel.
    - **Montos:** enteros en `amount_cents` (siempre ×100) junto con la moneda
    ISO 4217.

    - **Fechas y horas:** instantes en RFC 3339 con el offset del negocio;
    fechas sin hora como
      `YYYY-MM-DD` en la fecha local del negocio.
  contact:
    name: Craqui
    url: https://craqui.com
servers:
  - url: https://api.craqui.com/v1
    description: Producción
security:
  - bearerAuth: []
tags:
  - name: business
    description: El negocio al que pertenece la clave (un estudio o una academia).
  - name: booking_policy
    description: Las reglas de reserva del estudio. Solo estudios.
  - name: centers
    description: Las sedes del estudio. Solo estudios.
  - name: rooms
    description: Los salones de cada sede. Solo estudios.
  - name: teachers
    description: Quienes dan clases en el estudio. Solo estudios.
  - name: courses
    description: Las disciplinas del estudio (Yoga, Pilates…). Solo estudios.
  - name: classes
    description: Las clases con su horario semanal. Solo estudios.
  - name: sessions
    description: El horario del estudio, sesión por sesión, con sus lugares. Solo estudios.
  - name: clients
    description: >-
      Los clientes del estudio, con el contacto separado en su propio permiso.
      Solo estudios.
  - name: bookings
    description: Las reservas de las sesiones. Solo estudios.
  - name: credit_packs
    description: Los packs de créditos que vende el estudio. Solo estudios.
  - name: membership_plans
    description: Los planes de membresía que vende el estudio. Solo estudios.
  - name: intro_offers
    description: Las ofertas de bienvenida que vende el estudio. Solo estudios.
  - name: credits
    description: Los créditos de los clientes, sus lotes y sus movimientos. Solo estudios.
  - name: memberships
    description: Las membresías de los clientes y sus congelamientos. Solo estudios.
  - name: fees
    description: Las cuotas que el estudio le cobra a cada cliente. Solo estudios.
  - name: payments
    description: Los pagos de las cuotas. Solo estudios.
  - name: refunds
    description: Los reembolsos de los pagos. Solo estudios.
  - name: events
    description: >
      Lo que cambió en el estudio en los últimos 30 días, para enterarte sin
      consultar cada lista. Solo

      estudios.
  - name: webhook_endpoints
    description: >
      Las URLs a las que Craqui le avisa cada vez que algo cambia en el estudio,
      firmado y con reintentos. Solo

      estudios y solo con una clave `crq_live_`.
paths:
  /webhook_endpoints/{id}:
    patch:
      tags:
        - webhook_endpoints
      summary: Editar una URL de avisos
      description: >
        Cambia la URL, la descripción, los avisos o el estado. Los avisos nuevos
        tienen las mismas reglas que al crear.

        `status: enabled` vuelve a activar una URL desactivada (también una que
        Craqui desactivó por errores) y pone en cero

        sus fallas; `status: disabled` la desactiva y lo que estaba pendiente no
        se envía. Las mismas reglas de `not_found`

        que al verla.


        Solo para estudios: en una academia responde `wrong_vertical`. Solo con
        una clave `crq_live_`: una `crq_test_`

        responde `scope_required` (tu estudio de prueba no envía avisos).
      operationId: updateWebhookEndpoint
      parameters:
        - $ref: '#/components/parameters/CraquiVersion'
        - $ref: '#/components/parameters/IdempotencyKey-2'
        - $ref: '#/components/parameters/WebhookEndpointIdPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookEndpointUpdate'
      responses:
        '200':
          description: OK.
          headers:
            Request-Id:
              $ref: '#/components/headers/RequestId'
            Craqui-Version:
              $ref: '#/components/headers/CraquiVersion'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimitPolicy'
            Idempotent-Replayed:
              $ref: '#/components/headers/IdempotentReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpoint'
              example:
                id: whe_2d3gn7x2sz9rgsmv8z1hdqx6h1
                object: webhook_endpoint
                livemode: true
                url: https://hooks.recepcion-marea.example.com/craqui
                description: CRM de recepción
                enabled_events:
                  - booking.created
                  - booking.cancelled
                  - booking.attended
                status: enabled
                disabled_reason: null
                api_version: '2026-12-01'
                created_at: '2026-11-20T15:30:00-03:00'
                updated_at: '2026-11-20T15:30:00-03:00'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    CraquiVersion:
      name: Craqui-Version
      in: header
      required: false
      description: >
        Versión de la API para este pedido (`YYYY-MM-DD`). Si no la mandas, se
        usa la versión fijada en

        la clave cuando se creó.
      schema:
        type: string
        pattern: ^\d{4}-\d{2}-\d{2}$
        examples:
          - '2026-12-01'
    IdempotencyKey-2:
      name: Idempotency-Key
      in: header
      required: true
      description: >
        Obligatorio en todo `POST` que crea o modifica algo. Un valor único por
        operación (por ejemplo

        un UUID). Si repites el pedido con la misma clave y el mismo cuerpo
        dentro de 24 horas, recibes

        la misma respuesta sin que se repita el efecto.
      schema:
        type: string
        minLength: 1
        maxLength: 255
    WebhookEndpointIdPath:
      name: id
      in: path
      required: true
      description: El id de la URL (`whe_…`).
      schema:
        $ref: '#/components/schemas/WebhookEndpointId'
  schemas:
    WebhookEndpointUpdate:
      type: object
      additionalProperties: false
      properties:
        url:
          type: string
          maxLength: 2048
        description:
          type:
            - string
            - 'null'
          maxLength: 200
        enabled_events:
          type: array
          minItems: 1
          items:
            type: string
        status:
          type: string
          enum:
            - enabled
            - disabled
          description: >-
            `enabled` vuelve a activar una URL desactivada y pone en cero sus
            fallas.
    WebhookEndpoint:
      type: object
      description: >
        Una URL a la que Craqui le avisa cada vez que algo cambia en tu estudio.
        Cada aviso es un `event` firmado

        con Standard Webhooks (headers `webhook-id`, `webhook-timestamp` y
        `webhook-signature`). Si tu sistema no

        responde 2xx, se reintenta durante unos 3 días; si falla de forma
        sostenida, la URL se desactiva

        (`disabled_reason: failing`) y se le avisa al propietario del estudio.


        Tu clave solo ve las URLs creadas por la API cuyos avisos puede leer:
        las que creó el propietario desde el

        panel no aparecen.
      required:
        - id
        - object
        - livemode
        - url
        - description
        - enabled_events
        - status
        - disabled_reason
        - api_version
        - created_at
        - updated_at
      properties:
        id:
          $ref: '#/components/schemas/WebhookEndpointId'
        object:
          type: string
          const: webhook_endpoint
        livemode:
          type: boolean
          description: >-
            `true`: solo una clave `crq_live_` configura avisos (una `crq_test_`
            no; tu estudio de prueba no envía nada).
        url:
          type: string
          format: uri
          maxLength: 2048
          description: >-
            La URL, `https://` en el puerto 443, con nombre (no una IP) y
            pública.
        description:
          type:
            - string
            - 'null'
          maxLength: 200
        enabled_events:
          type: array
          description: >
            Los tipos de evento que recibe. Al crear o editar puedes mandar
            `["*"]`: se guarda como la lista de los

            tipos que tu clave puede leer en ese momento.
          items:
            type: string
        status:
          type: string
          enum:
            - enabled
            - disabled
          x-extensible-enum: true
        disabled_reason:
          type:
            - string
            - 'null'
          description: >-
            `manual` si la desactivó alguien, `failing` si la desactivó Craqui
            porque no respondía; `null` si está activa.
          enum:
            - manual
            - failing
            - null
        api_version:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: La versión de la API con la que se creó.
        created_at:
          $ref: '#/components/schemas/Instant'
        updated_at:
          $ref: '#/components/schemas/Instant'
        secret:
          type:
            - string
            - 'null'
          pattern: ^whsec_[A-Za-z0-9+/=]+$
          description: >
            El secreto de firma. Solo viene al crear la URL y al cambiar el
            secreto, y es la única vez que lo vas a

            ver: guárdalo. Si repites el pedido con la misma `Idempotency-Key`,
            la respuesta guardada trae

            `secret: null`; en ese caso, cambia el secreto.
    WebhookEndpointId:
      type: string
      description: Id de una URL de avisos.
      pattern: ^whe_[0-7][0-9a-hjkmnp-tv-z]{25}$
      examples:
        - whe_2d3gn7x2sz9rgsmv8z1hdqx6h1
    Instant:
      type: string
      format: date-time
      description: Instante en RFC 3339 con el offset del negocio en ese momento.
      examples:
        - '2026-12-02T19:00:00-03:00'
    Problem:
      type: object
      description: >
        Un error. Programa contra `code`, que no cambia; `title` y `detail` son
        para mostrarle a una

        persona y pueden cambiar de redacción.
      required:
        - type
        - title
        - status
        - code
        - request_id
      properties:
        type:
          type: string
          format: uri
          description: URL de la página de la documentación de este error.
          examples:
            - https://docs.craqui.com/errors/invalid_api_key
        title:
          type: string
          description: Resumen corto, en español.
          examples:
            - La clave no es válida
        status:
          type: integer
          description: El mismo código HTTP de la respuesta.
          examples:
            - 401
        code:
          type: string
          description: >
            Código estable del error. La lista puede crecer: trata un `code` que
            no conoces como un

            error genérico de su `status`.
          examples:
            - invalid_api_key
        detail:
          type: string
          description: Qué pasó y qué hacer, en español.
          examples:
            - >-
              Revisa que copiaste la clave completa, incluido el prefijo
              (crq_live_ o crq_test_).
        request_id:
          type: string
          pattern: ^req_[0-9a-hjkmnp-tv-z]{26}$
          description: >-
            Identificador del pedido. Búscalo en Configuración → Integraciones →
            Actividad de la API.
          examples:
            - req_01hzx8m4k2a7d9q3f5w6y8z0bc
        doc_url:
          type: string
          format: uri
          description: >-
            Igual a `type`, por compatibilidad con clientes que buscan este
            campo.
        required_scope:
          type: string
          description: >-
            Solo en `scope_required` y `event_type_not_permitted`. El permiso
            que le falta a la clave.
          examples:
            - business:read
        errors:
          type: array
          description: Solo en errores de validación. Un elemento por campo con problemas.
          items:
            $ref: '#/components/schemas/FieldError'
    FieldError:
      type: object
      required:
        - field
        - code
      properties:
        field:
          type: string
          description: El campo, como lo mandaste (por ejemplo `session_id`).
          examples:
            - session_id
        code:
          type: string
          description: Qué tiene mal el campo.
          examples:
            - invalid_prefix
        detail:
          type: string
          description: Explicación en español.
  headers:
    RequestId:
      description: Identificador del pedido. Aparece también en el cuerpo de los errores.
      schema:
        type: string
        pattern: ^req_[0-9a-hjkmnp-tv-z]{26}$
    CraquiVersion:
      description: La versión de la API con la que se respondió.
      schema:
        type: string
        pattern: ^\d{4}-\d{2}-\d{2}$
    RateLimit:
      description: >-
        Pedidos que quedan en la ventana actual y segundos hasta que se renueva
        (draft IETF httpapi-ratelimit-headers).
      schema:
        type: string
        examples:
          - '"read";r=97;t=42'
    RateLimitPolicy:
      description: Límite de la clave por ventana (draft IETF httpapi-ratelimit-headers).
      schema:
        type: string
        examples:
          - '"read";q=100;w=60'
    IdempotentReplayed:
      description: >-
        `true` cuando la respuesta es la guardada de un pedido anterior con la
        misma `Idempotency-Key`.
      schema:
        type: string
        enum:
          - 'true'
    RetryAfter:
      description: Segundos que hay que esperar antes de reintentar.
      schema:
        type: integer
        minimum: 0
  responses:
    BadRequest:
      description: >
        El pedido está mal formado. Códigos posibles: `invalid_api_version`,
        `idempotency_key_required`,

        `validation_failed` (con un elemento de `errors` por parámetro:
        `unknown_parameter`,

        `invalid_prefix`, `invalid_id`, `invalid_date`, `invalid_boolean`,
        `invalid_enum`,

        `invalid_limit`, `duplicate_parameter`, `expand_not_supported`…) e
        `invalid_cursor` (un

        `starting_after` de otra búsqueda: repite la primera página con los
        mismos filtros). En las URLs de

        avisos, `webhook_url_invalid` (en `errors`, la causa: `not_https`,
        `port_not_allowed`,

        `credentials_in_url`, `ip_literal`, `internal_hostname`,
        `private_address`, `craqui_host` o `too_long`).

        El detalle de un error nunca repite el valor que mandaste.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Unauthorized:
      description: >
        Falta la clave o no sirve. Códigos posibles: `missing_api_key`,
        `invalid_api_key`,

        `revoked_api_key`, `expired_api_key`, `legacy_api_key`.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          examples:
            revoked:
              value:
                type: https://docs.craqui.com/errors/revoked_api_key
                title: La clave fue revocada
                status: 401
                code: revoked_api_key
                detail: Crea una clave nueva en Configuración → Integraciones.
                request_id: req_01hzx8m4k2a7d9q3f5w6y8z0bc
    Forbidden:
      description: >
        La clave es válida pero no puede hacer esto. Códigos posibles:
        `scope_required`,

        `plan_required`, `api_key_suspended`, `browser_not_allowed`,
        `wrong_vertical`,

        `event_type_not_permitted` (eventos de un recurso que la clave no puede
        leer; `required_scope` dice cuál) y

        `write_access_disabled` (en una ruta que crea o cambia datos, si tu
        negocio no tiene habilitada la escritura por

        la API).
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    NotFound:
      description: >-
        No existe, o no es de tu negocio. Código `not_found` o
        `route_not_found`.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Conflict:
      description: >
        Solo con una clave `crq_test_`: tu estudio de prueba no está listo.
        Código

        `sandbox_unavailable`. Restablece tus datos de prueba en Configuración →
        Integraciones y vuelve

        a intentar. Una clave de prueba nunca responde con los datos reales del
        negocio. En los pedidos que

        crean o modifican algo, también `idempotency_in_progress` (el mismo
        pedido todavía se está procesando) y,

        al crear una URL de avisos, `webhook_endpoint_limit_reached` (ya hay
        10). En una ruta que crea o cambia datos

        del estudio, además, sus reglas no dejan hacerlo: la descripción de cada
        ruta lista sus códigos.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
          examples:
            sandbox_unavailable:
              value:
                type: https://docs.craqui.com/errors/sandbox_unavailable
                title: Tu estudio de prueba no está listo
                status: 409
                code: sandbox_unavailable
                detail: >-
                  Restablece tus datos de prueba en Configuración →
                  Integraciones y vuelve a intentar.
                request_id: req_01hzx8m4k2a7d9q3f5w6y8z0bc
    UnprocessableEntity:
      description: >
        El pedido se entendió pero no se puede aplicar así. Códigos posibles:
        `idempotency_key_reused` (esa

        `Idempotency-Key` ya se usó con otro pedido: genera una nueva),
        `sandbox_contact_not_allowed` y

        `sandbox_account_reserved` (en tu estudio de prueba, un contacto que no
        es ficticio).
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    TooManyRequests:
      description: >-
        Se pasó el límite de pedidos por minuto de la clave. Código
        `rate_limited`.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        RateLimit:
          $ref: '#/components/headers/RateLimit'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    InternalError:
      description: >-
        Falló algo de nuestro lado. Código `internal_error`. Reintenta; si
        sigue, escríbenos con el `request_id`.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    ServiceUnavailable:
      description: >-
        Los avisos no están disponibles en este momento. Código
        `configuration_error`. Prueba de nuevo más tarde.
      headers:
        Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: crq_live_sk_… / crq_live_rk_…
      description: >
        Clave del negocio. `sk` es una clave completa (todo lo que el rol de
        quien la creó puede dar)

        y `rk` una restringida a los permisos que se eligieron al crearla. Solo
        se usa desde un

        servidor: un pedido desde un navegador se rechaza con
        `browser_not_allowed`.

````

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