# Detectando falhas de autenticação

## Qual evento eu preciso?

**`item/error`.** Não há um evento separado para um problema de autenticação: toda
execução que termina em um estado de erro — incluindo uma que falhou na etapa de
login — é entregue como `item/error`. A lista completa de eventos está em
[Webhook](/docs/developer-tools/webhooks-ref#data-events); nada mais nela é
específico de autenticação.

Registre-o como qualquer outro evento:

```http
POST https://api.pluggy.ai/webhooks
X-API-KEY: {apiKey}
Content-Type: application/json

{
  "url": "https://example.com/pluggy",
  "event": "item/error"
}
```

Não há um curinga por produto. Se você quiser cada evento de Item em um único endpoint,
registre `all` em vez de um webhook por evento.

## Distinguindo as falhas

A notificação carrega um objeto `error`, e seu `code` é o mesmo valor que o
Item expõe como `executionStatus`:

```json
{
  "event": "item/error",
  "eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
  "itemId": "d161a74a-8bc8-4093-88de-724312969b0d",
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Credenciais inválidas"
  },
  "triggeredBy": "SYNC",
  "clientUserId": "seu-id-de-usuario"
}
```

Os códigos que significam "a conexão não pôde autenticar" são:

| `error.code` | O que significa | O que o usuário final deve fazer |
| --- | --- | --- |
| `INVALID_CREDENTIALS` | As credenciais foram rejeitadas pela instituição. | Reinsira as credenciais. O `status` do Item se torna `LOGIN_ERROR` e ele **não será mais sincronizado automaticamente** até que novas credenciais sejam fornecidas. |
| `INVALID_CREDENTIALS_MFA` | A segunda etapa de login falhou: token MFA incorreto ou expirado. | Inicie uma nova tentativa de conexão e envie um token novo. |
| `USER_INPUT_TIMEOUT` | O token MFA nunca foi enviado a tempo. | Comece novamente e envie o token dentro do prazo. |
| `ALREADY_LOGGED_IN` | A instituição recusou uma nova sessão porque uma já está ativa. | Feche a sessão aberta na instituição e tente novamente. |
| `ACCOUNT_LOCKED` | A conta está bloqueada na instituição. | Entre em contato com a instituição para desbloqueá-la. |
| `ACCOUNT_CREDENTIALS_RESET` | A instituição está forçando um reset de credenciais (senha expirada, nova política de segurança). | Redefina a senha na instituição e reconecte. |
| `ACCOUNT_NEEDS_ACTION` | A instituição está bloqueando a coleta de dados até que o usuário faça algo (aceitar novos termos, completar um perfil). | Resolva isso na instituição e tente novamente. |
| `USER_AUTHORIZATION_NOT_GRANTED` | A autorização do dispositivo não foi concedida ao conector. | Autorize o dispositivo no aplicativo do banco e reconecte. |
| `USER_AUTHORIZATION_REVOKED` | O usuário revogou o compartilhamento de dados na instituição. | Reconsente — isso cria uma nova conexão. |
| `USER_NOT_SUPPORTED` | O tipo de conta que o usuário está conectando não é suportado para esse conector. | Use um tipo de conta suportado. |

Cada valor, incluindo os não relacionados à autenticação, é descrito em
[Item lifecycle](/docs/connections/item-lifecycle#final-states).

<Callout variant="info" title="`USER_AUTHORIZATION_PENDING` também chega como `item/error`">
É um estado **intermediário**, não uma falha: o usuário precisa autorizar em
seu dispositivo ou na instituição, e a Pluggy retoma a coleta sozinha alguns
minutos depois. Trate esse código como "aguardando", não como "quebrado", ou você pedirá
ao usuário para reconectar uma conexão que estava prestes a ter sucesso.
</Callout>

<Callout variant="warning" title="O objeto `error` pode estar ausente">
Quando a falha ocorreu dentro da Pluggy ao armazenar dados já coletados, o
evento `item/error` ainda é acionado, mas não carrega um objeto `error` — esse código interno
não é exposto em superfícies voltadas para o cliente. Lide com a ausência de `error` sem
quebrar, e leia o `executionStatus` do Item com
[`GET /items/{id}`](/reference/items-retrieve) quando precisar do detalhe.
</Callout>

## O que *não* é um erro

Dois eventos parecem falhas e não são:

- **`item/waiting_user_input`** — o conector está pedindo um token MFA. O
  login foi bem-sucedido; a execução está suspensa até que o token seja enviado com
  [`POST /items/{id}/mfa`](/reference/items-send-mfa).
- **`item/waiting_user_action`** — o usuário deve agir em seu dispositivo (aprovar no
  aplicativo do banco, escanear um código QR).

Nenhum deles encerra a execução, portanto, nenhum deve acionar uma mensagem de "sua conexão bancária
falhou" para o seu usuário.

## Obtendo o `itemId`

`itemId` está no payload de cada evento `item/*`, assim como o `clientUserId`
que você definiu ao [criar o Connect Token](/docs/authentication) — esses dois
campos são tudo o que você precisa para mapear a falha a um de seus usuários, sem chamada
API extra.

Se você nunca armazenou o `itemId` em primeiro lugar, veja
[Eu perdi um itemId. Como posso encontrá-lo novamente?](/docs/get-started/faq) — listar
itens é opt-in por equipe, então o caminho confiável é persistir o `itemId` do
callback `onSuccess` do widget ou do webhook `item/created`.

## Reagindo a isso

1. Procure seu usuário através do `clientUserId` (ou seu próprio mapeamento de `itemId`).
2. Se o código for um dos erros de credenciais acima, peça ao usuário para
   reconectar. Reenviar as mesmas credenciais para um Item em `LOGIN_ERROR` sem
   que o usuário as reinsira falhará novamente.
3. Atualize o Item existente em vez de criar um novo — veja
   [Atualizando um Item](/docs/connect-widget/updating-item). Uma nova conexão significa
   um novo `itemId` e um histórico fresco.

Responda ao webhook com um `2xx` **dentro de 10 segundos** e processe de forma assíncrona;
um manipulador lento conta como uma falha e será refeito. O cronograma de tentativas está em
[Webhook](/docs/developer-tools/webhooks-ref#handling-notifications).