Plaid logo
Core Exchange
ALL DOCS

Post-launch

  • Post-launch operations
  • Dashboard monitoring
  • Consent management
  • App Directory
  • Troubleshooting
Core Exchange
Close search modal
Ask Bill!
Ask Bill!
Hi! I'm Bill! You can ask me all about Core Exchange. Try asking questions like:
    Note: Bill isn't perfect. He's just a robot platypus that reads our docs for fun. You should treat his answers with the same healthy skepticism you might treat any other answer on the internet. This chat may be logged for quality and training purposes. Please don't send Bill any PII -- he's scared of intimacy. All chats with Bill are subject to Plaid's Privacy Policy.
    Plaid.comGet Started
    Open nav

    Consent API (beta)

    Read and revoke FDX consent grants programmatically

    Overview

    Use the Consent API to build a consumer-facing consent portal, to answer support requests about a customer's connections, and to revoke access when a customer withdraws consent.

    The Consent API represents each of your customers' authorizations as an FDX consent grant: a record of which application has access, which of the customer's resources it can read, which data clusters are in scope, and how long that access lasts.

    The Consent API is currently in beta. To request access, contact Plaid solutions engineering. Note that the no-code Dashboard does not currently support the Consent API; if using both surfaces, you may see inconsistent data across the two.

    For conceptual background on authorization records, or to learn how to manage consent via the Dashboard instead of via API, see Consent management.

    Customer identifiers

    Every consent grant is scoped to a customerId, which must be the same persistent, unique identifier you use as the sub claim in your OIDC ID token. See Unique user identifier (consistency key).

    If you are a platform or gateway serving multiple institutions, Plaid assumes customerId is unique across all of them. If you reuse a customer identifier across institutions, contact your Plaid solutions engineering team before you integrate.

    Data clusters

    A consent grant covers a set of resources, each with a list of FDX data clusters. resources is omitted entirely when a grant covers none. resourceType is one of ACCOUNT, CUSTOMER, or DOCUMENT, and the clusters Plaid may request are:

    Data clusterIncludes
    ACCOUNT_BASICAccount name, type, and masked account number
    ACCOUNT_DETAILEDEverything in ACCOUNT_BASIC, plus credit limits, due dates, and interest rates
    BALANCESCurrent and available balances
    PAYMENT_SUPPORTAccount and routing numbers and other stored payment methods
    SCHEDULED_PAYMENTSFuture-dated single and recurring payments, with amounts and frequency
    TRANSACTIONSTransaction amounts, dates, descriptions, and merchants
    STATEMENTSPDF statements
    INVESTMENTSInvestment holdings, securities details, quantities, and market values
    CUSTOMER_CONTACTAccount owner name, email, phone, and postal address
    TAXTax forms such as 1099s and W-2s

    Plaid uses a different, consumer-facing taxonomy for these clusters in the Link flow. Contact your Plaid solutions engineering team if you need the mapping between the two.

    Plaid does not use the BILLS, CUSTOMER_PERSONAL, IMAGES, and REWARDS clusters, so they will not appear on a consent grant Plaid brokers. The FDXDataCluster enum also defines ACCOUNT_PAYMENTS and NOTIFICATIONS.

    Revocation and ecosystem sync

    If you offer users the ability to revoke access to connected apps (for example, via a consumer-facing consent portal), you must keep the ecosystem in sync. When a user revokes access on your side, Plaid and the downstream app need to know immediately.

    How it works:

    1. User revokes access on your domain: User visits your consent portal and disconnects an app
    2. Call PUT /fdx/consents/{consentId}/revocation: Your system calls Plaid's revocation endpoint
    3. Plaid notifies the app: Plaid sends a webhook to the disconnected app
    4. Plaid severs the connection: Plaid blocks the app from accessing data
    5. App stops requesting data: The app knows the user revoked access and stops making requests

    This keeps revocation instant across all parties. Without it, the app won't know that consent has been revoked until the next time it attempts to actively fetch data from the connection.

    Plaid notifies you of these events in real time via webhooks; see Webhooks below.

    Webhooks

    Plaid can optionally send webhooks to you when authorization events occur. Single-institution accounts can configure these in the Data Partner Dashboard via the Developers > Webhooks page. Platform accounts should reach out to your Plaid contact to have these enabled.

    Webhook configuration interface in the Data Partner Dashboard
    Configure webhooks for real-time connection and disconnection alerts

    Plaid sends two webhooks: AUTHORIZATION_GRANTED and CONSENT_REVOKED.

    Each webhook is an FDX event notification: a category/type pair identifies the event, and notificationPayload.customFields carries the details as name/value pairs.

    AUTHORIZATION_GRANTED

    Notifies you every time a user connects a new app via Plaid. While your system will already know about new OAuth authorizations, this webhook also alerts you to connections created via the returning user experience, where the user doesn't go through your OAuth flow and this webhook is your only real-time signal that a new connection was created.

    When it fires: After a user successfully authorizes a new app.

    Payload includes: The customer (user_identifier) and app details (application_id, application_name).

    What to do: Record the new connection. The webhook identifies the user and the app, but not the accounts or data clusters they authorized, so treat it as a signal to fetch the full consent grant from GET /fdx/consents rather than as the authorization record itself. If you offer a consent portal, display this new connection so users can view and manage it.

    AUTHORIZATION_GRANTED example
    {
      "notificationId": "b3f1c4d2-8a5e-4b6a-9c1f-2e7d5a8b3c9d",
      "sentOn": "2026-08-05T14:32:00Z",
      "category": "AUTHORIZATION",
      "type": "AUTHORIZATION_GRANTED",
      "publisher": { "name": "Plaid", "type": "DATA_ACCESS_PLATFORM" },
      "notificationPayload": {
        "id": "consentapi-example-1",
        "idType": "CONSENT",
        "customFields": [
          { "name": "user_identifier", "value": "consentapi-example-1" },
          { "name": "application_id", "value": "09f9befa-acb6-4575-93c7-b64ef523641e" },
          { "name": "application_name", "value": "Incremental Investing" }
        ]
      }
    }

    CONSENT_REVOKED

    Notifies you when a user revokes access to an app, either through the third-party app itself or via my.plaid.com (Plaid Portal). If you offer a consent portal, you need this webhook to catch the revocations that happen elsewhere; otherwise your portal will drift out of sync when users disconnect through my.plaid.com or the app itself instead of through you.

    When it fires: After a user or app revokes authorization.

    Payload includes: The customer (user_identifier), app details, and who initiated the revocation (initiator: DATA_ACCESS_PLATFORM, INDIVIDUAL, or DATA_RECIPIENT).

    What to do: Update your authorization records to mark the connection as revoked. If you offer a consent portal, update the display to show that the connection is no longer active.

    CONSENT_REVOKED example
    {
      "notificationId": "e7a2d9f1-3b6c-4a8e-9d5f-1c8b4e2a7d3f",
      "sentOn": "2026-08-05T14:35:00Z",
      "category": "CONSENT",
      "type": "CONSENT_REVOKED",
      "publisher": { "name": "Plaid", "type": "DATA_ACCESS_PLATFORM" },
      "notificationPayload": {
        "id": "consentapi-example-1",
        "idType": "CONSENT",
        "customFields": [
          { "name": "user_identifier", "value": "consentapi-example-1" },
          { "name": "application_id", "value": "09f9befa-acb6-4575-93c7-b64ef523641e" },
          { "name": "application_name", "value": "Incremental Investing" },
          { "name": "initiator", "value": "INDIVIDUAL" }
        ]
      }
    }

    Best practices

    • Implement the CONSENT_REVOKED webhook if you offer a consent portal
    • Use PUT /fdx/consents/{consentId}/revocation to keep the ecosystem in sync during revocations
    • Set refresh token expiration to 13+ months (allows buffer for reauthorization)
    • Direct users to my.plaid.com for self-service connection management

    Authentication

    Find your client_id and secret on the Developer > Keys tab of the Data Partner Dashboard and include both as the PLAID-CLIENT-ID and PLAID-SECRET headers, or as client_id and secret in the request body. All requests must be made over HTTPS.

    Endpoints

    EndpointFunctionality
    GET /fdx/consentsList a customer's consent grants
    GET /fdx/consents/{consentId}Get a single consent grant
    PUT /fdx/consents/{consentId}/revocationRevoke a consent grant
    GET /fdx/consents/{consentId}/revocationGet a consent grant's revocation history

    List a customer's consent grants

    GET /fdx/consents

    Fetch this list each time a customer opens your consent portal rather than serving a cached copy, so that revocations made elsewhere in the ecosystem are reflected immediately. Omit status to return grants in every state, which is useful for an audit view.

    List FDX consent grants for a customer

    Returns zero or more consent grants associated with the given data provider customer, optionally filtered by status.

    /fdx/consents

    Request fields

    customerId
    stringstring

    Data provider customer identifier whose consent grants to return.

    Parameter type: query
    status
    stringstring

    Optional filter restricting results to a single consent grant status. One of ACTIVE, REVOKED, EXPIRED.

    Possible values: ACTIVE, REVOKED, EXPIRED
    Parameter type: query
    curl -X GET 'https://production.plaid.com/fdx/consents?customerId=<customer_id>&status=ACTIVE' \
      -H 'PLAID-CLIENT-ID: <client_id>' \
      -H 'PLAID-SECRET: <secret>'
    /fdx/consents

    Response fields

    consent_grants
    [object][object]

    Consent grants matching the customerId (and optional status) filter.

    id
    stringstring

    The persistent identifier of the consent grant

    status
    stringstring

    Current status of a consent grant. One of ACTIVE, REVOKED, EXPIRED.

    Possible values: ACTIVE, REVOKED, EXPIRED
    createdTime
    stringstring

    When the consent was initially granted

    Format: date-time
    updatedTime
    stringstring

    When the consent grant was last updated

    Format: date-time
    expirationTime
    stringstring

    When the consent grant will expire. Omitted when the grant has no expiration.

    Format: date-time
    parties
    [object][object]

    Non-end-user parties participating in the consent grant (Data Recipient, Data Provider, Data Access Platform).

    name
    stringstring

    Human recognizable common name

    type
    stringstring

    Identifies the type of a party

    Possible values: DATA_ACCESS_PLATFORM, DATA_PROVIDER, DATA_RECIPIENT, INDIVIDUAL, MERCHANT, VENDOR
    homeUri
    stringstring

    URI for party, where an end user could learn more about the company or application involved in the data sharing chain

    Format: uri
    logoUri
    stringstring

    URI for a logo asset to be displayed to the end user

    Format: uri
    registry
    stringstring

    The registry containing the party's registration with name and id

    Possible values: FDX, GLEIF, ICANN, PRIVATE
    registeredEntityName
    stringstring

    Registered name of party

    registeredEntityId
    stringstring

    Registered id of party

    resources
    [object][object]

    Permissioned resource entries. Omitted when there are no resources.

    resourceType
    stringstring

    Type of resource permissioned on a consent grant.

    Possible values: ACCOUNT, CUSTOMER, DOCUMENT
    resourceId
    stringstring

    Identifier of the resource permissioned.

    dataClusters
    [string][string]

    Names of clusters of data elements permissioned.

    Possible values: ACCOUNT_BASIC, ACCOUNT_DETAILED, ACCOUNT_PAYMENTS, BILLS, CUSTOMER_CONTACT, CUSTOMER_PERSONAL, IMAGES, INVESTMENTS, NOTIFICATIONS, PAYMENT_SUPPORT, REWARDS, STATEMENTS, TAX, TRANSACTIONS, BALANCES, SCHEDULED_PAYMENTS
    Response Object
    {
      "consent_grants": [
        {
          "id": "9585694d-3ae5-8863-1234-567890abcdef",
          "status": "ACTIVE",
          "createdTime": "2026-01-01T00:00:00Z",
          "updatedTime": "2026-01-01T00:00:00Z",
          "parties": [
            {
              "name": "My Example Client",
              "type": "DATA_RECIPIENT",
              "homeUri": "https://example.com",
              "registry": "PRIVATE",
              "registeredEntityName": "My Example Client LLC",
              "registeredEntityId": "549300A0B1C2D3E4F5G6"
            },
            {
              "name": "First Platypus Bank",
              "type": "DATA_PROVIDER",
              "homeUri": "https://www.platypus.com"
            },
            {
              "name": "Plaid",
              "type": "DATA_ACCESS_PLATFORM",
              "homeUri": "https://plaid.com"
            }
          ],
          "resources": [
            {
              "resourceType": "ACCOUNT",
              "resourceId": "b14e1e714693bc00",
              "dataClusters": [
                "ACCOUNT_BASIC",
                "ACCOUNT_DETAILED",
                "STATEMENTS"
              ]
            }
          ]
        },
        {
          "id": "1a2b3c4d-5e6f-7890-abcd-ef0123456789",
          "status": "REVOKED",
          "createdTime": "2026-01-03T00:00:00Z",
          "updatedTime": "2026-01-04T00:00:00Z",
          "parties": [
            {
              "name": "Another Example Client",
              "type": "DATA_RECIPIENT",
              "homeUri": "https://another-example.com",
              "registry": "PRIVATE",
              "registeredEntityName": "Another Example Client LLC",
              "registeredEntityId": "549300Z9Y8X7W6V5U4T3"
            },
            {
              "name": "First Platypus Bank",
              "type": "DATA_PROVIDER",
              "homeUri": "https://www.platypus.com"
            },
            {
              "name": "Plaid",
              "type": "DATA_ACCESS_PLATFORM",
              "homeUri": "https://plaid.com"
            }
          ],
          "resources": [
            {
              "resourceType": "ACCOUNT",
              "resourceId": "c25f2f825704cd11",
              "dataClusters": [
                "ACCOUNT_BASIC",
                "ACCOUNT_DETAILED"
              ]
            }
          ]
        }
      ]
    }

    Get a single consent grant

    GET /fdx/consents/{consentId}

    Use the parties array to identify the application: the entry with type of DATA_RECIPIENT is the connected app, DATA_PROVIDER is you, and DATA_ACCESS_PLATFORM is Plaid.

    If you have an existing live integration and need the consentId values for connections that predate it, contact your Plaid solutions engineering team to coordinate a backfill.

    Get FDX consent grant

    Returns a consent grant by its identifier.

    /fdx/consents/{consentId}

    Request fields

    consentId
    stringstring

    Unique identifier of the consent grant.

    Parameter type: path
    curl -X GET 'https://production.plaid.com/fdx/consents/<consent_id>' \
      -H 'PLAID-CLIENT-ID: <client_id>' \
      -H 'PLAID-SECRET: <secret>'
    /fdx/consents/{consentId}

    Response fields

    id
    stringstring

    The persistent identifier of the consent grant

    status
    stringstring

    Current status of a consent grant. One of ACTIVE, REVOKED, EXPIRED.

    Possible values: ACTIVE, REVOKED, EXPIRED
    createdTime
    stringstring

    When the consent was initially granted

    Format: date-time
    updatedTime
    stringstring

    When the consent grant was last updated

    Format: date-time
    expirationTime
    stringstring

    When the consent grant will expire. Omitted when the grant has no expiration.

    Format: date-time
    parties
    [object][object]

    Non-end-user parties participating in the consent grant (Data Recipient, Data Provider, Data Access Platform).

    name
    stringstring

    Human recognizable common name

    type
    stringstring

    Identifies the type of a party

    Possible values: DATA_ACCESS_PLATFORM, DATA_PROVIDER, DATA_RECIPIENT, INDIVIDUAL, MERCHANT, VENDOR
    homeUri
    stringstring

    URI for party, where an end user could learn more about the company or application involved in the data sharing chain

    Format: uri
    logoUri
    stringstring

    URI for a logo asset to be displayed to the end user

    Format: uri
    registry
    stringstring

    The registry containing the party's registration with name and id

    Possible values: FDX, GLEIF, ICANN, PRIVATE
    registeredEntityName
    stringstring

    Registered name of party

    registeredEntityId
    stringstring

    Registered id of party

    resources
    [object][object]

    Permissioned resource entries. Omitted when there are no resources.

    resourceType
    stringstring

    Type of resource permissioned on a consent grant.

    Possible values: ACCOUNT, CUSTOMER, DOCUMENT
    resourceId
    stringstring

    Identifier of the resource permissioned.

    dataClusters
    [string][string]

    Names of clusters of data elements permissioned.

    Possible values: ACCOUNT_BASIC, ACCOUNT_DETAILED, ACCOUNT_PAYMENTS, BILLS, CUSTOMER_CONTACT, CUSTOMER_PERSONAL, IMAGES, INVESTMENTS, NOTIFICATIONS, PAYMENT_SUPPORT, REWARDS, STATEMENTS, TAX, TRANSACTIONS, BALANCES, SCHEDULED_PAYMENTS
    Response Object
    {
      "id": "9585694d-3ae5-8863-1234-567890abcdef",
      "status": "ACTIVE",
      "createdTime": "2026-01-01T00:00:00Z",
      "updatedTime": "2026-01-01T00:00:00Z",
      "parties": [
        {
          "name": "My Example Client",
          "type": "DATA_RECIPIENT",
          "homeUri": "https://example.com",
          "registry": "PRIVATE",
          "registeredEntityName": "My Example Client LLC",
          "registeredEntityId": "549300A0B1C2D3E4F5G6"
        },
        {
          "name": "First Platypus Bank",
          "type": "DATA_PROVIDER",
          "homeUri": "https://www.platypus.com"
        },
        {
          "name": "Plaid",
          "type": "DATA_ACCESS_PLATFORM",
          "homeUri": "https://plaid.com"
        }
      ],
      "resources": [
        {
          "resourceType": "ACCOUNT",
          "resourceId": "b14e1e714693bc00",
          "dataClusters": [
            "ACCOUNT_BASIC",
            "BALANCES",
            "TRANSACTIONS",
            "SCHEDULED_PAYMENTS"
          ]
        }
      ]
    }

    Revoke a consent grant

    PUT /fdx/consents/{consentId}/revocation

    Call this endpoint as soon as a customer disconnects an application in your portal, or when your own risk or compliance systems terminate access. Plaid then notifies the application and stops serving it data, which is what keeps your portal, Plaid, and the application in sync. See Revocation and ecosystem sync for what happens if you skip this call.

    Set initiator to the party that triggered the revocation, usually DATA_PROVIDER. Set reason to USER_ACTION when a customer disconnects the app themselves, or BUSINESS_RULE or SECURITY_EVENT when you revoke on your own initiative. If you pass OTHER, describe the circumstances in otherReason.

    A successful revocation returns 204 No Content with an empty body. Revocation is not idempotent: a grant that is already revoked or expired returns 409 CONFLICT rather than succeeding again. Revocation is also per grant, so a customer with several grants for the same application needs a call for each consentId.

    Revoke FDX consent grant

    Revokes a consent grant, ending the data recipient's ongoing access to the customer's data.

    /fdx/consents/{consentId}/revocation

    Request fields

    consentId
    stringstring

    Unique identifier of the consent grant.

    Parameter type: path
    initiator
    requiredstringrequired, string

    Identifies the type of a party

    Possible values: DATA_ACCESS_PLATFORM, DATA_PROVIDER, DATA_RECIPIENT, INDIVIDUAL, MERCHANT, VENDOR
    reason
    requiredstringrequired, string

    Reason for lifecycle event status change

    Possible values: BUSINESS_RULE, SECURITY_EVENT, USER_ACTION, OTHER
    otherReason
    stringstring

    Additional information or description of an OTHER reason

    updatedTime
    stringstring

    When the revocation was effected on the initiator's side

    Format: date-time
    curl -X PUT 'https://production.plaid.com/fdx/consents/<consent_id>/revocation' \
      -H 'PLAID-CLIENT-ID: <client_id>' \
      -H 'PLAID-SECRET: <secret>' \
      -H 'Content-Type: application/json' \
      -d '{
        "initiator": "DATA_PROVIDER",
        "reason": "USER_ACTION"
      }'

    Revoking a consent grant stops the application from requesting new data. It does not delete data the application has already received; a customer who wants that data deleted has to ask the application directly.

    Retrieve a consent grant's revocation history

    GET /fdx/consents/{consentId}/revocation

    Use this endpoint to show a customer when and why access ended, and to keep an audit record of who initiated it. Records are returned most recent first, and the array is empty for a grant that has never been revoked.

    Retrieve FDX consent grant revocation records

    Returns the revocation history of a consent grant.

    /fdx/consents/{consentId}/revocation

    Request fields

    consentId
    stringstring

    Unique identifier of the consent grant.

    Parameter type: path
    curl -X GET 'https://production.plaid.com/fdx/consents/<consent_id>/revocation' \
      -H 'PLAID-CLIENT-ID: <client_id>' \
      -H 'PLAID-SECRET: <secret>'
    /fdx/consents/{consentId}/revocation

    Response fields

    revocations
    [object][object]

    Revocation records for the consent grant, most recent first. Empty when the grant has never been revoked.

    status
    stringstring

    Current status of a consent grant. One of ACTIVE, REVOKED, EXPIRED.

    Possible values: ACTIVE, REVOKED, EXPIRED
    reason
    stringstring

    Reason for lifecycle event status change

    Possible values: BUSINESS_RULE, SECURITY_EVENT, USER_ACTION, OTHER
    initiator
    stringstring

    Identifies the type of a party

    Possible values: DATA_ACCESS_PLATFORM, DATA_PROVIDER, DATA_RECIPIENT, INDIVIDUAL, MERCHANT, VENDOR
    updatedTime
    stringstring

    When the consent grant was revoked

    Format: date-time
    Response Object
    {
      "revocations": [
        {
          "status": "REVOKED",
          "reason": "USER_ACTION",
          "initiator": "DATA_PROVIDER",
          "updatedTime": "2026-01-03T00:00:00Z"
        }
      ]
    }

    Testing in Sandbox

    A consent grant is normally created when a customer authorizes an application through your OAuth flow. To exercise these endpoints in Sandbox without a live connection, seed a grant with /sandbox/fdx/consent/seed and then list, retrieve, and revoke it as you would in production.

    Pass consent_id to control the identifier of the seeded grant, which makes tests deterministic; omit it and Plaid generates one. Seeding fails if a grant with that identifier already exists.

    Revoking a consent grant is permanent. To test reconnection, seed a second grant for the same customer_id and application_id; it is issued a new consent_id, and the original stays in the customer's history as REVOKED.

    POST /sandbox/fdx/consent/seed

    Seed an FDX consent grant for a sandbox data partner

    /sandbox/fdx/consent/seed creates a test FDX consent grant (and a backing Item) for a data provider's customer in Sandbox, so the FDX Consent API endpoints can be exercised end-to-end without a live data provider connection.

    customer_id is the data provider's identifier for the end user and application_id identifies the data recipient application the consent is granted to; both are required. Optionally provide consent_id (a UUIDv4) to control the seeded grant's identifier; one is generated when omitted. The seeded grant is returned by /fdx/consents and /fdx/consents/{consentId}, and can be revoked via /fdx/consents/{consentId}/revocation.

    /sandbox/fdx/consent/seed

    Request fields

    client_id
    stringstring

    Your Plaid API client_id. The client_id is required and may be provided either in the PLAID-CLIENT-ID header or as part of a request body.

    secret
    stringstring

    Your Plaid API secret. The secret is required and may be provided either in the PLAID-SECRET header or as part of a request body.

    customer_id
    requiredstringrequired, string

    The data provider's identifier for the end user to associate the seeded consent grant with.

    application_id
    requiredstringrequired, string

    This field will map to the application ID that is returned from /item/application/list, or provided to the institution in an oauth redirect.

    consent_id
    stringstring

    Optional UUIDv4 identifier for the seeded consent grant. If omitted, one is generated. Seeding fails if a grant with this identifier already exists.

    curl -X POST 'https://sandbox.plaid.com/sandbox/fdx/consent/seed' \
      -H 'Content-Type: application/json' \
      -d '{
        "client_id": "<client_id>",
        "secret": "<secret>",
        "customer_id": "consentapi-example-1",
        "application_id": "5d16db26-b759-4d3e-ab8f-e01e8c494eae"
      }'
    /sandbox/fdx/consent/seed

    Response fields

    consent_id
    stringstring

    The identifier of the newly seeded FDX consent grant.

    request_id
    stringstring

    A unique identifier for the request, which can be used for troubleshooting. This identifier, like all Plaid identifiers, is case sensitive.

    Response Object
    {
      "consent_id": "9cfe04b5-6d04-45ce-897e-45f2580bf013",
      "request_id": "m8MDnv9okwxFNBV"
    }

    Plaid provides demo applications to grant consent to when seeding:

    Demo applicationapplication_id
    Budget Works5cfef3f0-e405-4597-991d-057ac558e3d5
    Incremental Investing09f9befa-acb6-4575-93c7-b64ef523641e
    My Peer Payer5d16db26-b759-4d3e-ab8f-e01e8c494eae

    Seeded grants are never deleted, so repeatedly seeding and revoking the same customer_id and application_id pair grows that customer's result set from /fdx/consents indefinitely. Account for this in automated tests.

    Errors

    These endpoints use the FDX error format rather than Plaid's standard error object. The body contains error_type, error_code, and error_message only — there is no display_message or request_id. error_type and error_code are stable and safe to branch on; error_message is not.

    Statuserror_typeerror_codeReturned when
    400BAD_REQUEST32customerId is missing when listing grants, or the revocation body cannot be parsed or names an unsupported reason or initiator
    404NOT_FOUND1107The consent grant does not exist, or belongs to another institution
    409CONFLICT409Revocation was requested for a grant that is already revoked or expired
    500INTERNAL_SERVER_ERROR01An unexpected error occurred

    A 404 deliberately does not distinguish a grant that does not exist from one belonging to another institution, so you cannot use it to probe for grants you do not own.

    Because a failure here surfaces inside your own consent portal, treat these responses as internal diagnostics rather than something to pass through to the customer. A lookup that returns 404 is better rendered as an empty state than as an error.

    Migrating from Permissions Manager to the Consent API

    The two APIs describe the same underlying consent in different schemas.

    To do thisPermissions Manager APIConsent API
    List a customer's connected applications/item/application/listGET /fdx/consents
    Read the details of one authorization/item/application/listGET /fdx/consents/{consentId}
    Revoke an application's access/item/application/unlinkPUT /fdx/consents/{consentId}/revocation
    Read revocation history/item/activity/listGET /fdx/consents/{consentId}/revocation
    See when each application last read each data type/item/activity/listNot available
    See connection, disconnection, and data-deletion events/item/activity/listNot available

    The two views describe the same underlying consent, and revoking through either one takes effect everywhere.

    Customer identification differences

    Permissions Manager identifies a customer by an access_token, so every call is preceded by exchanging a customer identifier for one via /item/import. The Consent API drops this step: every endpoint takes your customerId directly, the same persistent identifier you use as the sub claim in your OIDC ID token. If you migrate, you can remove the /item/import call from your integration entirely.

    Scope mapping

    Permissions Manager reports scopes as product_access keys; the Consent API reports the same access as FDX data clusters. The two taxonomies don't line up one to one — for example, account_balance_info spans both ACCOUNT_BASIC and BALANCES:

    Permissions Manager product_access keyConsent API data cluster(s)
    account_balance_infoACCOUNT_BASIC, BALANCES
    contact_infoCUSTOMER_CONTACT
    account_routing_numberPAYMENT_SUPPORT
    transactionsTRANSACTIONS
    credit_loan_infoACCOUNT_DETAILED
    investmentsINVESTMENTS
    bank_statementsSTATEMENTS

    This mapping is derived from each field's description in the two schemas, not from a joint spec. Confirm it with your Plaid solutions engineering team before relying on it for scope-gated logic.

    Error handling

    Permissions Manager returns Plaid's standard error object (error_type, error_code, error_message, display_message, request_id). The Consent API uses the FDX error format instead — only error_type, error_code, and error_message, with no display_message or request_id — so error-handling code written against Permissions Manager will need updating rather than reused as-is. See Errors above for the full list.