Skip to content
Last updated

plaid-txn-stream is the only publicly documented file content contract. Upload UTF-8 JSON with fileType=json and Content-Type: application/json.

Percents supports two payload layouts:

  1. an array of Plaid transaction objects where each transaction has an attached account; or
  2. an object containing a transactions array and an accounts array, joined by account_id.
{
  "accounts": [
    {
      "account_id": "acc_EXAMPLE_abc123xyz",
      "mask": "4321",
      "name": "Freedom Unlimited",
      "official_name": "CHASE FREEDOM UNLIMITED VISA SIGNATURE",
      "type": "credit",
      "subtype": "credit card",
      "balances": {
        "available": 1234.56,
        "current": 1234.56,
        "iso_currency_code": "USD"
      }
    }
  ],
  "transactions": [
    {
      "transaction_id": "plaid-transaction-1",
      "pending_transaction_id": null,
      "account_id": "acc_EXAMPLE_abc123xyz",
      "amount": 4.75,
      "iso_currency_code": "USD",
      "date": "2026-07-11",
      "datetime": "2026-07-11T14:32:07Z",
      "authorized_date": "2026-07-10",
      "authorized_datetime": "2026-07-10T18:04:12Z",
      "name": "BLUE BOTTLE COFFEE #142 OAKLAND CA",
      "merchant_name": "Blue Bottle Coffee",
      "merchant_entity_id": "mrch_ent_EXAMPLE_bluebottle",
      "payment_channel": "in store",
      "pending": false,
      "category": ["Food and Drink", "Restaurants", "Coffee Shop"],
      "personal_finance_category": {
        "primary": "FOOD_AND_DRINK",
        "detailed": "FOOD_AND_DRINK_COFFEE",
        "confidence_level": "VERY_HIGH"
      },
      "location": {
        "city": "Oakland",
        "region": "CA",
        "postal_code": "94607",
        "country": "US"
      }
    }
  ]
}

Fields used for normalization

FieldRequirement and behavior
transaction_idRequired, non-empty unique transaction identifier
account_idRequired; must match an account when account metadata supplies the card mask
amountRequired finite number in Plaid transaction units; do not convert dollars to cents
datetime, authorized_datetime, date, authorized_dateAt least one valid value; Percents uses the first available in this order
merchant_name or nameAt least one required; merchant_name is preferred as canonical merchant name
nameUsed as the transaction descriptor when present
merchant_entity_idUsed as the network merchant ID when present
iso_currency_codeDefaults to USD when absent
account maskRequired either on the transaction or matching account
account name, official_name, subtype, typeOptional card/account metadata
payment_channelin store maps to chip; online maps to online; other values remain in the raw payload without a mapped auth method

Additional Plaid fields are allowed and preserved with the raw transaction for audit and troubleshooting. Do not remove fields from a standard Plaid response merely because Percents does not currently normalize them.

Array with attached account

[
  {
    "transaction_id": "plaid-transaction-1",
    "account_id": "acc_EXAMPLE_abc123xyz",
    "amount": 4.75,
    "date": "2026-07-11",
    "name": "BLUE BOTTLE COFFEE",
    "merchant_name": "Blue Bottle Coffee",
    "account": {
      "account_id": "acc_EXAMPLE_abc123xyz",
      "mask": "4321",
      "type": "credit",
      "subtype": "credit card"
    }
  }
]

When an attached account is present, its account_id must equal the transaction's account_id.