Sail

Account Connections

Sail connects to three kinds of accounts:

  • Bank and card accounts
  • Merchant accounts
  • HSA/FSA administrator accounts

All three are established the same way, through a connect_account flow of the Connect Account Widget, but each produces different data. The table below describes each connection type and what it gives you.

Connection type (connection_type)Links toProduces
cardA bank or credit/debit cardTransaction-level expenses
storeA merchant accountItem-level expenses
benefit_accountAn HSA/FSA administratorAccount information

A fourth connection type, external, isn’t established through the Connect Account Widget at all. It’s a feed you push yourself through the API rather than an account a user logs into, so it’s out of scope for this page.

Bank and card connections

A card connection links a user’s bank account or credit or debit card, the same kind of linking Plaid provides. Once connected, Sail reports one expense per transaction. See Transaction-Level and Item-Level Expenses for how that transaction-level data is structured.

Merchant connections

A store connection has a user log into a merchant directly (Amazon, Walgreens, Target, CVS, Walmart, and Costco, among others) through Sail’s Connect Account Widget. Instead of one expense per transaction, Sail reports individual products, giving you item-level detail a card connection alone can’t. See Transaction-Level and Item-Level Expenses for how transaction- and item-level data relate.

HSA/FSA connections

A benefit_account connection links a user’s HSA, FSA, or HRA administrator, for example Health Equity. Unlike a card or store connection, it doesn’t produce expenses, it produces account information:

  • Balance
  • Contribution activity
  • Owner identity
  • Deposit numbers

One administrator login can hold more than one account. A single Health Equity login, for example, can expose both an HSA and an LPFSA, each with its own account_id. Sail also publishes a directory of supported administrators through List HSA/FSA Administrators, listing each one’s capabilities and login URLs.

Where account information lives

Account information isn’t one object, it’s assembled from six separate endpoints, each gated by its own scope and product requirement.

  • Get Account returns balance and account type. Requires benefit_account scope and product.
  • List Activity returns contribution, distribution, interest, and fee history. Requires benefit_account scope and product.
  • Get Contribution Summary returns year-to-date contributions against the IRS limit. Requires benefit_account scope and product.
  • Get Account & Routing Numbers returns masked deposit numbers. Requires account_numbers scope, product, and a user token.
  • Reveal Full Account Number returns the full, unmasked deposit numbers. Requires account_numbers scope, product, and a user token with numbers:reveal.
  • Get Account Owner Identity returns the account owner’s name, address, email, and phone. Requires identity scope, product, and a user token.

Deposit numbers are masked by default

GET .../accounts/{account_id}/numbers returns the account number masked (for example, ••••3388) alongside the routing number, which is returned unmasked since routing numbers are public per institution. This is safe to display and to poll.

The full, unmasked account number requires a separate call, POST .../accounts/{account_id}/numbers/reveal. Every reveal is audit-logged and rate-limited per user. Treat the response as a one-time read for immediate use, such as initiating a deposit, and don’t store it unencrypted. See Scoped API Keys for why revealing a full account number needs a key with account_numbers scope plus an ephemeral user token, on top of the base connection.

Owner identity is answered per account, not per user

GET .../accounts/{account_id}/identity returns the administrator-reported owner of that specific account, names, emails, phones, and addresses. This is deliberately scoped to the account, not aggregated across a user’s connections, because the question “who owns the account I’m about to deposit into” must be answered from that account’s own source. Since HSAs are individually owned, expect exactly one owner. This is a different endpoint from a user’s originated identity (the contact details supplied when the user was created), which lives at GET /users/{user_id}/identity instead.

Reimbursement#

Once a user’s expenses are eligible, eligible funds can be reimbursed from their HSA/FSA back to them. See Reimbursement for the preconditions, the status lifecycle, and how a reimbursement can fail.

Next steps