FDX

Financial Data Exchange (FDX) US open-banking standard — consent records, SHA3 transaction hashes, data-recipient registry.

CFPB §1033 (12 CFR §1033.121-461, final rule 2024-10-22) gives US consumers the right to authorize a third party to access their financial data through a covered data provider's developer interface. FDX (https://financialdataexchange.org) is the industry-standard schema + protocol the CFPB rule effectively codifies (FDX 6.0+ aligns with the §1033 final rule). Compliance deadline 2026-04-01 already past for $250B+ asset-size banks.

The framework can't be the operator's authorization server, resource server, or FDX-data origin — those are the operator's core banking system. What it can do: bind the operator's auth server to the FAPI 2.0 profile (which §1033.351 effectively requires), validate FDX response shapes, emit §1033-shape audit events on every authorized data access, and generate the §1033.401(b) consent receipt.

b.fdx.bind(opts) #

stable0.8.0fdxfapi2
{
  authServer: {
    issuer:  string,        // required, non-empty
    jwksUri: string,        // required, non-empty
    fapi2:   { pkce, dpop?, mtls?, par },
  },
  resources: ["accounts" | "transactions" | "statements" |
              "payment-networks" | "rewards" | "tax-forms"],
}

Bind an operator's authorization-server config to the FDX 6.0 data-sharing surface and the FAPI 2.0 security profile. Refuses unknown FDX resources, refuses missing issuer/jwksUri, and runs b.fapi2.assertOAuthConfig on the supplied FAPI opts so a non-conformant deployment fails at boot. Returns a handle with schemaValidator(resource, body) and consent.receipt(opts).

var fdx = b.fdx.bind({
  authServer: {
    issuer:  "https://auth.example-bank.com",
    jwksUri: "https://auth.example-bank.com/.well-known/jwks.json",
    fapi2:   { pkce: true, mtls: true, par: true },
  },
  resources: ["accounts", "transactions"],
});
fdx.fapi2Posture;
// → "fapi-2.0"

b.fdx.validateResponse(resourceType, body) #

stable0.8.0fdx

Validate an FDX response payload against the framework's FDX 6.0 minimum-required-field schema. Accepts both envelope form ({ accounts: [...] }) and bare-array / single-record form. Returns { valid, errors } so the operator can decide whether to refuse, redact, or pass through. Throws FdxError only when resourceType is unknown.

var result = b.fdx.validateResponse("accounts", {
  accounts: [{
    accountId:            "acct-1",
    accountType:          "DEPOSIT",
    accountNumberDisplay: "****1234",
    currency:             "USD",
    currentBalance:       1234.56,
  }],
});
result.valid;
// → true
result.errors.length;
// → 0

b.fdx.consentReceipt(opts) #

stable0.8.0fdx
{
  dataProvider:  string,         // issuer / data provider name
  consumerRef:   string,         // operator-side consumer identifier
  thirdParty:    string,         // recipient name
  revocationUrl: string,         // public revocation endpoint
  scopes:        [string, ...],  // data scopes (account ids, resources)
  durationMs:    number,         // optional; defaults to 52 weeks
}

Mint the §1033.401(b) consent receipt the authorization server gives the consumer at authorization time. Required fields: dataProvider, consumerRef, thirdParty, revocationUrl, scopes. Optional durationMs defaults to 52 weeks. Emits fdx.consent_receipt_issued to the audit chain so the regulator sees a record per receipt.

var receipt = b.fdx.consentReceipt({
  dataProvider:  "https://auth.example-bank.com",
  consumerRef:   "consumer-42",
  thirdParty:    "Aggregator Inc.",
  revocationUrl: "https://example-bank.com/consent/revoke/abc",
  scopes:        ["accounts", "transactions"],
  durationMs:    365 * 86400 * 1000,
});
receipt.type;
// → "fdx.consent-receipt"

Last updated 2026-08-08T16:39:49.652Z by seeder.