Looking for the previous documentation?Go to v1.docs.pluggy.ai

Detecting authentication failures

There is no dedicated webhook event for a failed bank login. `item/error` is the event, and its `error.code` tells you whether the user has to re-enter credentials, authorise on their device, or just wait.

View as Markdown

Which event do I need?#

item/error. There is no separate event for an authentication problem: every execution that finishes in an error state — including one that failed at the login step — is delivered as item/error. The full event list is in Webhook; nothing else in it is auth-specific.

Register it like any other event:

http
POST https://api.pluggy.ai/webhooks
X-API-KEY: {apiKey}
Content-Type: application/json
 
{
  "url": "https://example.com/pluggy",
  "event": "item/error"
}

There is no per-product wildcard. If you want every Item event on one endpoint, register all instead of one webhook per event.

Telling the failures apart#

The notification carries an error object, and its code is the same value the Item exposes as executionStatus:

json
{
  "event": "item/error",
  "eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
  "itemId": "d161a74a-8bc8-4093-88de-724312969b0d",
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Invalid credentials"
  },
  "triggeredBy": "SYNC",
  "clientUserId": "your-user-id"
}

The codes that mean "the connection could not authenticate" are:

error.codeWhat it meansWhat the end user has to do
INVALID_CREDENTIALSThe credentials were rejected by the institution.Re-enter credentials. The Item's status becomes LOGIN_ERROR and it is no longer auto-synced until new credentials are provided.
INVALID_CREDENTIALS_MFAThe second login step failed: wrong or expired MFA token.Start a new connection attempt and submit a fresh token.
USER_INPUT_TIMEOUTThe MFA token was never submitted in time.Start again and submit the token within the window.
ALREADY_LOGGED_INThe institution refused a new session because one is already active.Close the open session at the institution, then retry.
ACCOUNT_LOCKEDThe account is locked at the institution.Contact the institution to unlock it.
ACCOUNT_CREDENTIALS_RESETThe institution is forcing a credentials reset (expired password, new security policy).Reset the password at the institution, then reconnect.
ACCOUNT_NEEDS_ACTIONThe institution is blocking data collection until the user does something (accept new terms, complete a profile).Resolve it at the institution, then retry.
USER_AUTHORIZATION_NOT_GRANTEDDevice authorisation was not granted to the connector.Authorise the device in the bank app and reconnect.
USER_AUTHORIZATION_REVOKEDThe user revoked data sharing at the institution.Re-consent — this creates a new connection.
USER_NOT_SUPPORTEDThe kind of account the user is connecting is not supported for that connector.Use a supported account type.

Every value, including the non-authentication ones, is described in Item lifecycle.

`USER_AUTHORIZATION_PENDING` also arrives as `item/error`

It is an intermediate state, not a failure: the user has to authorise on their device or at the institution, and Pluggy resumes the collection by itself a few minutes later. Treat this code as "waiting", not as "broken", or you will ask the user to reconnect a connection that was about to succeed.

The `error` object can be absent

When the failure happened inside Pluggy while storing already-collected data, the item/error event still fires but carries no error object — that internal code is not exposed on client-facing surfaces. Handle a missing error without crashing, and read the Item's executionStatus with GET /items/{id}API when you need the detail.

What is not an error#

Two events look like failures and are not:

  • item/waiting_user_input — the connector is asking for an MFA token. The login succeeded; the execution is suspended until the token is sent with POST /items/{id}/mfaAPI.
  • item/waiting_user_action — the user must act on their device (approve in the bank app, scan a QR code).

Neither ends the execution, so neither should trigger a "your bank connection failed" message to your user.

Getting the itemId#

itemId is in the payload of every item/* event, and so is the clientUserId you set when creating the Connect Token — those two fields are all you need to map the failure to one of your users, with no extra API call.

If you never stored the itemId in the first place, see I lost an itemId. How do I find it again? — listing items is opt-in per team, so the reliable path is to persist the itemId from the widget's onSuccess callback or the item/created webhook.

Reacting to it#

  1. Look up your user through clientUserId (or your own itemId mapping).
  2. If the code is one of the credential errors above, prompt the user to reconnect. Re-sending the same credentials to an Item in LOGIN_ERROR without the user re-entering them will fail again.
  3. Update the existing Item rather than creating a new one — see Updating an Item. A new connection means a new itemId and a fresh history.

Answer the webhook with a 2xx within 10 seconds and process asynchronously; a slow handler counts as a failure and is retried. The retry schedule is in Webhook.

Was this page helpful?