Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.redbark.co/llms.txt

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

The REST API is in beta. This endpoint’s response shape may change.
Returns a paginated list of posted transactions for a given connection. Transactions are fetched live from the banking provider. No transaction data is stored on Redbark servers.

Request

GET /v1/transactions

Headers

HeaderRequiredDescription
AuthorizationYesBearer YOUR_API_KEY
Trialing customers retain full API access (including brokerage endpoints if their trial plan is Professional).

Response headers

HeaderDescription
X-CacheHIT, MISS, or BYPASS. Set unconditionally by the cache layer; useful for debugging stale data and tuning poll frequency.
X-Redbark-Truncatedtrue if the row ceiling fired (see Response limits).
Deprecation / SunsetPresent when accountId is omitted (see Tip above).

Caching

Responses are cached at the edge for 30 minutes. Cache key is userId + path + sorted query string, so different orderings of query parameters produce different cache entries.

Query parameters

ParameterTypeRequiredDefaultDescription
connectionIdstringYesConnection to fetch transactions from
accountIdstringNoAll accountsFilter to a specific account
fromstringNo30 days agoStart date (YYYY-MM-DD or ISO 8601)
tostringNoNowEnd date (YYYY-MM-DD or ISO 8601)
limitintegerNo200Maximum items to return (1 to 500)
offsetintegerNo0Number of items to skip
connectionId is required. Use the List Connections endpoint to get connection IDs.
Pass accountId whenever you can. It scopes the upstream provider call to a single account, which is faster, cheaper, and keeps you on the supported call shape. Calls that omit accountId currently return Deprecation: true and Sunset: Wed, 01 Sep 2027 00:00:00 GMT response headers — they still work, but plan to migrate before that date.

Response limits

To bound memory under wide date ranges, the service stops fetching upstream pages once it has roughly 5,000 matching rows for a single request. When this happens:
  • The response sets X-Redbark-Truncated: true.
  • pagination.hasMore is true and pagination.total is a lower bound rather than the exact count.
  • Continue paginating with the next offset + limit window — the same cap applies per request, not per session.
When accountId is omitted, the service additionally caps at 50 upstream provider pages. Because each page is filtered client-side to the accounts on this connection, this is a different truncation path that can trigger X-Redbark-Truncated: true at modest row counts on connections with many sibling accounts. Pass accountId to avoid it.

Response

{
  "data": [
    {
      "id": "e4a7f91b2c3d4e5f6a7b8c9d",
      "accountId": "a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890",
      "accountName": "Everyday Account",
      "status": "posted",
      "date": "2026-03-12",
      "datetime": "2026-03-11T13:00:00.000Z",
      "description": "Woolworths Sydney",
      "amount": "-45.50",
      "direction": "debit",
      "category": "FOOD_AND_DRINK",
      "merchantName": "Woolworths",
      "merchantCategoryCode": null
    },
    {
      "id": "f5b8a02c3d4e5f6a7b8c9d0e",
      "accountId": "a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890",
      "accountName": "Everyday Account",
      "status": "posted",
      "date": "2026-03-11",
      "datetime": "2026-03-10T13:00:00.000Z",
      "description": "Salary Payment",
      "amount": "3500.00",
      "direction": "credit",
      "category": "INCOME",
      "merchantName": null,
      "merchantCategoryCode": null
    }
  ],
  "pagination": {
    "total": 87,
    "limit": 200,
    "offset": 0,
    "hasMore": false
  }
}

Transaction object

FieldTypeDescription
idstringOpaque transaction identifier from the banking provider. Treat as an arbitrary string.
accountIdstringUUID of the account this transaction belongs to
accountNamestringAccount display name
statusstring"posted". The service requests only posted transactions from the provider — pending transactions are not returned by this endpoint. The response schema permits any string up to 64 chars, but "posted" is the only value emitted today.
datestringTransaction date in your account’s timezone (YYYY-MM-DD). Defaults to Australia/Sydney if no timezone is set. Change your timezone in Settings.
datetimestring | nullRaw ISO 8601 timestamp from the banking provider. Use this if you need to handle timezone conversion yourself.
descriptionstringTransaction description
amountstringSigned decimal string (e.g. "-45.50"). Negative for debits, positive for credits.
directionstring"credit" or "debit" (convenience field matching the sign of amount)
categorystring | nullRaw CDR primary-category code (see list below). Not all transactions have a category.
merchantNamestring | nullMerchant name, if available
merchantCategoryCodestring | nullMerchant category code (MCC), if available
The amount field is a string to preserve decimal precision. Parse it as a decimal in your application — not a float.

Categories

The category field returns the raw CDR primary-category code (uppercase, underscored) as assigned by the banking provider — not a human-readable label. Not all transactions have a category (the field is nullable).
category valueHuman-readable label
BANK_FEESBank Fees
ENTERTAINMENTEntertainment
FOOD_AND_DRINKFood & Drink
GOVERNMENT_AND_NON_PROFITGovernment & Non-Profit
HOME_IMPROVEMENTHome Improvement
INCOMEIncome
LOAN_PAYMENTSLoan Payments
MEDICALMedical
MERCHANDISEMerchandise
PERSONAL_CAREPersonal Care
RENT_AND_UTILITIESRent & Utilities
SERVICESServices
TRANSFER_INTransfer In
TRANSFER_OUTTransfer Out
TRANSPORTATIONTransportation
TRAVELTravel
Fetch this mapping programmatically from GET /v1/categories.
Categories depend on the banking provider and account type. Some transactions (e.g. direct debits, older transactions) may have a null category.

Pagination object

FieldTypeDescription
totalinteger | nullCount of posted transactions seen by the service for the filters. When hasMore is true the service may have stopped paging early, so total is a lower bound (and may be null if the count is unknown). When hasMore is false, total is exact.
limitintegerLimit applied to this request
offsetintegerOffset applied to this request
hasMorebooleantrue if more items exist beyond this page

Error responses

Errors use the standard envelope { "error": { "message": string, "code"?: string, "details"?: string[] } }. The optional code field is set for the structured cases below — clients should branch on code rather than parsing message.
StatuscodeWhen
400invalid_paramsMissing connectionId
400(none)Invalid date format (details[] lists the offending fields)
400invalid_date_rangeInvalid date range: frommust be on or beforeto“
400from_too_old`from` is too far in the past — banking providers serve at most ~7 years of history
400wrong_endpoint_for_categoryTransactions are only available for banking connections — use /v1/trades for brokerage connections
404connection_not_found / account_not_foundConnection or account not found, or does not belong to you
429(none)Rate limit exceeded — heavy bucket is 30/min per API key, plus a per-key cap of 4 concurrent in-flight requests (excess returns Too many concurrent requests). See Retry-After and X-RateLimit-Reset.
503(none)Banking provider temporarily unavailable. Retry-After: 30.
503upstream_breaker_openAfter 3 upstream failures within a 60s window for the same userId+connectionId, subsequent requests fail fast for ~60s. Retry-After reflects the remaining cooldown.
Example error body:
{
  "error": {
    "message": "`from` is too far in the past — banking providers serve at most ~7 years of history",
    "code": "from_too_old"
  }
}

Date validation

The from and to parameters accept:
  • Date strings: 2026-03-01
  • Full ISO 8601 / RFC 3339 with explicit timezone: 2026-03-01T00:00:00Z or 2026-03-01T00:00:00+10:00
Naive datetimes with no Z and no ±HH:MM offset are explicitly rejected. Invalid formats return a 400 with details:
{
  "error": {
    "message": "Invalid date parameters",
    "details": [
      "from: Must be YYYY-MM-DD or RFC3339 with timezone (e.g. 2026-05-09T23:35:19Z or 2026-05-09T23:35:19+10:00)"
    ]
  }
}

Examples

All transactions for a connection (last 30 days)

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.redbark.co/v1/transactions?connectionId=b7c4a1e2-8d3f-4e9a-9c5b-1f2a3e4d5c6b"

Filter by account and date range

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.redbark.co/v1/transactions?connectionId=b7c4a1e2-8d3f-4e9a-9c5b-1f2a3e4d5c6b&accountId=a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890&from=2026-01-01&to=2026-03-01"

Paginate

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.redbark.co/v1/transactions?connectionId=b7c4a1e2-8d3f-4e9a-9c5b-1f2a3e4d5c6b&limit=50&offset=50"

Python: fetch all pages

import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.redbark.co"

all_transactions = []
offset = 0
limit = 200

while True:
    resp = requests.get(
        f"{BASE}/v1/transactions",
        headers={"Authorization": f"Bearer {API_KEY}"},
        params={
            "connectionId": "b7c4a1e2-8d3f-4e9a-9c5b-1f2a3e4d5c6b",
            "from": "2026-01-01",
            "to": "2026-03-13",
            "limit": limit,
            "offset": offset,
        },
    )
    data = resp.json()
    all_transactions.extend(data["data"])

    if not data["pagination"]["hasMore"]:
        break
    offset += limit

print(f"Fetched {len(all_transactions)} transactions")

JavaScript: fetch all pages

const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.redbark.co";

const allTransactions = [];
let offset = 0;
const limit = 200;

while (true) {
  const params = new URLSearchParams({
    connectionId: "conn_abc123",
    from: "2026-01-01",
    to: "2026-03-13",
    limit: String(limit),
    offset: String(offset),
  });

  const resp = await fetch(`${BASE}/v1/transactions?${params}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
  const { data, pagination } = await resp.json();

  allTransactions.push(...data);

  if (!pagination.hasMore) break;
  offset += limit;
}

console.log(`Fetched ${allTransactions.length} transactions`);