Webhook#
Neste guia, abordaremos os webhooks que são enviados pelo Pluggy para criar uma integração reativa a mudanças. Isso abrangerá tanto integrações de dados quanto de pagamentos.
Um Webhook é uma ferramenta que permite que você receba uma notificação para um determinado evento. Ele permite que você configure uma URL HTTPS em nossa plataforma para certos eventos, e você receberá um evento JSON POST nessa URL, com dados específicos do evento.
Para se inscrever em eventos de Webhook, você pode:
- Criar uma instância de Webhook diretamente, ou
- Especificar o parâmetro
webhookUrl(com uma URL HTTPS válida), ao:- criar um Item,
- criar um Connect Token, ou
- criar uma Solicitação de Pagamento
Se você criar uma instância de Webhook diretamente, estará se inscrevendo para todos os casos de eventos do tipo de evento especificado. Em vez disso, se você fizer isso especificando o webhookUrl ao criar um Item ou criar um Connect Token, você será notificado sobre todos os eventos, mas apenas relacionados a esse recurso específico. Que é, ou a esse Item especificamente, ou aos itens relacionados criados usando esse Connect Token.
Eventos de Dados#
Apoiamos o registro para os seguintes eventos ao consumir os endpoints de dados do Pluggy.
| Evento | Descrição |
|---|---|
item/created | Um item foi criado e terminou de se conectar com sucesso. |
item/updated | Um item foi atualizado e sincronizado com sucesso. |
item/deleted | Um item foi excluído com sucesso. |
item/error | Um item encontrou erros em sua execução. O caso de USER_AUTHORIZATION_PENDING também acionará este evento. |
item/waiting_user_input | Um item está bloqueado aguardando a entrada do usuário para continuar. |
item/waiting_user_action | Um item está bloqueado aguardando o usuário aprovar uma ação em seu dispositivo (por exemplo, autorizar acesso no aplicativo bancário ou escanear um código QR). |
item/login_succeeded | Um item fez login com sucesso no provedor e está coletando os dados. |
connector/status_updated | Um conector mudou de status (ONLINE/UNSTABLE/OFFLINE). Este evento informa o ID do conector afetado e o status atualizado. Verifique o endpoint de Conectores para ver todos os conectores e seus IDs. |
transactions/deleted | IDs de transações excluídas após mesclar dados na atualização do item. |
transactions/created | Receba este evento de webhook e use a página createdTransactionsLink para acessar todas as transações disponíveis e inseri-las em sua fonte de dados. |
transactions/updated | IDs de transações atualizadas após mesclar dados na atualização do item. Após receber este webhook, é recomendável obter os dados completos das transações usando o endpoint de transações com o parâmetro ids. |
Note
Os webhooks de transações são acionados apenas quando há uma mudança de dados. Se não houver transações, não será acionado um evento transactions/created.
Eventos de Pagamento#
Apoiamos o registro para os seguintes eventos ao consumir os endpoints de pagamento do Pluggy.
Intenção de Pagamento#
| Evento | Descrição |
|---|---|
payment_intent/created | ID da intenção de pagamento criada pelo usuário, com paymentRequestId. |
payment_intent/completed | ID da intenção de pagamento concluída com sucesso pelo usuário, com paymentRequestId. |
payment_intent/waiting_payer_authorization | ID da intenção de pagamento quando precisa de autorização adicional. |
payment_intent/error | ID da intenção de pagamento quando ocorre um erro durante o fluxo, com paymentRequestId. |
payment_request/updated | O status da solicitação de pagamento foi alterado. |
Pagamento Agendado#
| Evento | Descrição |
|---|---|
scheduled_payment/created | IDs da autorização de pagamento agendado. |
scheduled_payment/completed | Um único pagamento da autorização foi realizado. |
scheduled_payment/error | Pagamento não concluído, finalizado com erro. |
scheduled_payment/canceled | Pagamento cancelado pelo usuário ou pelo cliente. |
Pagamento PIX Automático#
| Evento | Descrição |
|---|---|
automatic_pix_payment/created | Um pagamento foi agendado para uma solicitação de pagamento PIX automático. |
automatic_pix_payment/completed | Um pagamento agendado associado a uma solicitação de pagamento PIX automático foi concluído com sucesso. |
automatic_pix_payment/error | Um pagamento agendado associado a uma solicitação de pagamento PIX automático terminou com erro. |
automatic_pix_payment/canceled | Um pagamento agendado associado a uma solicitação de pagamento PIX automático foi cancelado. |
Transferência Inteligente#
| Evento | Descrição |
|---|---|
smart_transfer_preauthorization/completed | Uma pré-autorização de transferência inteligente foi aprovada por um usuário. |
smart_transfer_preauthorization/error | Ocorreu um erro durante a aprovação da pré-autorização de transferência inteligente. Por exemplo, quando o usuário rejeita o consentimento. |
smart_transfer_payment/completed | Um pagamento de transferência inteligente foi concluído. |
smart_transfer_payment/error | Ocorreu um erro ao liquidar o pagamento de transferência inteligente. Por exemplo, quando a conta não tem saldo suficiente. |
Para se registrar em um evento específico, você terá que enviar o evento desejado para ouvir apenas aqueles eventos de webhook.
Alternativamente, você pode apenas usar a opção all para receber todos os eventos associados.
Aceitamos apenas URLs HTTPS. URLs localhost não são permitidas; você terá que fornecer uma URL HTTPS usando ngrok ou outras ferramentas para fornecer URLs públicas e seguras.
Dica
Para testar essa funcionalidade, você pode usar RequestCatcher, que é uma ferramenta que apenas receberá nossa notificação e mostrará o payload. Você pode facilmente criar um catcher com apenas um nome em segundos.
Parâmetros do Payload#
Ao fazer a solicitação POST, todos os webhooks enviarão os seguintes parâmetros em formato JSON:
- event: nome do evento (
item/created,item/updated,item/error, etc.) - eventId: identificador do evento em si. Deve ser o mesmo para um evento quando enviado para muitos endpoints.
- triggeredBy: quem acionou o evento (para todos os eventos, exceto
item/deleted,connector/status_updatedetransactions/deleted). Valores possíveis:USER: um usuário final acionou o evento com um Connect Token (por exemplo, do Pluggy Connect)CLIENT: um cliente acionou o evento com uma Chave de API (por exemplo, executando PATCH em um Item)SYNC: Auto-sync acionou o eventoINTERNAL: Foi acionado por alguém da equipe de suporte do Pluggy
Dependendo do tipo de evento, o ID da entidade é enviado. Por exemplo, para itens, itemId. Em transações, transactionIds, e em conectores, connectorId.
clientUserId é enviado apenas em eventos item/*#
clientUserId -- o identificador que você definiu ao criar o Connect Token -- está incluído no payload de cada evento item/*: item/created, item/updated, item/error, item/deleted, item/login_succeeded, item/waiting_user_input e item/waiting_user_action.
Não está não incluído em eventos transactions/*. Esses payloads carregam itemId, accountId e os campos da transação, mas não clientUserId. Para atribuir um evento de transação a um usuário final, mantenha seu próprio mapeamento itemId -> usuário (que você já tem do evento item/created ou do callback onSuccess do widget) e resolva a partir de itemId.
Se `clientUserId` chegar como `null` em eventos `item/*`
A causa usual é que foi enviado na raiz do corpo do POST /connect_token em vez de dentro de options. A API descarta propriedades desconhecidas da raiz e ainda retorna 200, então o valor nunca chega ao Item. Veja Configurando um Connect Token. Você pode preencher os Itens afetados com PATCH /items/API.
Exemplos de Item#
item/created:
{
"event": "item/created",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}item/updated:
{
"event": "item/updated",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}item/deleted:
{
"event": "item/deleted",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}item/error:
{
"event": "item/error",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "d161a74a-8bc8-4093-88de-724312969b0d",
"error": {
"code": "USER_INPUT_TIMEOUT",
"message": "A entrada solicitada pelo usuário expirou",
"parameter": "token"
},
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}item/waiting_user_input:
{
"event": "item/waiting_user_input",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "d038aaa6-35f2-4f06-8b8a-c464a4a61fc2",
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}item/waiting_user_action:
{
"event": "item/waiting_user_action",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "d038aaa6-35f2-4f06-8b8a-c464a4a61fc2",
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}item/login_succeeded:
{
"event": "item/login_succeeded",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
"triggeredBy": "USER",
"clientUserId": "client-user-id"
}Exemplos de Conector#
connector/status_updated:
{
"id": "201",
"event": "connector/status_updated",
"eventId": "4552bee0-b87f-48b5-896b-c23113839319",
"connectorId": "201",
"data": {
"status": "UNSTABLE"
}
}Exemplos de Transação#
transactions/deleted:
{
"event": "transactions/deleted",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
"accountId": "8a6e2c17-2817-40bb-b03d-546febc6a60a",
"transactionIds": [
"5a14feae-eaa7-423a-820c-6b83837c35b7",
"786c7d98-6085-4879-9c7f-2255260e2436"
]
}transactions/updated:
{
"event": "transactions/updated",
"eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
"itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
"accountId": "8a6e2c17-2817-40bb-b03d-546febc6a60a",
"transactionIds": [
"5a14feae-eaa7-423a-820c-6b83837c35b7",
"786c7d98-6085-4879-9c7f-2255260e2436"
]
}transactions/created:
{
"itemId": "de7bbf5a-abf2-47e4-94b1-586b36758423",
"event": "transactions/created",
"id": "de7bbf5a-abf2-47e4-94b1-586b36758423",
"eventId": "4e69d62d-b7c8-4f01-b591-a1d8a94710b9",
"accountId": "0d5a0de2-9c82-4ea2-af50-31643a632a33",
"transactionsCount": 332,
"transactionsMinDate": "2025-02-12T15:00:01.000Z",
"transactionsCreatedAtFrom": "2025-02-13T17:21:53.719Z",
"createdTransactionsLink": "https://api.pluggy.ai/transactions?accountId=0d5a0de2-9c82-4ea2-af50-31643a632a33&createdAtFrom=2025-02-13T17:21:53.719Z"
}Exemplos de Intenção de Pagamento#
payment_intent/created:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"paymentIntentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"event": "payment_intent/created",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0"
}payment_intent/completed:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"paymentIntentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"event": "payment_intent/completed",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"referenceId": "E33371172200009110200U70a27b2698"
}payment_intent/error:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"paymentIntentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"event": "payment_intent/error",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"referenceId": "E33371172200009110200U70a27b2698",
"error": {
"code": "REJECTED_BY_USER",
"description": "O consentimento foi rejeitado pelo usuário.",
"detail": "O usuário rejeitou a autorização do consentimento"
}
}Exemplos de Solicitação de Pagamento#
payment_request/updated:
{
"event": "payment_request/updated",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6",
"clientId": "client-123",
"status": "CANCELED"
}Exemplos de Pagamentos Agendados#
scheduled_payment/created:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"scheduledPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "scheduled_payment/created"
}scheduled_payment/completed:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"scheduledPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "scheduled_payment/completed"
}scheduled_payment/error:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"scheduledPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "scheduled_payment/error",
"error": {
"title": "Título do erro",
"code": "Código do Erro",
"description": "Descrição do erro"
}
}scheduled_payment/canceled:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"scheduledPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "scheduled_payment/canceled"
}Exemplos de Pagamentos PIX Automáticos#
automatic_pix_payment/created:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"automaticPixPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"endToEndId": "E37943755202506111319U0da92d1b7e",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "automatic_pix_payment/created"
}automatic_pix_payment/completed:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"automaticPixPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"endToEndId": "E37943755202506111319U0da92d1b7e",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "automatic_pix_payment/completed"
}automatic_pix_payment/error:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"automaticPixPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"endToEndId": "E37943755202506111319U0da92d1b7e",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "automatic_pix_payment/error",
"error": {
"title": "Título do erro",
"code": "Código do Erro",
"description": "Descrição do erro"
}
}automatic_pix_payment/canceled:
{
"paymentRequestId": "624cb41e-2b76-42ac-8021-ce6b6b4ace6b",
"automaticPixPaymentId": "8429f45a-f541-4fc3-8439-cbc8d9dc9952",
"endToEndId": "E37943755202506111319U0da92d1b7e",
"eventId": "71e0b4db-4e8c-401d-8ad8-5ab3ecd1f3d0",
"event": "automatic_pix_payment/canceled"
}Exemplos de Transferências Inteligentes#
smart_transfer_preauthorization/completed:
{
"clientId": "65a8c757-ef2c-4bc3-94ed-99218f6a0ee8",
"event": "smart_transfer_preauthorization/completed",
"eventId": "8013240b-7c0a-409e-bf00-7fc586cc9196",
"smartTransferPreauthorizationId": "f84e6e06-e0f9-4ab3-89f2-da062be65e7c",
"status": "COMPLETED"
}smart_transfer_preauthorization/error:
{
"clientId": "65a8c757-ef2c-4bc3-94ed-99218f6a0ee8",
"event": "smart_transfer_preauthorization/error",
"eventId": "54ceeb25-b9f7-4b90-8124-0cff66d1b2c3",
"smartTransferPreauthorizationId": "3dd45002-52aa-44e8-a206-f6b99a293d9a",
"status": "REJECTED",
"error": {
"code": "REJECTED_BY_USER",
"description": "O consentimento foi rejeitado pelo usuário.",
"detail": "O usuário rejeitou a autorização do consentimento"
}
}smart_transfer_payment/completed:
{
"clientId": "65a8c757-ef2c-4bc3-94ed-99218f6a0ee8",
"event": "smart_transfer_payment/completed",
"eventId": "0dfa6e5d-aee4-42b6-bd3b-e27e9c591339",
"smartTransferPreauthorizationId": "f84e6e06-e0f9-4ab3-89f2-da062be65e73",
"smartTransferPaymentId": "2afc828e-0dc2-4195-a774-145f7d7fc46c",
"status": "PAYMENT_COMPLETED"
}smart_transfer_payment/error:
{
"clientId": "65a8c757-ef2c-4bc3-94ed-99218f6a0ee6",
"event": "smart_transfer_payment/error",
"eventId": "59ff7a4a-d804-499b-a31c-7865014ba0ef",
"smartTransferPreauthorizationId": "f84e6e06-e0f9-4ab3-89f2-da062be65e73",
"smartTransferPaymentId": "b546ab61-f1cd-4cd4-b5bf-0073d9a9ee3a",
"status": "PAYMENT_REJECTED",
"error": {
"code": "INSUFFICIENT_BALANCE",
"description": "A conta não tem saldo suficiente para realizar o pagamento.",
"detail": "Saldo insuficiente."
}
}Tratamento de notificações#
Quando enviamos uma notificação de webhook, uma de duas coisas acontece:
- Sua API responde com um status
2XXdentro de 10 segundos → sucesso - Sua API responde com qualquer outro status, ou não responde dentro de 10 segundos → falha
Cronograma de Tentativas#
Tentamos entregar cada webhook até 3 vezes:
| Tentativa | Quando |
|---|---|
| 1ª | Imediatamente |
| 2ª | ~15 minutos após a 1ª tentativa falhar |
| 3ª | ~2 horas após a 2ª tentativa falhar |
Se a 3ª tentativa falhar, a notificação não será entregue novamente automaticamente.
Respostas que não tentamos novamente#
Algumas respostas nos dizem que a solicitação nunca terá sucesso como enviada. Nesses casos, paramos após a primeira tentativa e não agendamos novas tentativas:
400 · 401 · 403 · 404 · 405
Qualquer outro resultado que não seja 2XX é tratado como temporário e recebe o cronograma completo de 3 tentativas acima, incluindo 408, 429, qualquer 5XX, erros de conexão e timeouts.
Caution
Se seu endpoint responder 400 enquanto está temporariamente quebrado — um bug ao analisar o payload, um deploy que deixa seu manipulador rejeitando solicitações válidas — essas notificações são descartadas após uma única tentativa e não voltarão por conta própria. Retorne um 5XX para problemas temporários ou inesperados do lado do servidor, e reserve 4XX para solicitações que você nunca aceitará.
Exceção: eventos de item sensíveis ao tempo
item/waiting_user_input e item/login_succeeded são sensíveis ao tempo: eles recebem 3 tentativas espaçadas em cerca de 6 minutos, e nunca usam o cronograma de 15 minutos / 2 horas. Após a 3ª tentativa, não são tentados novamente.
Se todas as tentativas falharem#
Você pode tentar uma notificação manualmente a partir do Dashboard. Uma tentativa manual inicia um novo ciclo de até 3 tentativas, ~15 minutos de intervalo. A regra acima ainda se aplica: se seu endpoint continuar respondendo 400, 401, 403, 404 ou 405, a tentativa manual também para após uma tentativa — então conserte o endpoint primeiro, depois tente novamente.
Respondendo a notificações#
É obrigatório que sua API retorne 2XX logo após receber uma notificação, e então faça seu processamento após responder ao Pluggy. Dessa forma, se seu processamento levar mais de 10 segundos, não interpretaremos isso como uma falha, evitando assim tentativas indesejadas da mesma notificação.
Para todas as notificações de itens, esperamos que a primeira coisa que você faça ao processar o evento seja fazer um GET /items/{id} para recuperar as informações mais recentes relacionadas ao evento, em vez de processar a partir dos dados do payload do evento.
Whitelist dos IPs do Pluggy
Se você deseja adicionar medidas de segurança extras para fornecer filtragem de IP para nossas solicitações, deve colocar na lista branca os seguintes IPs:
52.67.145.81
Cabeçalhos do Webhook#
Ao criar um webhook, você pode especificar um objeto headers para enviar cabeçalhos específicos em suas notificações de webhook. Isso pode ser útil, por exemplo, se sua URL de webhook estiver protegida com uma Chave de API. Você pode adicionar cabeçalhos ao seu webhook assim:
{
"url": "example.com",
"event": "all",
"headers": {
"Authorization": "Minha chave de API",
"X-CLIENT-ID": "Alguma informação extra secreta"
}
}Apenas API
Os cabeçalhos do webhook atualmente só podem ser configurados via API, pois podem conter dados sensíveis a serem expostos em nosso dashboard.
Para mais informações, veja Webhook em nossa referência da API.
