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

# Criar webhook

> Registra um endereço para receber notificações e devolve o secret de assinatura — a única vez que ele aparece.

`POST /webhooks`

Faz parte do recurso [Webhooks](/pt-BR/webhooks) — o catálogo de eventos e as regras do `secret`
estão lá.

Registra a URL, define quais eventos ela recebe e devolve `201` com o webhook criado. Já nasce
ativo: se houver evento assinado acontecendo, a primeira entrega sai em seguida.

<Warning>
  **Copie o `secret` desta resposta.** É a única vez que ele sai em claro — as leituras devolvem
  `hasSecret` e `secretHint` no lugar, e **nenhuma rota o troca depois**. Sem ele guardado, não há
  como verificar a assinatura das entregas.
</Warning>

<Note>
  **Não precisa inventar um segredo.** Omita o campo e a plataforma gera um `whsec_…` de 256 bits,
  que volta nesta mesma resposta — mais forte que a maioria dos valores escolhidos à mão. Enviar o
  seu próprio continua valendo, com no mínimo 8 caracteres, para quando o segredo já existe do seu
  lado.
</Note>

<Note>
  **`events` vazio, ou omitido, assina TODOS os eventos** — inclusive os que forem criados no
  futuro. Para receber só o que interessa, liste os códigos do
  [catálogo](/pt-BR/webhooks/listeners); um código fora dele é recusado com `400`.
</Note>

<Note>
  **A URL precisa ser pública.** `localhost`, faixas privadas e endereços de metadata de nuvem são
  recusados com `400` — a lista completa está na [visão geral](/pt-BR/webhooks).
</Note>

## Exemplo

```bash theme={null}
curl -X POST https://api.sandbox.z2pay.com/v1/webhooks \
  -H "x-api-key: SUA_CHAVE_DE_SANDBOX" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f1c8a90-2b7d-4d2e-9b1a-6f0e2c5a9d11" \
  -d '{
    "name": "Notificações de pagamento",
    "url": "https://meusite.com/webhooks/z2pay",
    "events": ["transaction.paid", "transaction.refunded"]
  }'
```

```json Resposta 201 theme={null}
{
  "id": "whk_k9clfafnldd96dbbxruh34233",
  "name": "Notificações de pagamento",
  "url": "https://meusite.com/webhooks/z2pay",
  "events": ["transaction.paid", "transaction.refunded"],
  "isActive": true,
  "hasSecret": true,
  "secretHint": "whsec_kQ8v…rS8t",
  "secret": "whsec_kQ8vN2pR7mT4wY6zA1bC3dE5fG9hJ0kL2nM4pQ6rS8t",
  "autoDisabledAt": null,
  "createdAt": "2026-06-24T13:45:00.000Z",
  "updatedAt": "2026-06-24T13:45:00.000Z"
}
```

<Note>
  O `secret` só aparece aqui. Em [buscar](/pt-BR/webhooks/get) e
  [listar](/pt-BR/webhooks/list), o mesmo webhook volta sem essa linha.
</Note>


## OpenAPI

````yaml openapi/psp.json POST /webhooks
openapi: 3.0.3
info:
  title: Z2Pay PSP API
  version: 1.0.0
  description: API pública do PSP — autenticação via API Key (Credential)
servers:
  - url: https://api.sandbox.z2pay.com/v1
    description: Sandbox
  - url: https://api.z2pay.com/v1
    description: Produção
security: []
tags:
  - name: Cards
    description: Cartões salvos de um cliente
  - name: Chargebacks
    description: Gerenciamento de chargebacks
  - name: Customers
    description: Gerenciamento de clientes (compradores)
  - name: Fees
    description: Tabela de taxas da conta (pix, boleto, cartão, saque, refund, chargeback)
  - name: Recipients
    description: Gerenciamento de recebedores (sellers/merchants que recebem repasses)
  - name: Refunds
    description: Gerenciamento de reembolsos e estornos
  - name: Splits
    description: Regras de divisão do valor de uma venda entre recebedores
  - name: Transactions
    description: Gerenciamento de transações e payments
  - name: Wallets
    description: Saldo, extrato e resumo da carteira de um recebedor, agrupados por moeda
  - name: Webhooks
    description: Configuração, gerenciamento e histórico de entregas de webhooks
  - name: Withdrawals
    description: Solicitação e acompanhamento de saques (payouts) por recipient
paths:
  /webhooks:
    post:
      tags:
        - Webhooks
      summary: Criar webhook
      description: >-
        Registra um novo webhook para receber notificações de eventos. Defina a
        URL e os eventos desejados
      operationId: WebhookController_create
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: Chave única para garantir idempotência da requisição
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: Nome de identificação do webhook.
                url:
                  type: string
                  format: uri
                  description: >-
                    URL HTTPS que receberá as notificações de eventos (via
                    POST).
                events:
                  type: array
                  items:
                    type: string
                    enum:
                      - transaction.created
                      - transaction.waiting_payment
                      - transaction.paid
                      - transaction.partially_paid
                      - transaction.pending
                      - transaction.refused
                      - transaction.failed
                      - transaction.canceled
                      - transaction.waiting_refund
                      - transaction.refunded
                      - transaction.in_protest
                      - transaction.chargeback
                      - payment.created
                      - payment.waiting_payment
                      - payment.paid
                      - payment.pending
                      - payment.refused
                      - payment.failed
                      - payment.canceled
                      - payment.waiting_refund
                      - payment.refunded
                      - payment.in_protest
                      - payment.chargeback
                      - refund.created
                      - refund.approved
                      - refund.refused
                      - refund.processing
                      - refund.refunded
                      - refund.failed
                      - refund.awaiting_bank_details
                      - refund.bank_details_received
                      - refund.invalid_bank_details
                      - refund.ted_processing
                      - chargeback.opened
                      - chargeback.under_review
                      - chargeback.submitted
                      - chargeback.won
                      - chargeback.lost
                      - chargeback.document.uploaded
                      - customer.created
                      - customer.updated
                      - recipient.created
                      - recipient.updated
                      - recipient.approved
                      - recipient.refused
                      - recipient.deleted
                      - recipient.pendency_updated
                      - withdrawal.requested
                      - withdrawal.paid
                      - withdrawal.rejected
                      - invoice.issued
                      - invoice.payment_attempted
                      - invoice.paid
                      - invoice.voided
                      - invoice.refunded
                      - invoice.rescheduled
                      - subscription.created
                      - subscription.trial_started
                      - subscription.activated
                      - subscription.canceled
                      - subscription.cycle_advanced
                      - subscription.paused
                      - subscription.resumed
                      - subscription.past_due
                      - subscription.unpaid
                      - subscription.restored
                      - subscription.reactivated
                      - anticipation.status_changed
                  default: []
                  description: >-
                    Eventos que disparam notificações para este webhook (ex.:
                    transaction.paid, payment.refunded).
                secret:
                  type: string
                  minLength: 8
                  description: >-
                    Segredo usado para assinar (HMAC) os payloads e validar a
                    autenticidade das notificações.
              required:
                - name
                - url
      responses:
        '201':
          description: Webhook criado
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Identificador único do registro.
                  name:
                    type: string
                    description: Nome do registro.
                  url:
                    type: string
                    format: uri
                    description: URL de destino do webhook ou link de download do arquivo.
                  events:
                    type: array
                    items:
                      type: string
                    description: Tipos de evento assinados pelo webhook.
                  isActive:
                    type: boolean
                    description: Indica se o registro está ativo.
                  hasSecret:
                    type: boolean
                  secretHint:
                    type: string
                    nullable: true
                  autoDisabledAt:
                    type: string
                    format: date-time
                    nullable: true
                  createdAt:
                    type: string
                    format: date-time
                    description: Data e hora de criação do registro (ISO 8601).
                  updatedAt:
                    type: string
                    format: date-time
                    description: Data e hora da última atualização do registro (ISO 8601).
                  secret:
                    type: string
                    nullable: true
                    description: Segredo usado para assinar as entregas do webhook.
                required:
                  - id
                  - name
                  - url
                  - events
                  - isActive
                  - hasSecret
                  - secretHint
                  - autoDisabledAt
                  - createdAt
                  - updatedAt
                  - secret
        '400':
          description: >-
            Requisição inválida — algum parâmetro ou campo do corpo não passou
            na validação
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
                      issues:
                        type: array
                        description: >-
                          Um item por campo rejeitado. Nunca vem vazio: se há
                          400 de validação, há pelo menos um.
                        items:
                          type: object
                          properties:
                            path:
                              type: string
                              description: >-
                                Campo que falhou. Vem vazio quando o erro é do
                                corpo como um todo.
                            message:
                              type: string
                              description: O que há de errado com esse campo.
              example:
                error:
                  code: VALIDATION_ERROR
                  message: Validation failed
                  issues:
                    - path: status
                      message: >-
                        Status inválido. Valores aceitos: pending,
                        waiting_payment, paid, refused, canceled, refunded
                    - path: startDate
                      message: >-
                        Data deve ser ISO 8601 com timezone (ex.:
                        2026-06-24T00:00:00Z)
        '401':
          description: Chave de API ausente, malformada ou inválida
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
              example:
                error:
                  code: UNAUTHORIZED
                  message: Invalid API key
        '409':
          description: >-
            Já existe uma requisição em andamento com esta Idempotency-Key. A
            API aguarda a primeira concluir por até 5 segundos antes de
            responder assim
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: >-
                      Mensagem do conflito de idempotência. Aqui `error` é
                      texto, não objeto — ramifique pelo status HTTP.
              example:
                error: A request with this idempotency key is already being processed
        '422':
          description: >-
            Idempotency-Key já usada com um corpo diferente. Use uma chave nova
            para uma operação diferente
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: >-
                      Mensagem do conflito de idempotência. Aqui `error` é
                      texto, não objeto — ramifique pelo status HTTP.
              example:
                error: Idempotency key already used with a different request body
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: API Key da Credential (gerada no Backoffice)

````