{
  "schema": "aaes/capability-pack/1",
  "provider": "plaid",
  "version": "1.0.0",
  "description": "Plaid account data: read accounts, transactions, balances and identity data for connected Items, and create Link tokens.",
  "notes": "Plaid's API is JSON-over-HTTP and POST-only, including for reads, so the read capabilities here ride on POST methods; nothing about a POST method changes the read verb's meaning. Hosts are per environment — Plaid's docs name https://sandbox.plaid.com (Sandbox) and https://production.plaid.com (Production), and Items cannot be moved between environments — so this pack registers the Production host, and a deployment testing in Sandbox replaces the host in the endpoint and the egress allowlist in step.\n\nThis pack does not register /item/public_token/exchange: the exchange returns the access_token, and Plaid's own guidance is that every token except the public_token and link_token is long-lasting and sensitive — that response is newly minted credential material, which a governed executor must not receive as call output, so the exchange belongs in the deployment's token-handling path, not in a capability. SECOND SECRET: the read capabilities take an access_token in the request body, and that per-Item token is end-user credential material — a second secret distinct from the pack credential (the client secret below).\n\nThe deployment must resolve it from a trusted per-Item vault and have the trusted executor inject it into the request body, without ever exposing it to the agent, to prompts, or to ordinary request logs; this pack's single registered injection (the PLAID-SECRET header) does NOT implement that per-Item wiring — it is a deployment wiring item, and enabling these capabilities without it would push a live access_token into agent-visible request material.\n\nLink tokens: plaid.link_token.create covers both initial-linking Link sessions and update-mode Link sessions (re-authentication or permission repair for an existing Item, where the request carries that Item's access_token, with the same second-secret custody). Excluding Plaid's money-movement products (Transfer, Payment Initiation) from this pack does not constrain the Link configuration this call can request: an unrestricted /link/token/create request can name any product the Plaid account has enabled, so the deployment must either enforce an allowlist of products and other Link configuration at the wiring layer, or treat this capability as supporting the broader effects of every product enabled on the account.\n\nThis pack does not register the processor-token endpoints. AAES has not been certified by Plaid; the endpoints here are configuration to review and test; the vendor has not endorsed it.",
  "credential": {
    "secret_ref_id": "secret-ref-plaid-client-secret",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "PLAID-SECRET",
    "note": "The Plaid API secret for the deployment's own Plaid account, held in the client's own secret manager. Plaid authenticates every request with a client_id and secret pair, sent either as the PLAID-CLIENT-ID and PLAID-SECRET headers or in the request body; this pack injects the PLAID-SECRET header, and the stored material must be the complete header value — the raw secret, with no scheme prefix — while the non-secret client_id travels as the PLAID-CLIENT-ID header from the deployment's own configuration.\n\nProvisioning and rotation are external: the secret is issued, and can be rotated or revoked, in the Plaid Dashboard by the account's administrators; it remains valid until rotated or revoked there (no short automatic expiry is documented for the secret itself), so rotation cadence and revocation-on-suspicion are the deployment's process, and a revoked value fails closed. Privilege restrictions: the secret authenticates at the Plaid account level — the available restriction is the Dashboard's per-environment and per-product configuration of the account and its keys (Sandbox and Production secrets are different credentials), so point this reference at the Production secret only when the deployment is meant to read live account data, and confirm the enabled-product set there because link_token.create can request any of them.\n\nExecutor hygiene: the resolved material must exist only in the executor process's memory for the moment of injection, must never be written to logs, traces or diagnostics, and must never appear in crash reports. SECOND SECRET — separate from this reference: each per-Item access_token the read capabilities spend is additional end-user credential material, minted outside this pack by the deployment's token-handling path; it must be held in a trusted per-Item vault and injected into the request body by the trusted executor with the same log/trace/crash protections, never exposed to the agent, prompts or ordinary request logs.\n\nThis single registered injection does NOT implement that per-Item resolution and body injection — it is a deployment wiring item."
  },
  "capabilities": [
    {
      "capability_id": "plaid.accounts.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "financial",
      "egress_allowlist": [
        "production.plaid.com"
      ],
      "endpoint": "https://production.plaid.com/accounts/get",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-plaid-client-secret",
      "inject": "header",
      "inject_name": "PLAID-SECRET",
      "actions": [
        "read"
      ],
      "resource_id": "plaid-items",
      "description": "Read the accounts linked to one Item (one end user's institution login): account ids, names, masks, types, and current and available balances. The request body's access_token selects the Item.\n\nThat per-Item access_token is a separate secret from the account-level PLAID-SECRET header. Resolve it from a trusted per-Item vault and have the trusted executor inject it into the request body. Never expose it to the agent, prompts, or ordinary request logs. This package does not supply that resolution and body injection; configure it before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "plaid.transactions.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "financial",
      "egress_allowlist": [
        "production.plaid.com"
      ],
      "endpoint": "https://production.plaid.com/transactions/get",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-plaid-client-secret",
      "inject": "header",
      "inject_name": "PLAID-SECRET",
      "actions": [
        "read"
      ],
      "resource_id": "plaid-items",
      "description": "Read a paginated collection of transactions for one Item (one end user's institution login). The request body selects the date range and page.\n\nThe request body's access_token is a separate per-Item secret from the account-level PLAID-SECRET header. Resolve it from a trusted per-Item vault and have the trusted executor inject it into the body. Never expose it to the agent, prompts, or ordinary request logs. This package does not supply that resolution and body injection; configure it before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "plaid.balances.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "financial",
      "egress_allowlist": [
        "production.plaid.com"
      ],
      "endpoint": "https://production.plaid.com/accounts/balance/get",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-plaid-client-secret",
      "inject": "header",
      "inject_name": "PLAID-SECRET",
      "actions": [
        "read"
      ],
      "resource_id": "plaid-items",
      "description": "Read current and available balances for one Item's accounts. Plaid requests updated balances from the institution where supported.\n\nThe request body's access_token is a separate per-Item secret from the account-level PLAID-SECRET header. Resolve it from a trusted per-Item vault and have the trusted executor inject it into the body. Never expose it to the agent, prompts, or ordinary request logs. This package does not supply that resolution and body injection; configure it before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "plaid.identity.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "production.plaid.com"
      ],
      "endpoint": "https://production.plaid.com/identity/get",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-plaid-client-secret",
      "inject": "header",
      "inject_name": "PLAID-SECRET",
      "actions": [
        "read"
      ],
      "resource_id": "plaid-items",
      "description": "Read identity data held by the institution for one Item's accounts: owner names, addresses, emails, and phone numbers. These are personal data.\n\nThe request body's access_token is a separate per-Item secret from the account-level PLAID-SECRET header. Resolve it from a trusted per-Item vault and have the trusted executor inject it into the body. Never expose it to the agent, prompts, or ordinary request logs. This package does not supply that resolution and body injection; configure it before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "plaid.link_token.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R2",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "production.plaid.com"
      ],
      "endpoint": "https://production.plaid.com/link/token/create",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-plaid-client-secret",
      "inject": "header",
      "inject_name": "PLAID-SECRET",
      "actions": [
        "create"
      ],
      "resource_id": "plaid-items",
      "description": "Create a link_token for an end-user Link session. The call returns a token object, rather than account data. Completing an initial linking flow produces a public_token valid for 30 minutes; the deployment exchanges it outside this package for the long-lasting access_token used by the registered reads.\n\nThe operation also opens update-mode sessions to repair authentication or permissions for an existing Item. Those requests carry the Item's access_token. Resolve that separate secret from the trusted per-Item vault and have the trusted executor inject it into the body with the protections in the package notes.\n\nExcluding money-movement endpoints does not restrict which Link products a request can enable. Enforce an allowlist of products and other Link settings in the deployment wiring, or treat this capability as permitting the effects of every product enabled on the Plaid account.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "plaid-items",
      "kind": "api",
      "locator": "https://production.plaid.com",
      "data_class": "financial",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://plaid.com/docs/api/ (retrieved 2026-09-21)",
      "https://plaid.com/docs/api/items/ (retrieved 2026-09-21)",
      "https://plaid.com/docs/api/link/ (retrieved 2026-09-21)",
      "https://plaid.com/docs/api/accounts/ (retrieved 2026-09-21)",
      "https://plaid.com/docs/api/products/transactions/ (retrieved 2026-09-21)",
      "https://plaid.com/docs/api/products/balance/ (retrieved 2026-09-21)",
      "https://plaid.com/docs/api/products/identity/ (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
