When a payer links an account on the payment page, Pluggy stores an enrollment: the link between their account at one institution and the device and browser where they created the passkey. Enrollments are created only by the payer, during a payment. Through the API you can list them, read them, see the payments made with them and revoke them.
Every endpoint on this page only returns your own client's enrollments.
The enrollment#
{
"id": "c91a5e2b-7d0f-4f3e-9a51-2f6b8e1d4c77",
"status": "AUTHORIZED",
"connector": {
"id": 608,
"name": "Santander",
"imageUrl": "https://cdn.pluggy.ai/assets/connector-icons/208.svg"
},
"debtor": {
"name": "John Doe",
"taxNumber": "***.456.789-**",
"bankAccount": {
"agency": "1234",
"account": "****4821",
"name": "Santander"
}
},
"cpf": "***.456.789-**",
"cnpj": null,
"customerId": "a2d4c1e8-5b7f-4c3a-9e2d-1f6b8c0d7e55",
"limits": {
"transaction": 1000,
"daily": 3000,
"dailyUsed": 149.9
},
"expiresAt": "2027-10-28T13:05:00.000Z",
"dataConsent": null,
"revokedBy": null,
"errorDetail": null,
"createdAt": "2026-10-28T13:02:00.000Z",
"updatedAt": "2026-10-28T13:05:00.000Z"
}| Field | Description |
|---|---|
id | The enrollment id. Payment intents reference it as enrollmentId. |
status | See the table below. |
connector | The institution where the account is held. |
debtor | The linked account, as the institution reported it. The tax number and the account number are masked. |
cpf / cnpj | The payer's tax number, masked. Use the unmasked value to filter the list. |
customerId | The Payment Customer of the payment request where the link was created, or null when the payer typed their CPF. |
limits | The per-payment (transaction) and daily limits the payer set at the bank, and how much of today's limit is used (dailyUsed), in BRL. Any of them can be null when the institution does not report it. |
expiresAt | When the link expires, as set by the institution. |
dataConsent | The balance-sharing permission, or null when it was not requested. See Sharing balance. |
revokedBy | Who revoked the link: BANK (the payer or the institution, at the bank) or CLIENT (you, through the API). null unless status is REVOKED. |
errorDetail | { code, description } with the reason the institution gave when the link was rejected, for example because the payer did not complete it in time. Otherwise null. |
status | Meaning |
|---|---|
CREATED | The payer started linking and has not finished: they are at the bank or creating the passkey. |
AUTHORIZED | The link is active. Payments on that device need only biometrics. |
REJECTED | The link was not completed: the institution or the payer rejected it, or the payer did not finish in time. errorDetail says which. |
REVOKED | The link was revoked at the bank or through the API. |
EXPIRED | The link reached its expiration date or became inactive at the institution. |
REJECTED, REVOKED and EXPIRED are final. To pay with biometrics again, the payer links again, which creates a new enrollment.
List enrollments#
GET /pix-biometric/enrollments?customerId={customerId}&status=AUTHORIZED
| Query parameter | Description |
|---|---|
customerId | Enrollments created in payment requests for this Payment Customer. |
cpf | The payer's CPF, digits only. |
cnpj | The payer's CNPJ, digits only. |
status | One of the statuses above. |
page / pageSize | Pagination. pageSize is at most 500. |
The response uses the usual pagination:
{
"total": 1,
"totalPages": 1,
"page": 1,
"results": [
{
"id": "c91a5e2b-7d0f-4f3e-9a51-2f6b8e1d4c77",
"status": "AUTHORIZED"
}
]
}A payer can have several enrollments: one per device and browser, and one per institution they linked. See the API referenceAPI.
Retrieve an enrollment#
GET /pix-biometric/enrollments/{id}
Returns the enrollment, refreshed from the institution, so a link revoked at the bank shows up as REVOKED here even before the webhook arrives. An id that does not exist for your client answers 404 with PIX_BIOMETRIC_ENROLLMENT_NOT_FOUND. See the API referenceAPI.
Payments made with an enrollment#
GET /payments/intents?enrollmentId={id}
Lists the payment intents made with that link, with the usual pagination. Each one carries its paymentRequest, so you can tell which purchases the payer made with it. See the API referenceAPI.
Revoke an enrollment#
POST /pix-biometric/enrollments/{id}/revoke
No body. The link is revoked at the institution and the enrollment is returned with status: "REVOKED" and revokedBy: "CLIENT". You also get a pix_biometric_enrollment/revoked webhook. If the payer was still completing their first payment with that link, that payment intent fails.
Revoking cannot be undone: the payer has to link again to pay with biometrics. Revoking an enrollment that is already REJECTED, REVOKED or EXPIRED returns it unchanged, so retrying is safe. See the API referenceAPI.
The payer can also undo the link at any time in their bank's app. You learn about it through the pix_biometric_enrollment/revoked webhook, and the enrollment then shows revokedBy: "BANK".
Sharing balance#
When the payment request was created with linkedJourney: true, the payer can also share their account balance and overdraft limit with you, in the same approval at the bank. It is optional for the payer and lasts as long as the link. Read the balance right before charging, to avoid a payment rejected for insufficient funds.
The enrollment carries the permission in dataConsent:
{
"status": "AUTHORISED",
"rejectionReason": null,
"updatedAt": "2026-10-28T13:05:00.000Z"
}dataConsent.status | Meaning |
|---|---|
AWAITING_AUTHORISATION | The payer has not approved yet. |
AUTHORISED | The balance can be read. |
REJECTED | The payer or the institution rejected it. rejectionReason says why. |
REVOKED | The permission was cancelled. |
dataConsent is null when the request did not ask for it, or the payer chose not to share.
Read the balance#
GET /pix-biometric/enrollments/{id}/balance
Reads the balance in real time from the institution. Amounts are in BRL. See the API referenceAPI.
{
"balance": 5.48,
"overdraft": {
"contracted": 1000,
"used": 0,
"available": 1000
}
}overdraft is the account's overdraft limit: how much was contracted, how much is in use and how much is still available. It is null when the institution does not share it.
| Status | codeDescription | Meaning |
|---|---|---|
200 | Balance read. | |
403 | PIX_BIOMETRIC_DATA_CONSENT_NOT_AVAILABLE | The link is not AUTHORIZED, or the payer did not share the balance, or the permission was cancelled. |
429 | PIX_BIOMETRIC_RATE_LIMITED | The institution's rate limit is reached, for example the account's monthly balance quota. |
Every call counts toward the institution's quota
Each call reads the balance from the institution, with no cache. Open Finance limits balance reads per account per month (see Operational Rate Limits). Read the balance right before a payment, not on a schedule.
Stop sharing the balance#
DELETE /pix-biometric/enrollments/{id}/data-consent
Cancels only the balance permission: the link stays AUTHORIZED and payments keep working. It returns the enrollment with dataConsent.status set to REVOKED. Cancelling a permission that already ended returns the enrollment unchanged, so retrying is safe. A link created without the permission answers 403 with PIX_BIOMETRIC_DATA_CONSENT_NOT_AVAILABLE. See the API referenceAPI.
Revoking the link also ends the balance permission. A permission cannot be added to an existing link: the payer links again from a payment request created with linkedJourney: true.
Webhooks#
| Event | When |
|---|---|
pix_biometric_enrollment/authorized | The payer completed a link. |
pix_biometric_enrollment/revoked | The link was revoked, at the bank or through the API. |
pix_biometric_enrollment/error | The link was not completed: it was rejected, or ended before the payer finished it. |
{
"event": "pix_biometric_enrollment/authorized",
"eventId": "8013240b-7c0a-409e-bf00-7fc586cc9196",
"enrollmentId": "c91a5e2b-7d0f-4f3e-9a51-2f6b8e1d4c77",
"customerId": "a2d4c1e8-5b7f-4c3a-9e2d-1f6b8c0d7e55",
"paymentRequestId": "5b7e2c1d-3a4f-4e8b-9c6d-7f0a1b2c3d4e"
}paymentRequestId is the payment request where the link was created, and customerId is null when it had no customer. Each event is sent once, when the enrollment enters that status. Retrieve the enrollment for the details.
A link that was AUTHORIZED and later reaches its expiresAt sends no event: check expiresAt, or retrieve the enrollment, to know it ended.
