> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trdrs.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Publish a datafeed to your traders

> Run a small HTTP feed, register it with us, and your symbols appear in the platform for your traders and nobody else.

Publish a datafeed when your market comes from a venue the engine does not connect to. You run a
small read-only HTTP server, we poll it, and the symbols show up in your traders' symbol search,
charts, and live streams alongside everything else on the platform. Your traders never talk to your
server — the engine does.

Reach for this second. If your traders' data comes from a venue login you already issue, use
[venue entitlements](/guides/venue-data) instead: there is no feed to run, no server to keep up, and
the data flows under each trader's own subscription. A published feed exists for the markets that
path cannot reach — your firm's internal indices, a synthetic product, a venue we have not
integrated.

## Who can see it

Only your traders. A symbol you publish is visible to a trader linked to your firm — one holding an
account you issued, or one whose registration their own venue login satisfied. To everyone else on
the platform, including other firms, the symbol does not exist: it is absent from search, absent
from symbol resolution, and a request naming it directly answers exactly as a symbol nobody
published does. There is no request shape and no error message that tells one case from the other.

Your symbols also cannot collide with the shared catalog. The engine namespaces every published
symbol under your firm, so you can publish `ES` without touching the CME contract of the same name —
your traders resolve yours, everyone else resolves theirs.

## What your firm builds

A UDF datafeed: three read-only JSON endpoints over HTTPS. The contract is the one Quick Charts
already documents and tests against in `createUdfDatafeed` (`src/udfDatafeed.ts`), which is the
authority for every shape below — a server that already drives Quick Charts drives this engine
unchanged, with nothing to add.

### `GET /config`

Declare what you serve. Fetched once and cached.

```json theme={null}
{
  "supports_search": true,
  "supported_resolutions": ["1", "5", "15", "60", "1D"],
  "exchanges": [{ "value": "ACME", "name": "Acme", "desc": "Acme markets" }]
}
```

`supported_resolutions` is a promise the engine holds you to: a resolution you did not declare is
refused before a request goes out, because a UDF server asked for an unlisted bar size often answers
a different one rather than an error. Declare an empty list, or serve no `/config` at all, and the
engine assumes the protocol's defaults and restricts nothing.

### `GET /search?query=&limit=`

Return the matching symbols.

```json theme={null}
[{ "symbol": "ACME1", "description": "Acme index", "exchange": "ACME", "type": "index" }]
```

`type` is your own vocabulary. It is passed through to the trader verbatim rather than remapped, so
call an index an index.

If you answer `supports_search: false`, serve `GET /symbol_info?group=<exchange>` instead, in the
protocol's columnar form — parallel arrays keyed `symbol`, `ticker`, `description`,
`exchange-listed`, `type`, with a scalar applying to every row. The engine fetches each exchange you
listed in `/config` once and searches them locally. In that mode `/config` must list at least one
exchange, or there is nothing to enumerate.

### `GET /history?symbol=&resolution=&from=&to=&countback=`

Return OHLCV bars in the protocol's columnar form. Times are epoch seconds.

```json theme={null}
{ "s": "ok", "t": [1757376000], "o": [100], "h": [101], "l": [99], "c": [100.5], "v": [1200] }
```

Three answers, and the difference between them matters:

* `s: "ok"` with the arrays — bars, oldest first.
* `s: "no_data"` — an honest empty window. The chart stops paging back.
* `s: "error"` with `errmsg` — this symbol or this window is bad. It is a per-symbol answer and does
  not count against your feed's health, so one trader's typo never takes your feed off the air.

Read `to` as exclusive, the way the protocol writes it — the rightmost bar is not included. The
engine bridges its own inclusive window to yours, so page seams never drop a bar. `countback`, when
present, outranks `from`: return that many bars at or before `to`.

Resolutions use the protocol's own grammar: seconds as `30S`, minutes bare as `5`, hours as minutes
(`60` is one hour), then `1D`, `1W`, `1M`. Omit `v` and every bar reads as volume 0.

### What you do not build

No quotes endpoint. The engine reads bars only, and a chart on a published symbol shows `—` for
bid/ask rather than a number nobody quoted. No push channel either — the engine polls, so an
ordinary HTTP server is the whole requirement.

## Register it with us

Registration runs through us during onboarding. Send your account manager:

* the base URL of your feed, e.g. `https://feed.yourfirm.com/udf`;
* the `Authorization` header value your server expects, if it wants one — we send it verbatim on
  every request, and it is stored as a secret that no read of your firm's record returns.

We set both on your firm record, and your symbols appear for your traders within the minute. Clear
the URL and they disappear the same way. There is no self-serve registration today; that is a
separate decision, not an oversight.

Serve the feed over HTTPS from an address reachable on the public internet, and keep it behind a
credential — the header above is the whole gate on your data.

## How the engine reads it

* History comes straight from `/history` on the window the chart asks for.
* Live bars come from polling the tail of `/history` every 10 seconds — the same cadence Quick
  Charts uses, so a server tuned for that adapter sees the same request rate from us. The newest bar
  re-emits as it forms and seals when the next one opens.
* Traders share the poll. Ten of your traders watching one symbol cost your server one request every
  10 seconds, not ten, and those subscriptions are counted against the same engine capacity every
  other feed is counted against.
* Every request carries a 10-second deadline, so a slow answer never hangs a chart.

## When your feed goes down

Your feed going down costs your symbols and nothing else.

After three consecutive transport failures — a timeout, a connection error, a non-2xx answer, an
unparseable body — the engine marks your feed down and your symbols become absent for your traders:
they stop listing in search, and a request naming one answers as an unknown symbol would. The rest
of the platform is untouched, other firms are untouched, and no shared request fails because of it.

While your feed is down the engine stops asking on every chart and probes once every 30 seconds
instead, so a server that is already struggling is not hammered by the platform. One successful
answer clears the state and your symbols return. We log the transition each way and see it on our
own dashboards, so a feed that stays down is something we will raise with you.

A `s: "error"` answer is never counted as down. That is you telling us about one symbol, which is
the feed working.

## What this does not cover

Trading. A published symbol charts; no order path binds to it, so your traders cannot take a
position in a market you publish this way. Quotes, push ingestion, and self-serve registration are
all deliberately out of the first version.
