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

# Crear un Registro de Webhook

> Utilice este endpoint para registrar un endpoint de webhook con alcance al tenant que recibe notificaciones de eventos de transferencia. El registro está limitado al tenant del llamador, derivado del JWT bearer (claim `tenantId`), nunca de un header de solicitud.

El servidor genera el `signingSecret` y lo devuelve **exactamente una vez** en esta respuesta. Almacénelo de forma segura — no se devuelve nuevamente. Utilícelo para verificar la firma en cada evento entregado. Para obtener un nuevo secreto, llame al endpoint de rotación.

Use el header `X-Idempotency` para deduplicación garantizada. Las llamadas repetidas con la misma clave reproducen la respuesta en caché.



## OpenAPI

````yaml es/openapi/v3-current/ted.yaml post /v1/webhooks
openapi: 3.0.3
info:
  title: API del Plugin de Transferencia Bancaria (TED)
  description: >-
    API completa para transferencias bancarias brasileñas (TED OUT, TED IN, P2P)
    a través de la plataforma Lerian, incluyendo iniciación de transferencias,
    procesamiento, seguimiento de estado y cancelación.
  version: 1.1.9
servers:
  - url: https://ted.sandbox.lerian.net
    description: Sandbox (marcador de posición — aún no disponible para acceso público)
security:
  - BearerAuth: []
  - OAuth2ClientCredentials:
      - api
  - OAuth2Password:
      - api
tags:
  - name: Transfers API
    description: Endpoints para iniciar, procesar, rastrear y cancelar transferencias.
  - name: Webhooks
    description: >-
      Endpoints para registrar y gestionar suscripciones de webhooks con alcance
      al tenant para eventos de transferencia.
  - name: Webhook DLQ
    description: >-
      Endpoints para inspeccionar y reintentar mensajes de la dead-letter queue
      de webhooks.
paths:
  /v1/webhooks:
    post:
      tags:
        - Webhooks
      summary: Crear un Registro de Webhook
      description: >-
        Utilice este endpoint para registrar un endpoint de webhook con alcance
        al tenant que recibe notificaciones de eventos de transferencia. El
        registro está limitado al tenant del llamador, derivado del JWT bearer
        (claim `tenantId`), nunca de un header de solicitud.


        El servidor genera el `signingSecret` y lo devuelve **exactamente una
        vez** en esta respuesta. Almacénelo de forma segura — no se devuelve
        nuevamente. Utilícelo para verificar la firma en cada evento entregado.
        Para obtener un nuevo secreto, llame al endpoint de rotación.


        Use el header `X-Idempotency` para deduplicación garantizada. Las
        llamadas repetidas con la misma clave reproducen la respuesta en caché.
      operationId: createWebhook
      parameters:
        - $ref: '#/components/parameters/XIdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWebhookRequest'
            examples:
              create:
                summary: Subscribe to completed transfers
                value:
                  name: Operations webhook
                  endpointUrl: https://hooks.example.com/transfer-events
                  enabled: true
                  eventTypes:
                    - transfer.completed
                    - transfer.rejected
      responses:
        '201':
          description: >-
            Indica que el registro de webhook fue creado. El `signingSecret`
            solo se devuelve en esta respuesta.


            Las llamadas repetidas con la misma clave `X-Idempotency` reproducen
            la respuesta en caché.


            Consulte [Reintentos e
            idempotencia](/es/reference/retries-idempotency) para más detalles.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateWebhookResponse'
              examples:
                created:
                  summary: Registration created with signing secret
                  value:
                    id: 550e8400-e29b-41d4-a716-446655440000
                    name: Operations webhook
                    endpointUrl: https://hooks.example.com/transfer-events
                    enabled: true
                    eventTypes:
                      - transfer.completed
                      - transfer.rejected
                    signingSecret: whsec_example_not_a_real_secret
                    createdAt: '2026-02-01T15:30:00Z'
                    updatedAt: '2026-02-01T15:30:00Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/WebhookConflict'
        '422':
          $ref: '#/components/responses/WebhookValidationError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    XIdempotencyKey:
      name: X-Idempotency
      in: header
      required: true
      description: >-
        Clave de idempotencia requerida para reintentos seguros. Utilice un UUID
        v4 o un identificador de negocio único. Si se envía la misma clave
        nuevamente y la solicitud original ya fue procesada, se devuelve la
        respuesta almacenada en caché.


        Consulte [Reintentos e idempotencia](/es/reference/retries-idempotency)
        para más detalles.
      schema:
        type: string
        maxLength: 255
      example: 019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b
  schemas:
    CreateWebhookRequest:
      type: object
      required:
        - name
        - endpointUrl
      properties:
        name:
          type: string
          description: Un nombre legible para el registro.
          example: Operations webhook
        endpointUrl:
          type: string
          format: uri
          pattern: ^https://
          description: >-
            El endpoint que recibe las entregas de eventos. Debe ser una URL
            HTTPS.
          example: https://hooks.example.com/transfer-events
        enabled:
          type: boolean
          description: Si el registro está activo. Por defecto es true cuando se omite.
          example: true
        eventTypes:
          type: array
          maxItems: 64
          description: >-
            Los tipos de evento a los que se suscribe este endpoint. Cuando se
            omite, el registro recibe todos los tipos de evento. Utilice el
            endpoint Listar Tipos de Evento de Webhook para conocer los valores
            aceptados.
          items:
            type: string
          example:
            - transfer.completed
            - transfer.rejected
    CreateWebhookResponse:
      type: object
      allOf:
        - $ref: '#/components/schemas/WebhookRegistrationResponse'
        - type: object
          required:
            - signingSecret
          properties:
            signingSecret:
              type: string
              description: >-
                El secreto de firma generado por el servidor, devuelto
                **únicamente** en esta respuesta. Almacénelo de forma segura y
                utilícelo para verificar la firma en los eventos entregados.
              example: whsec_example_not_a_real_secret
    WebhookRegistrationResponse:
      type: object
      required:
        - id
        - name
        - endpointUrl
        - enabled
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
          description: El identificador único del registro de webhook.
          example: 550e8400-e29b-41d4-a716-446655440000
        name:
          type: string
          description: El nombre legible del registro.
          example: Operations webhook
        endpointUrl:
          type: string
          format: uri
          description: El endpoint HTTPS que recibe las entregas de eventos.
          example: https://hooks.example.com/transfer-events
        enabled:
          type: boolean
          description: Si el registro está activo.
          example: true
        eventTypes:
          type: array
          description: >-
            Los tipos de evento a los que se suscribe este endpoint. Ausente
            cuando el registro recibe todos los tipos de evento.
          items:
            type: string
          example:
            - transfer.completed
        createdAt:
          type: string
          format: date-time
          description: La marca de tiempo de cuando se creó el registro.
          example: '2026-02-01T15:30:00Z'
        updatedAt:
          type: string
          format: date-time
          description: La marca de tiempo de la última actualización.
          example: '2026-02-01T15:30:00Z'
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - service
            - category
            - message
            - requestId
          properties:
            code:
              type: string
              description: >-
                El código de error estable. Los errores del plugin usan el
                formato `BTF-XXXX`; los rechazos de negocio/autenticación de JD
                SPB transmiten el código del proveedor sin modificar (p. ej.
                `AAC90`, `ACE95`, `DVE01`), y los fallos de JD a nivel de
                transporte muestran los marcadores sintéticos `TRANSPORT` o
                `JD_MISSING_CODE`. Haga la coincidencia sobre este valor en
                lugar del estado HTTP.
              example: BTF-0010
            service:
              type: string
              description: El servicio o dominio que produjo el error.
              example: plugin
            category:
              type: string
              description: >-
                Categoría de error legible por máquina utilizada para las
                decisiones de reintento.
              enum:
                - deterministic
                - transient
                - rate_limit
                - plugin
              example: deterministic
            message:
              type: string
              description: Un resumen del error legible por humanos.
              example: >-
                Transfers can only be initiated Monday-Friday between 06:30 and
                17:00 Brasília time
            requestId:
              type: string
              description: >-
                El ID de correlación de la solicitud. Presente incluso cuando
                está vacío.
              example: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            fields:
              type: object
              additionalProperties: true
              description: >-
                Metadatos estructurados de validación o reintento cuando están
                disponibles. Los detalles de validación a nivel de campo,
                encabezado, ruta y consulta se devuelven todos aquí.
              example:
                currentTime: '2026-02-01T18:30:00-03:00'
                operatingHours: Mon-Fri 06:30-17:00 UTC-3
  responses:
    BadRequest:
      description: >-
        Indica que la solicitud contiene datos de entrada inválidos. Verifique
        los detalles del campo para errores de validación específicos.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidInput:
              summary: Validation error
              value:
                error:
                  code: BTF-0001
                  service: plugin
                  category: deterministic
                  message: >-
                    The request contains invalid fields. Check the field details
                    below.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    recipientIspb: must be 8 digits
                    amount: must be positive
    Unauthorized:
      description: Indica que la solicitud no tiene un token de autenticación válido.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unauthorized:
              summary: Missing authorization
              value:
                error:
                  code: BTF-0401
                  service: plugin
                  category: deterministic
                  message: Missing or invalid authentication token
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    Forbidden:
      description: >-
        Indica que el llamador está autenticado pero carece de permiso para esta
        operación, o el tenant no está licenciado para este endpoint.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            notLicensed:
              summary: Tenant not licensed
              value:
                error:
                  code: BTF-0403
                  service: plugin
                  category: deterministic
                  message: Tenant is not licensed to use this endpoint
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            permissionDenied:
              summary: Caller lacks permission
              value:
                error:
                  code: BTF-0405
                  service: plugin
                  category: deterministic
                  message: Caller lacks permission for this resource
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    WebhookConflict:
      description: >-
        Indica que ya existe un registro de webhook con el mismo endpoint para
        este tenant.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            duplicate:
              summary: Endpoint already registered
              value:
                error:
                  code: BTF-0012
                  service: plugin
                  category: deterministic
                  message: webhook registration already exists
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    WebhookValidationError:
      description: >-
        Indica que el payload del webhook violó una restricción de dominio, como
        una URL de endpoint inválida o un tipo de evento no soportado.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidEventType:
              summary: Unsupported event type
              value:
                error:
                  code: BTF-0002
                  service: plugin
                  category: deterministic
                  message: eventTypes contains an unsupported value
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            invalidUrl:
              summary: Endpoint URL not allowed
              value:
                error:
                  code: BTF-0002
                  service: plugin
                  category: deterministic
                  message: endpointUrl must be a valid HTTPS URL
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    ServiceUnavailable:
      description: >-
        Indica que un servicio externo (CRM, JD SPB, Midaz o Fees) no está
        disponible temporalmente.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            crmUnavailable:
              summary: CRM service down
              value:
                error:
                  code: BTF-0502
                  service: crm
                  category: transient
                  message: >-
                    Unable to validate account. The CRM service is temporarily
                    unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            jdUnavailable:
              summary: JD SPB unavailable
              value:
                error:
                  code: TRANSPORT
                  service: jd_spb
                  category: transient
                  message: >-
                    Unable to submit transfer. The JD SPB service is temporarily
                    unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            midazUnavailable:
              summary: Midaz ledger unavailable
              value:
                error:
                  code: BTF-2000
                  service: midaz
                  category: transient
                  message: >-
                    Unable to process transfer. The Midaz ledger service is
                    temporarily unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            feeServiceUnavailable:
              summary: Fee service unavailable (fail-closed mode)
              value:
                error:
                  code: BTF-3000
                  service: fees
                  category: transient
                  message: >-
                    Unable to calculate fee. The fee service is temporarily
                    unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            dlqInspectorUnavailable:
              summary: DLQ inspector not configured
              value:
                error:
                  code: BTF-9005
                  service: plugin
                  category: deterministic
                  message: DLQ inspector is not configured
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Autenticación mediante token JWT Bearer. El tenantId se deriva del token
        bearer o del contexto autenticado de la solicitud y no se proporciona a
        través de X-Organization-Id.
    OAuth2ClientCredentials:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: /v1/login/oauth/access_token
          scopes:
            api: Acceso a la API de transferencias TED
    OAuth2Password:
      type: oauth2
      flows:
        password:
          tokenUrl: /v1/login/oauth/access_token
          scopes:
            api: Acceso a la API de transferencias TED

````