API reference · v1
Every endpoint, as it actually behaves.
The complete v1 surface: request fields, validation bounds, status codes and rate limits, documented from the running implementation. New here? Start with the quick start. Base URL for all paths: https://truefills.com.
Conventions
- Bearer auth. Authenticated requests send
Authorization: Bearer YOUR_KEY. There are two key kinds: a creator key minted when you register a strategy, and a feed key minted for a paid subscription. Both are shown once, stored only as SHA-256 hashes, and compared in constant time. A wrong or missing key returns 401. - JSON only. Request bodies must be JSON with
Content-Type: application/json. A body that fails to parse returns 400 with a specific error message. Every response is JSON. - Rate limits. Exceeding a limit returns 429 with body
{"error":"rate limit exceeded; slow down and retry","retryAfterSec":N}and aRetry-Afterheader in seconds. Wait that long, then retry. Limits are keyed per IP for unauthenticated writes and per key for authenticated calls; exact numbers are listed on each endpoint below. - Append-only. A posted order is sealed into its strategy’s public hash chain the moment it arrives: each entry stores the previous entry’s hash and its own SHA-256 over that link plus the order body. Nothing can be edited or deleted afterward, by anyone, including us.
Strategies
Register a strategy and mint its creator API key. Requires a signed-in session, and the strategy belongs to that account from the moment it exists. The key appears once in this response and is stored only as a hash; it cannot be recovered. The strategy name as it appears in the URL (the slug field) is derived from the name you give: lowercased, non-alphanumerics collapsed to dashes, trimmed to 40 characters.
Endpoint
https:// truefills.com/ api/ v1/ strategiesParameters
| Parameter | Type | Constraints |
|---|---|---|
| namestring | string | Required. 60 characters or fewer after trimming. Must leave a URL name of at least 3 characters. Platform and route names are reserved, and the derived URL name must not already be taken, including by a strategy that has been deleted. |
Example
curl -X POST https://truefills.com/api/v1/strategies \
-H "Content-Type: application/json" \
-H "Cookie: amx_session=<your session cookie>" \
-d '{"name": "My Mean Reversion Strategy"}'Success response (201)
{
"slug": "my-mean-reversion-strategy",
"name": "My Mean Reversion Strategy",
"apiKey": "f3a9...48 hex characters",
"note": "Store this key now; it is shown once. Post orders to /api/v1/strategies/my-mean-reversion-strategy/orders with Authorization: Bearer <key>."
}Errors
- 400 body is not JSON, or “name” is missing or not a string
- 401 no signed-in session; create the strategy on your account page or send your session cookie
- 409 name over 60 characters, URL name under 3 characters, reserved name, or that name already taken
- 429 rate limit exceeded; honor Retry-After
Public list of all strategies: Printhouse first, then every registered user strategy. New user strategies start in mode “unverified”.
Endpoint
https:// truefills.com/ api/ v1/ strategiesParameters
None.
Example
curl https://truefills.com/api/v1/strategies
Success response (200)
{
"strategies": [
{ "slug": "printhouse", "name": "Printhouse", "flagship": true, "mode": "paper" },
{ "slug": "my-mean-reversion-strategy", "name": "My Mean Reversion Strategy", "createdAt": "2026-09-05T14:02:11.412Z", "mode": "unverified" }
]
}Errors
- none this endpoint always returns 200
Public record for one strategy. User strategies return registration data plus the head of their order chain. Printhouse's slug returns a richer record: live stats, the equity series, verification pointers and the URL of its published chain file. Responses may be cached for up to an hour.
Endpoint
https:// truefills.com/ api/ v1/ strategies/ :slugParameters
None.
Example
curl https://truefills.com/api/v1/strategies/my-mean-reversion-strategy
Success response (200), user strategy
{
"slug": "my-mean-reversion-strategy",
"name": "My Mean Reversion Strategy",
"mode": "unverified",
"createdAt": "2026-09-05T14:02:11.412Z",
"orderCount": 12,
"chainHead": "9c41...hash of the latest sealed order, null when empty"
}
// GET https://truefills.com/api/v1/strategies/printhouse returns instead:
// { "slug", "name", "flagship": true, "mode", "startedLive",
// "stats": { "equity", "totalPlPct", ... }, "equitySeries": [{ "date", "equity" }, ...],
// "verification": { "source", "chain", "records" }, "chainUrl": "/chain/printhouse.jsonl" }
// Between the 16:00 bell and the broker publishing that day's close (the next
// morning), the last equitySeries point is the 16:00 reading and carries
// "provisional": true. The published close replaces it.Errors
- 404 unknown strategy name
Orders
Post a trade as your strategy makes it. Fills only: there are no limit or stop orders, and nothing you send sets the price. The server stamps refPrice, the market price observed on arrival, seals it with the order and appends both to the strategy's public hash chain, where they cannot be changed afterward.
Endpoint
https:// truefills.com/ api/ v1/ strategies/ :slug/ ordersParameters
| Parameter | Type | Constraints |
|---|---|---|
| action"buy" | "sell" | "buy" | "sell" | Required. |
| symbolstring | string | Required. Uppercase ticker matching ^[A-Z][A-Z0-9.]{0,9}$ (1 to 10 characters). |
| qtynumber | number | Required. Greater than 0, at most 10,000,000. |
| type"market" | "market" | Optional, and market is the only value. A limit or stop order, or any price, is refused with 400. |
Example
curl -X POST https://truefills.com/api/v1/strategies/my-mean-reversion-strategy/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"action":"buy","symbol":"AAPL","qty":10}'Success response (201)
{
"sealed": true,
"order": {
"seq": 12,
"ts": "2026-09-05T14:31:07.412Z",
"action": "buy",
"symbol": "AAPL",
"qty": 10,
"type": "market",
"refPrice": 150.02,
"prevHash": "9c41...hash of the previous entry, GENESIS for the first",
"hash": "e07b...sha256 over prevHash plus this order body"
}
}Errors
- 400 body is not JSON, a field fails validation, or the order names a limit, stop or price; the error message says which
- 401 invalid or missing API key for this strategy
- 429 rate limit exceeded; honor Retry-After
refPrice is left out of the sealed entry only when no market price was observable on arrival.
The hash-chained order log for a strategy, oldest first, Printhouse included. Everyone gets each entry's sequence, time and hashes, so anyone can recompute the chain. The trade inside each entry (symbol, side, size, price) goes to the strategy's owner, paying subscribers and accounts running it, identified by session cookie or by the feed key of a paid subscription. A strategy with no price shows it to everyone.
Endpoint
https:// truefills.com/ api/ v1/ strategies/ :slug/ ordersParameters
None.
Example
curl https://truefills.com/api/v1/strategies/my-mean-reversion-strategy/orders \ -H "Authorization: Bearer YOUR_FEED_KEY"
Success response (200), with access to the trades
{
"orders": [
{
"seq": 0,
"ts": "2026-09-04T19:55:01.002Z",
"action": "buy",
"symbol": "AAPL",
"qty": 10,
"type": "market",
"refPrice": 149.87,
"prevHash": "GENESIS",
"hash": "9c41..."
}
],
"total": 1
}Errors
- 404 unknown strategy name
Without access each entry keeps seq, ts, prevHash and hash, with redacted: true, and the response adds gated: true and a note saying who sees the trades.
Subscriptions and feed
Mint a feed key for a strategy you pay for, so your own software can read its trades. Requires a signed-in session with an active paid subscription to that strategy; the key belongs to that account. Asking again returns the existing subscription with a 200 and no new key; keys cannot be recovered. Running a strategy shows its trades too, signed in, with no key.
Endpoint
https:// truefills.com/ api/ v1/ subscriptionsParameters
| Parameter | Type | Constraints |
|---|---|---|
| strategystring | string | Required. The strategy name as it appears in its address (its slug); lowercased server-side. |
Example
curl -X POST https://truefills.com/api/v1/subscriptions \
-H "Content-Type: application/json" \
-H "Cookie: amx_session=<your session cookie>" \
-d '{"strategy":"printhouse"}'Success response (201; 200 if already subscribed)
{
"subscriptionId": "3f0e8a4c-7c1d-4e9a-9f2b-1a6d8c0e5b42",
"strategy": "printhouse",
"apiKey": "b7d2...48 hex characters",
"note": "Store this key now; it is shown once. Poll /api/v1/feed with Authorization: Bearer <key>. It reads the trades while the paid subscription is active."
}Errors
- 400 body is not JSON
- 401 no signed-in session
- 403 no active paid subscription to this strategy
- 404 unknown strategy name
- 429 rate limit exceeded; honor Retry-After
Latest orders for a strategy whose trades you may see: one you pay for, or one running in your account. Two ways in: the feed key of a paid subscription as a bearer token, or a signed-in session (add ?strategy=slug to pick one; Printhouse is the default). User strategies return their last 50 sealed orders. Printhouse returns live orders read directly from the broker when the connection is configured, otherwise an empty list with an explanatory note.
Endpoint
https:// truefills.com/ api/ v1/ feedParameters
None.
Example
curl https://truefills.com/api/v1/feed \ -H "Authorization: Bearer YOUR_FEED_KEY"
Success response (200), user strategy
{
"strategy": "my-mean-reversion-strategy",
"orders": [ ...last 50 sealed orders, same shape as the public order log... ],
"note": "Latest sealed orders for your subscribed strategy."
}
// Flagship feed entries come from the broker and look like:
// { "ts", "action", "symbol", "qty", "type", "limit"?, "stop"?, "status" }Errors
- 401 invalid feed key, or neither a key nor a signed-in session
- 403 no active paid subscription behind the key, or the signed-in account neither pays for the strategy nor runs it
- 429 rate limit exceeded; honor Retry-After
- 503 Printhouse's broker feed temporarily unavailable; retry shortly
GET /api/v1/subscriptions serves the same handler; /api/v1/feed is the documented path.
Broker connections
Read-only account links power broker-sourced records. These endpoints use the signed-in browser session, not API keys: broker links belong to people, not strategies. Credentials are entered on the broker’s own portal, never here, and no order placement exists on this platform.
Registers the signed-in user with the broker-connection provider (once) and returns a one-time portal URL. Open it, pick your brokerage, sign in there; the link created is read-only.
Endpoint
https:// truefills.com/ api/ v1/ broker/ connectParameters
None.
Example
curl -X POST https://truefills.com/api/v1/broker/connect \ -H "Cookie: your TrueFills session"
Success response (200)
{
"redirect": "https://app.snaptrade.com/connect?...one-time portal URL"
}Errors
- 401 sign in required
- 429 rate limit exceeded; honor Retry-After
- 502 the connection provider rejected the request; the error message says which step failed
- 503 broker connections are not enabled yet on this deployment
Connected brokerage accounts for the signed-in user: institution, account name, balance. Read-only data. Returns linked: false with an empty list when no broker has been connected.
Endpoint
https:// truefills.com/ api/ v1/ broker/ accountsParameters
None.
Example
curl https://truefills.com/api/v1/broker/accounts \ -H "Cookie: your TrueFills session"
Success response (200)
{
"linked": true,
"accounts": [
{
"id": "acc_...",
"name": "Individual",
"institution": "Robinhood",
"logo": "https://...institution logo, null when unknown",
"balance": { "amount": 12450.33, "currency": "USD" }
}
]
}Errors
- 401 sign in required
- 503 broker connections are not enabled yet on this deployment
Public list of supported brokerages. Served from a committed snapshot when the live provider list is unavailable, so it never renders empty. Responses may be cached for up to an hour.
Endpoint
https:// truefills.com/ api/ v1/ broker/ vendorsParameters
None.
Example
curl https://truefills.com/api/v1/broker/vendors
Success response (200)
{
"vendors": [
{ "slug": "SCHWAB", "name": "Schwab", "logo": "https://...or null" },
{ "slug": "FIDELITY", "name": "Fidelity", "logo": null }
]
}Errors
- none this endpoint always returns 200