Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/midday-ai/midday/llms.txt

Use this file to discover all available pages before exploring further.

Midday supports three major banking providers to connect bank accounts across different regions. All providers use OAuth flows and webhook-based sync.

Architecture

The banking package (~/workspace/source/packages/banking/) provides a unified interface for all providers:
import { Provider } from "@midday/banking";

const provider = new Provider({ provider: "plaid" });

// Unified API works across all providers
const accounts = await provider.getAccounts({ accessToken, institutionId });
const transactions = await provider.getTransactions({ accessToken, accountId });
const balance = await provider.getAccountBalance({ accessToken, accountId });

Provider Interface

All banking providers implement the same interface (~/workspace/source/packages/banking/src/interface.ts):
interface Provider {
  getTransactions(params: GetTransactionsRequest): Promise<GetTransactionsResponse>;
  getAccounts(params: GetAccountsRequest): Promise<GetAccountsResponse>;
  getAccountBalance(params: GetAccountBalanceRequest): Promise<GetAccountBalanceResponse>;
  getInstitutions(params: GetInstitutionsRequest): Promise<GetInstitutionsResponse>;
  getHealthCheck(): Promise<boolean>;
  deleteAccounts(params: DeleteAccountsRequest): void;
  getConnectionStatus(params: GetConnectionStatusRequest): Promise<GetConnectionStatusResponse>;
  deleteConnection(params: DeleteConnectionRequest): void;
}

GoCardLess

GoCardLess provides Open Banking access to European banks via PSD2.

Configuration

1

Get API Credentials

Sign up at GoCardLess Bank Account Data and create an application.
2

Set Environment Variables

Add your credentials to your environment:
GOCARDLESS_SECRET_ID=your_secret_id
GOCARDLESS_SECRET_KEY=your_secret_key
3

Initialize Provider

The provider automatically handles token refresh:
import { Provider } from "@midday/banking";

const provider = new Provider({ provider: "gocardless" });

Features

  • Coverage: European banks supporting PSD2 Open Banking
  • Authentication: OAuth via requisitions (consent links)
  • Token Management: Automatic access token refresh
  • Data: Transactions, balances, account details

API Usage

GoCardLess uses requisition IDs for account access:
// Get accounts using requisition ID
const accounts = await provider.getAccounts({ id: requisitionId });

// Get transactions for an account
const transactions = await provider.getTransactions({
  accountId: account.id,
  accountType: account.type,
  latest: true // Only fetch recent transactions
});

// Get account balance
const balance = await provider.getAccountBalance({
  accountId: account.id,
  accountType: account.type
});

Implementation Details

Location: ~/workspace/source/packages/banking/src/providers/gocardless/
  • API Client: gocardless-api.ts handles authentication and requests
  • Provider: gocardless-provider.ts implements the unified interface
  • Transforms: transform.ts normalizes GoCardLess data to Midday format
GoCardLess tokens expire after 1 hour. The API client automatically:
  1. Caches access tokens with TTL
  2. Uses refresh token when access token expires
  3. Generates new token pair when refresh token expires
  4. Stores tokens in banking cache
See: ~/workspace/source/packages/banking/src/providers/gocardless/gocardless-api.ts:67-81

Plaid

Plaid provides banking connectivity for US and Canadian financial institutions.

Configuration

1

Get API Credentials

Sign up at Plaid Dashboard and create an application.
2

Set Environment Variables

PLAID_CLIENT_ID=your_client_id
PLAID_SECRET=your_secret
PLAID_ENVIRONMENT=production # or 'sandbox' for testing
3

Configure Webhook URL

Plaid sends webhooks to:
  • Production: https://api.midday.ai/webhook/plaid
  • Sandbox: https://api-staging.midday.ai/webhook/plaid
The webhook URL is automatically configured during Link token creation.

Features

  • Coverage: 12,000+ US and Canadian financial institutions
  • Authentication: Plaid Link web component
  • Sync Mode: Webhook-based with transactions sync API
  • Balance Types: Available, current, limit (for credit accounts)

API Usage

Plaid uses access tokens for account access:
// Exchange public token from Link for access token
const exchangeResponse = await plaidApi.exchangePublicToken({
  publicToken: linkPublicToken,
  institutionId: institutionId
});

const accessToken = exchangeResponse.access_token;

// Get accounts
const accounts = await provider.getAccounts({ 
  accessToken,
  institutionId 
});

// Get transactions (uses Plaid Sync API)
const transactions = await provider.getTransactions({
  accessToken,
  accountId: account.id,
  accountType: account.type,
  latest: false // Full sync
});

Implementation Details

Location: ~/workspace/source/packages/banking/src/providers/plaid/
  • API Client: plaid-api.ts uses official Plaid Node SDK
  • Provider: plaid-provider.ts implements the unified interface
  • Transforms: transform.ts normalizes Plaid data
Plaid sends webhooks for transaction updates:Transaction Webhooks:
  • SYNC_UPDATES_AVAILABLE - New transactions to sync
  • DEFAULT_UPDATE - Legacy webhook for transaction updates
  • INITIAL_UPDATE - First sync after connection
  • HISTORICAL_UPDATE - Historical data sync
  • TRANSACTIONS_REMOVED - Transactions deleted by bank
Item Webhooks:
  • ERROR - Connection error (marks connection as disconnected)
  • PENDING_DISCONNECT - User initiated disconnection
  • USER_PERMISSION_REVOKED - User revoked access
  • LOGIN_REPAIRED - User reconnected account
See: ~/workspace/source/apps/api/src/rest/routers/webhooks/plaid/index.ts

Health Check

Plaid health status is checked via their public status page:
const isHealthy = await provider.getHealthCheck();
// Checks https://status.plaid.com/api/v2/status.json

Teller

Teller provides modern banking API access for US banks.

Configuration

1

Get API Credentials

Sign up at Teller.io and get your certificate and private key.
2

Set Environment Variables

Teller uses certificate-based authentication:
TELLER_CERT_BASE64=base64_encoded_certificate
TELLER_KEY_BASE64=base64_encoded_private_key
3

Configure Webhook

Set your webhook URL in the Teller dashboard:
https://api.midday.ai/webhook/teller

Features

  • Coverage: Major US banks
  • Authentication: Certificate-based API access
  • Balance Strategy: Free balance from transaction running_balance
  • Account Details: Instant access to routing/account numbers

API Usage

Teller uses access tokens (enrollment tokens):
// Get accounts with access token
const accounts = await provider.getAccounts({ 
  accessToken: enrollmentToken 
});

// Accounts include routing/account numbers
accounts.forEach(account => {
  console.log(account.routing_numbers);
  console.log(account.account_number);
});

// Get transactions
const transactions = await provider.getTransactions({
  accessToken: enrollmentToken,
  accountId: account.id,
  accountType: account.type,
  latest: true // Fetch last 100 transactions
});

// Get balance (free via running_balance)
const balance = await provider.getAccountBalance({
  accessToken: enrollmentToken,
  accountId: account.id
});

Implementation Details

Location: ~/workspace/source/packages/banking/src/providers/teller/
  • API Client: teller-api.ts handles certificate authentication
  • Provider: teller-provider.ts implements the unified interface
  • Transforms: transform.ts normalizes Teller data
Teller charges for balance API calls, but includes running_balance in transaction data for free.Midday’s balance strategy:
  1. Fetch recent transactions (free)
  2. Extract running_balance from the first transaction with a balance
  3. Return balance without extra API cost
This works for both depository and credit accounts. Only fails for brand new accounts with no transactions (rare).See: ~/workspace/source/packages/banking/src/providers/teller/teller-api.ts:84-100
Teller sends webhooks for:
  • enrollment.disconnected - User disconnected their account
  • transactions.processed - New transactions available
  • account.number_verification.processed - Account verification complete
  • webhook.test - Test webhook event
See: ~/workspace/source/apps/api/src/rest/routers/webhooks/teller/index.ts

Connection Management

Health Monitoring

Check the health of all banking providers:
const provider = new Provider({ provider: "plaid" });
const health = await provider.getHealthCheck();

if (!health.plaid.healthy) {
  // Handle Plaid outage
}

Connection Status

Check if a connection is still valid:
const status = await provider.getConnectionStatus({ 
  accessToken,
  id: connectionId 
});

if (status.status === "disconnected") {
  // Prompt user to reconnect
}

Deleting Connections

// Delete all accounts for a connection
await provider.deleteAccounts({ accessToken });

// Delete the connection itself
await provider.deleteConnection({ accessToken, id: connectionId });

Error Handling

All providers use unified error handling via ProviderError:
import { ProviderError, getProviderErrorDetails } from "@midday/banking";

try {
  await provider.getTransactions({ ... });
} catch (error) {
  if (error instanceof ProviderError) {
    const details = getProviderErrorDetails(error);
    console.error(details.message, details.code, details.statusCode);
  }
}
See: ~/workspace/source/packages/banking/src/utils/error.ts

Rate Limiting

All provider API calls use automatic retry with exponential backoff:
import { withRateLimitRetry } from "@midday/banking/utils/retry";

const data = await withRateLimitRetry(() => 
  api.getSomeData()
);
Defaults:
  • Max retries: 3
  • Exponential backoff: 1s, 2s, 4s
  • Rate limit detection: HTTP 429 or provider-specific codes

Testing

process.env.PLAID_ENVIRONMENT = "sandbox";

const provider = new Provider({ provider: "plaid" });
// Uses https://sandbox.plaid.com
Never commit real API credentials to version control. Use environment variables and keep secrets in secure storage.

Build docs developers (and LLMs) love