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 trades for a brokerage connection. Trades are fetched live from the brokerage provider. No investment data is stored on Redbark servers.
This endpoint requires a Professional plan subscription. Saver-plan API keys get a generic 403 (API access requires a Developer or Professional plan). Developer-plan keys get a 403 with "code": "professional_required" specifically for this endpoint.
Request
| Header | Required | Description |
|---|
Authorization | Yes | Bearer YOUR_API_KEY |
Trialing customers retain general API access but do not receive brokerage access. The brokerage entitlement requires an active (or past_due) subscription on a Professional price — a trialing Professional subscription returns a 403 professional_required on /holdings and /trades.
| Header | Description |
|---|
X-Cache | HIT, MISS, or BYPASS. Set unconditionally by the cache layer; useful for debugging stale data and tuning poll frequency. |
X-Redbark-Truncated | true if the row ceiling fired (see Response limits). |
Query parameters
| Parameter | Type | Required | Default | Description |
|---|
connectionId | string | Yes | | Brokerage connection to fetch trades from |
accountId | string | No | All accounts | Filter to a specific brokerage account |
accountIds | string | No | All accounts | Comma-separated subset of brokerage account UUIDs on the connection (max 4 000 chars). Takes precedence over accountId when both are passed. Any id not on the connection is a 404. |
from | string | No | (provider default) | Start date (YYYY-MM-DD or ISO 8601). No from is passed through to the brokerage provider as-is; SnapTrade’s behaviour without from depends on the underlying broker. |
to | string | No | (provider default) | End date (YYYY-MM-DD or ISO 8601) |
limit | integer | No | 200 | Maximum items to return (1 to 500) |
offset | integer | No | 0 | Number of items to skip |
connectionId must refer to a brokerage connection. Passing a banking connection ID returns a 400 error. Use the List Connections endpoint to find your brokerage connection IDs.
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 null (the exact total isn’t known when paging stops early).
- Continue paginating with the next
offset + limit window — the same cap applies per request, not per session.
Response
Cached at the edge for 10 minutes. Cache key is userId + path + sorted query string, so different orderings of query parameters (or different deduplications of accountIds) produce different cache entries.
{
"data": [
{
"id": "2026-03-15-VAS.AX-BUY-4487.5-50-2026-03-17-9.5-",
"accountId": "d4e5f6a7-b8c9-0123-d4e5-f6a7b8c90123",
"accountName": "Trading Account",
"symbol": "VAS.AX",
"name": "Vanguard Australian Shares ETF",
"type": "buy",
"quantity": "50",
"price": "89.75",
"currency": "AUD",
"totalAmount": "4487.5",
"fees": "9.5",
"tradeDate": "2026-03-15",
"settlementDate": "2026-03-17",
"description": null
},
{
"id": "2026-03-10-CBA.AX-SELL-2846-20-2026-03-12-9.5-",
"accountId": "d4e5f6a7-b8c9-0123-d4e5-f6a7b8c90123",
"accountName": "Trading Account",
"symbol": "CBA.AX",
"name": "Commonwealth Bank of Australia",
"type": "sell",
"quantity": "20",
"price": "142.3",
"currency": "AUD",
"totalAmount": "2846",
"fees": "9.5",
"tradeDate": "2026-03-10",
"settlementDate": "2026-03-12",
"description": null
}
],
"pagination": {
"total": null,
"limit": 200,
"offset": 0,
"hasMore": true
}
}
Trade object
| Field | Type | Description |
|---|
id | string | Deterministic trade identifier built from tradeDate-symbol-TYPE-totalAmount-quantity-settlementDate-fees-description. Treat as an opaque string — the format is not a stable API contract. |
accountId | string | UUID of the brokerage account |
accountName | string | Account display name |
symbol | string | Ticker symbol (e.g. VAS.AX, AAPL) |
name | string | null | Security name |
type | string | One of "buy", "sell", "dividend", "split", "transfer", "fee", "interest", or "other" |
quantity | string | Number of units traded (decimal string; supports fractional shares) |
price | string | Price per unit at execution |
currency | string | Currency code (e.g. AUD, USD) |
totalAmount | string | Total value of the trade |
fees | string | null | Brokerage fees charged |
tradeDate | string | Date or ISO 8601 timestamp when the trade executed — the provider passes through whatever SnapTrade returns in trade_date. May be a date-only string (YYYY-MM-DD) or a full ISO datetime depending on the broker. |
settlementDate | string | null | Settlement date/timestamp — same format caveat as tradeDate |
description | string | null | Additional description from the broker, if any |
All monetary and quantity fields are strings to preserve decimal precision. Parse them as decimals in your application.
| Field | Type | Description |
|---|
total | integer | null | Total number of matching trades. Returns null when hasMore is true (the total is not known until all pages have been fetched). When hasMore is false, total is the exact count. |
limit | integer | Limit applied to this request |
offset | integer | Offset applied to this request |
hasMore | boolean | true 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.
| Status | code | When |
|---|
400 | invalid_params | Missing connectionId |
400 | (none) | Invalid date format (details[] lists the offending fields) |
400 | invalid_date_range | Invalid date range: frommust be on or beforeto“ |
400 | wrong_endpoint_for_category | Trades are only available for brokerage connections (passed a banking connection) |
403 | (none) | API access requires a Developer or Professional plan (Saver-plan keys) |
403 | professional_required | Developer-plan key hitting a brokerage endpoint |
404 | connection_not_found / account_not_found | Connection 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) | Brokerage provider temporarily unavailable. Retry later. |
Example error body:
{
"error": {
"message": "Trades are only available for brokerage connections",
"code": "wrong_endpoint_for_category"
}
}
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 trades for a connection
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.redbark.co/v1/trades?connectionId=e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b"
Filter by date range
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.redbark.co/v1/trades?connectionId=e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b&from=2026-01-01&to=2026-03-31"
Paginate
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.redbark.co/v1/trades?connectionId=e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b&limit=50&offset=50"
Python: fetch all pages
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://api.redbark.co"
all_trades = []
offset = 0
limit = 200
while True:
resp = requests.get(
f"{BASE}/v1/trades",
headers={"Authorization": f"Bearer {API_KEY}"},
params={
"connectionId": "e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b",
"from": "2026-01-01",
"to": "2026-03-31",
"limit": limit,
"offset": offset,
},
)
data = resp.json()
all_trades.extend(data["data"])
if not data["pagination"]["hasMore"]:
break
offset += limit
print(f"Fetched {len(all_trades)} trades")
JavaScript: fetch all pages
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.redbark.co";
const allTrades = [];
let offset = 0;
const limit = 200;
while (true) {
const params = new URLSearchParams({
connectionId: "conn_abc123",
from: "2026-01-01",
to: "2026-03-31",
limit: String(limit),
offset: String(offset),
});
const resp = await fetch(`${BASE}/v1/trades?${params}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data, pagination } = await resp.json();
allTrades.push(...data);
if (!pagination.hasMore) break;
offset += limit;
}
console.log(`Fetched ${allTrades.length} trades`);