# Nox FZE documentation > Every page of https://noxfze.com/docs in full, then the contact page: The record, Record format, version 1, Command-line verification, Synthetic example hour, Starting a record, Questions venues ask, Contact. Requests by email to contact@noxfze.com, subject "Venue record request (agent)". # The record Summary: Nox FZE, an independent company, records your venue's public market data. Each UTC hour becomes a sealed hour in a hash chain, delivered into storage you own within 15 minutes after the hour closes. If your storage or the recorder is unavailable, the hour arrives later. Anyone you share a sealed hour with can recompute its file hashes and its link to the hour before with openly available tools. ## What one sealed hour holds Each channel your venue publishes (trades, order book, funding) has one directory per UTC hour. It holds the frames exactly as received, a normalized form of trades and the order book, and a manifest. Each normalized row references the frame it came from. The manifest lists each file of the hour with its size and hash. It lists every reconnection and every gap Nox detects in your venue's message sequence. It carries the hash of the previous hour's manifest, which makes the hours a hash chain. Every UTC hour has a manifest, including an hour in which Nox received no messages. The hash of an hour's manifest is that hour's root, and the next hour's manifest carries it. This root shows only that the hour is unchanged since Nox FZE sealed it, and which messages Nox FZE received from the venue's public interfaces and when. It gives no opinion on the venue or on its markets, volume, statements, controls or systems. ## Who these pages are for - **Your venue's engineers**, who read the exact contract before the first sealed hour arrives. - **Anyone you share a sealed hour with**, such as a partner, a data aggregator or a researcher. - **AI agents working for your venue**, which read, cite and run these pages. Each page has a Markdown version, and [the complete documentation as one text file](https://noxfze.com/llms-full.txt) holds every page. ## Pages - [Record format, version 1](https://noxfze.com/docs/format): the layout, encodings, files and manifests of a sealed hour, and the checks a verifier makes. - [Command-line verification](https://noxfze.com/docs/verify): the manifest, each file's size and hash, and the link to the hour before, with `jq`, `b3sum` and `zstd`. - [Synthetic example hour](https://noxfze.com/docs/example): a synthetic sealed hour and the hour before it, as one download, with its listing and the expected result. - [Starting a record](https://noxfze.com/docs/start): the written request, the order form, storage you own, and the 30-day pilot. - [Questions venues ask](https://noxfze.com/docs/questions): short answers to the questions a venue asks before a record starts, each with the page that states it in full. To verify a sealed hour in your browser without installing anything, use [Verification, the in-browser check of a sealed hour](https://noxfze.com/verify). --- # Record format, version 1 Summary: Record format version 1 is the contract of every sealed hour. It states where the files of a sealed hour sit in storage you own, and how time, JSON and hashes are encoded. It defines the raw file, the normalized tables, and the hourly and daily manifests that form the hash chain. It lists the ten checks a verifier makes. Within version 1, only optional manifest fields and new columns may be added. What follows is the format document itself, unedited apart from its title. Status: draft. This document states what a segment contains and what a verifier checks. It is the public contract of format major 1. ## Layout ``` /recorder=/venue=/channel=/date=YYYY-MM-DD/ manifest.json daily manifest manifest.json.sig detached signature over the daily manifest hour=HH/ raw.jsonl.zst every frame exactly as received .parquet normalized tables of the channel manifest.json hourly manifest manifest.json.sig detached signature over the hourly manifest ``` Channels: `trades`, `book`, `funding`, `liquidations`. A frame belongs to the UTC hour of its frame time ("Raw file", below). ## Encodings - **Time.** int64 nanoseconds since the Unix epoch. In JSON, an RFC 3339 UTC string with the `Z` designator and exactly nine fractional digits (`2026-10-03T14:00:00.000000000Z`); one instant has one encoding. - **JSON.** Manifests and raw-file lines are RFC 8785 canonical JSON. Numbers are integers within ±(2^53 − 1); every other value is a string. - **Hashes.** BLAKE3, 32 bytes, lowercase hexadecimal. ## Raw file A frame's **frame time** is the earliest `receive_time` among its receipts that carry `clock_error_bound`, or among all its receipts when none does. Frames are ordered and assigned to hours by frame time, and normalized rows carry it in `receive_time`. `raw.jsonl.zst` is zstd-compressed; each line is one envelope, in order of frame time: | Field | Type | Meaning | |---|---|---| | `payload` | string | The frame: verbatim text, or base64 of a binary frame | | `payload_encoding` | `text` or `base64` | How `payload` encodes the frame | | `exchange_time` | time, optional | Time the venue stated for the frame; the earliest when it states several | | `receipts` | array | One per replica that received the frame | Each receipt: `replica` (`a` or `b`), `connection` (opaque), `receive_time`, `clock_offset` (the receiving host clock's estimated offset from UTC, in signed integer nanoseconds, positive when the host clock is fast), and `clock_error_bound` (a non-negative integer of nanoseconds bounding the absolute error of `receive_time` against UTC, below). Both are absent when no estimate existed or the replica withheld it (time daemon unsynchronized, sample older than 16 s, clock stepped, or source not NTS-authenticated), which the manifest states. ## Clock calibration - **Point of timestamping.** `receive_time` is read when the replica holds the complete frame from its connection (after transport decryption and frame reassembly), for every venue. - **Bound.** `clock_error_bound` = abs(`clock_offset`) + root dispersion + root delay / 2 + 15e-6 × the sample's age + 1.25 ns, rounded up to the next nanosecond, from the time daemon's latest sample: the absolute offset, plus RFC 5905's root distance (root dispersion plus half the root delay), plus dispersion growth at RFC 5905's frequency tolerance (PHI, 15 ppm), plus 1.25 ns for the nanosecond resolution at which the sample states its offset, root delay and root dispersion (0.5 ns each, halved for the root delay). The age is measured on a monotonic clock from the moment the replica starts reading the sample. - **Conditions.** The bound holds when the upstream reference is correct, the host clock's frequency error stays within 15 ppm, the clock is not stepped between the sample and the receipt, and the time daemon reports itself synchronized. A replica withholds `clock_offset` and `clock_error_bound` while the time daemon reports itself unsynchronized, when the latest sample is older than 16 s, for a receipt whose sample did not come from a source authenticated with Network Time Security (NTS, RFC 8915), and after a step until the time daemon has updated the clock from a measurement taken after the step. - **Kind of bound.** The bound is a maximum-error bound under these conditions, not a probabilistic interval, and no coverage factor is claimed. - **`receive_time` and `exchange_time`.** `exchange_time` is the venue's stated time for the frame; the venue's clock carries no bound in this record, so the difference between the two times is not a one-way network delay and can be negative. ## Normalized tables Parquet, zstd-compressed, one per table even when it has no rows. Every row references its frame by `raw_index`, the zero-based line index in the hour's `raw.jsonl.zst`, and carries that frame's frame time in `receive_time`. Values are exactly as the venue sent them: no rounding, no unit or currency conversion, no inference. Venue fields the tables do not define stay in the raw file. | Column | Parquet type | Tables | |---|---|---| | `raw_index` | int64, required | all | | `instrument` | string, required | all | | `trade_id` | string, optional | `trades` | | `side` | string; optional in `trades` (the venue's word), required in the book tables (`bid` or `ask`) | all | | `price`, `size` | DECIMAL(38, 18) on FIXED_LEN_BYTE_ARRAY(16), required | all | | `exchange_time` | TIMESTAMP(NANOS, UTC) on int64, optional | all | | `receive_time` | TIMESTAMP(NANOS, UTC) on int64, required | all | Tables: `trades.parquet` (channel `trades`); `book_snapshots.parquet` (the snapshots the venue sent, one row per level) and `book_deltas.parquet` (one row per changed level; a size of zero removes the level) (channel `book`). A frame with a value that DECIMAL(38, 18) cannot hold exactly, or a frame of a row-carrying type that does not parse as the venue's documented structure, yields no rows; the hourly manifest lists its line index in `unrepresentable_frames`, and the hour is `partial` with reason `unrepresentable_value`. ## Hourly manifest | Field | Meaning | |---|---| | `format_version` | `1` | | `recorder`, `venue`, `channel` | Identity of the chain | | `interval` | The hour: `start_time`, `end_time` (exclusive) | | `files` | Each file of the hour directory: `name`, `size`, `blake3`, `rows` | | `frame_time_bounds` | Earliest and latest frame time, absent when there are no frames | | `sequence_gaps` | `instrument`, `after_id`, `before_id` for each break in a venue sequence | | `checksum_failures` | `instrument`, `receive_time` (the `receive_time` of the receipt whose replica found the mismatch), `expected`, `computed` for each venue checksum mismatch | | `unrepresentable_frames` | Raw-file line indices kept in the raw file only; absent when empty | | `replicas` | Per replica: `replica`, `frames`, `covered_ns`, `reconnect_windows`, `gap_free_runs`, and `clock` (all below) | | `replica_agreement` | Frames seen by `both` replicas and by `one_only`, and trade IDs in `conflict` | | `conflicts` | Each `trade_id` of an `instrument` that raw-file lines carry with different `side`, `price`, `size` or `exchange_time` (channel `trades`): `instrument`, `trade_id`, and `lines` (each `raw_index` and the `blake3` of the line's bytes without its terminating newline, U+000A); absent when there are none | | `completeness` | `status` (`complete`, `partial`, `missing`) and `reasons` | | `previous_manifest_blake3` | Hash of the previous hour's manifest bytes; null at the chain's start | Each entry of `reconnect_windows` carries `start_time`, `end_time` (exclusive) and, when the venue closed the connection that the window follows with a close frame carrying a status code, `close_code`: that frame's status code (RFC 6455, section 7.4). A window that continues from the previous hour keeps its `close_code`. The verifier does not check `close_code`. Each entry of `gap_free_runs` (channel `trades`) states an interval during which one connection of the replica was subscribed and the replica detected no gap in the venue's trade sequence for one instrument: `instrument`, `connection`, `start_time`, and `end_time` (exclusive). A run's `end_time` is 1 ns after the connection's last frame before the first event that breaks the run (a disconnection, a gap detected in the venue's trade sequence for that instrument, a checksum failure, or a resubscription), or the end of the hour; the next run starts where the break was detected, so each break lies between two stated times. A run states that the replica detected no gap, not that none occurred. `gap_free_runs` is absent when the replica states no run. The verifier checks their references (check 9), not the venue sequences they rest on, and checks `conflicts` by reference (check 10). Each replica with receipts in the raw file carries `clock`: `source` (`nts`; present exactly when `error_bound_max` is), `error_bound_max` (the largest `clock_error_bound` of the replica's receipts), and `unbounded` (the count of its receipts without one); `source` and `error_bound_max` are absent when every receipt of the replica is unbounded. A replica with no receipts in the hour has no `clock`. The reason `clock_offset_unknown` means that at least one frame has no receipt with `clock_offset`; a replica's `unbounded` can be nonzero without it. Every hour has a manifest, including an hour with no data, so the chain never skips an hour. Completeness reasons: `reconnect`, `sequence_gap`, `checksum_failure`, `clock_offset_unknown`, `journal_torn`, `journal_corrupt`, `recorder_down`, `unrepresentable_value`, `destination_unavailable`. ## Daily manifest `format_version`, `recorder`, `venue`, `channel`, `date`, `hours` (each `hour`, `blake3`, `status`, in order) and `previous_manifest_blake3` (the previous day's daily manifest, null at the start). ## Signatures `manifest.json.sig` is a detached JWS (RFC 7515) with an unencoded payload (RFC 7797) over the exact bytes of `manifest.json`: protected header `alg` `Ed25519` (RFC 9864), `kid`, `b64` false, `crit` `["b64"]`. Keys are published as a JWK Set (RFC 7517) of OKP keys (RFC 8037) with RFC 7638 thumbprints as `kid`. ## What a verifier checks 1. Every manifest is canonical JSON with `format_version` 1; an unknown major is rejected. 2. Every listed file exists with the listed size and BLAKE3 hash. 3. The raw file decompresses; every line is a canonical envelope; frame times lie in the hour and never decrease; the line count equals the listed rows. 4. Every table of the channel is listed, has the v1 schema and the listed row count, and each row's `raw_index` exists and never decreases, and its `receive_time` equals the frame time of its frame. 5. Hours are consecutive and each manifest carries the previous manifest's hash; the same holds for days, and each daily manifest lists exactly its day's hourly manifests. Copies of one channel in several directories are one chain; a manifest held twice with different bytes is a fork and fails. 6. Every signature verifies against a key valid at signing time. 7. Each receipt carries `clock_error_bound` exactly when it carries `clock_offset`, and the bound is at least the absolute value of the offset. 8. Each replica with receipts carries `clock`, and no other replica does; its values equal those recomputed from the raw file; the reasons include `clock_offset_unknown` exactly when some raw-file line has no receipt with `clock_error_bound`. 9. Each entry of `gap_free_runs` lies within the hour and ends after it starts, and its `connection` appears in a receipt of its replica. 10. Each `conflicts` line's `raw_index` exists, its `blake3` is the hash of that raw-file line's bytes without its terminating newline, U+000A, and every line of one conflict carries its `trade_id`. Within major 1, only optional manifest fields and new columns may be added; readers ignore fields they do not know. --- # Command-line verification Summary: Three openly available tools verify a sealed hour against its manifest and against the hour before it. `jq` reads the manifest, `b3sum` recomputes BLAKE3 hashes, and `zstd` opens the raw file. The commands verify the format version, each listed file's size and hash, the raw file's line count, and the hash chain link to the previous hour. Each command prints its result and exits with a non-zero status when its check fails. ## What you need - `jq`, `b3sum` and `zstd`, from your system's package manager. - A POSIX shell: `sh`, `bash` or `zsh`. - Two consecutive sealed hours of one channel: the [synthetic example hour](https://noxfze.com/docs/example), or two hour directories from storage you own. ## 1. Get two consecutive hours The synthetic example hour and the hour before it: ```sh download curl -fsSO https://noxfze.com/docs/example-hour.tar tar -xf example-hour.tar ``` Go to the channel's directory and name the hour to check and the hour before it: ```sh setup cd example-hour/recorder=r1/venue=example/channel=trades HOUR=date=2026-01-06/hour=00 PREV=date=2026-01-05/hour=23 ``` For your own record, copy two consecutive hour directories of one channel from storage you own. Keep their `date=YYYY-MM-DD/hour=HH` paths, and set `HOUR` and `PREV` to them. The hour before 00:00 UTC is 23:00 UTC of the previous date. ## 2. Read the manifest The manifest is format version 1. It lists each file of the hour with its size in bytes and its BLAKE3 hash: ```sh check version jq -e '.format_version == 1' "$HOUR/manifest.json" ``` ```text output version true ``` ```sh check listing jq -r '.files[] | "\(.name) \(.size) \(.blake3)"' "$HOUR/manifest.json" ``` ```text output listing raw.jsonl.zst 318 d9aa031a1200254b0951863450ea62e506ecbe32f6d6b63106689b622238f96e trades.parquet 2052 a693551b628a352b8303946729066efb66d32452d11a3ee0230055af9f81769e ``` ## 3. Verify each file's size and hash Each listed file has the listed size: ```sh check sizes jq -r '.files[] | "\(.size) \(.name)"' "$HOUR/manifest.json" | while read -r size name; do test "$(wc -c < "$HOUR/$name")" -eq "$size" || { echo "$name: size differs"; exit 1; } echo "$name: $size bytes, as listed" done ``` ```text output sizes raw.jsonl.zst: 318 bytes, as listed trades.parquet: 2052 bytes, as listed ``` Each listed file has the listed BLAKE3 hash. A file that is missing or differs by one byte fails here: ```sh check hashes jq -r '.files[] | "\(.blake3) \(.name)"' "$HOUR/manifest.json" | (cd "$HOUR" && b3sum --check) ``` ```text output hashes raw.jsonl.zst: OK trades.parquet: OK ``` ## 4. Open the raw file The raw file holds one line per frame, and its line count is the number of rows the manifest lists for it: ```sh check rows rows=$(jq '.files[] | select(.name == "raw.jsonl.zst") | .rows' "$HOUR/manifest.json") test "$(zstd -dc "$HOUR/raw.jsonl.zst" | wc -l)" -eq "$rows" && echo "raw.jsonl.zst: $rows lines, as listed" ``` ```text output rows raw.jsonl.zst: 4 lines, as listed ``` The first frame of the hour, with the venue's payload as received and one receipt per replica that received it: ```sh check frame zstd -dc "$HOUR/raw.jsonl.zst" | head -n 1 | jq . ``` ```text output frame { "exchange_time": "2026-01-06T00:00:04.998000000Z", "payload": "{\"type\":\"trade\",\"instrument\":\"INST-1\",\"id\":\"1003\",\"side\":\"buy\",\"price\":\"100.5\",\"size\":\"0.25\",\"time\":1767657604998}", "payload_encoding": "text", "receipts": [ { "clock_error_bound": 60000, "clock_offset": 300, "connection": "c1", "receive_time": "2026-01-06T00:00:05.000000000Z", "replica": "a" }, { "connection": "c2", "receive_time": "2026-01-06T00:00:05.001000000Z", "replica": "b" } ] } ``` ## 5. Verify the hash chain link The hour's manifest carries the BLAKE3 hash of the previous hour's manifest bytes. A change to any byte of the previous manifest, including a file hash it lists, changes that hash: ```sh check chain computed=$(b3sum --no-names "$PREV/manifest.json") carried=$(jq -r .previous_manifest_blake3 "$HOUR/manifest.json") echo "computed: $computed" echo "carried: $carried" test "$computed" = "$carried" && echo "chain: OK" ``` ```text output chain computed: 05a9316fa40d8f7ea43cd1c6cbb27c88c979059466054d6cae45150c4aded1e8 carried: 05a9316fa40d8f7ea43cd1c6cbb27c88c979059466054d6cae45150c4aded1e8 chain: OK ``` The two hours are consecutive and belong to the same hash chain: ```sh check consecutive jq -e --slurpfile prev "$PREV/manifest.json" '.interval.start_time == $prev[0].interval.end_time and .recorder == $prev[0].recorder and .venue == $prev[0].venue and .channel == $prev[0].channel' \ "$HOUR/manifest.json" ``` ```text output consecutive true ``` The first hour of a hash chain carries `null` instead of a hash. To verify a longer run of hours, repeat step 5 for each pair of consecutive hours. ## What these commands do not verify The commands make check 2 of the [ten checks of record format, version 1](https://noxfze.com/docs/format#what-a-verifier-checks). They also make the format version part of check 1, the line count of check 3, and the hourly links of check 5. The other checks need an implementation of the format. They cover the canonical form of the manifests (check 1), the rest of the raw file and the tables (checks 3 and 4), and the daily manifests (check 5). They also cover signatures, on hours that carry them (check 6), and the clock fields, runs and conflicts (checks 7 to 10). A pass does not show that these hours are the ones Nox FZE sealed: confirm that by matching an hour's root to a root you received earlier. An hour's root is the hash of its manifest. This root shows only that the hour is unchanged since Nox FZE sealed it, and which messages Nox FZE received from the venue's public interfaces and when. It gives no opinion on the venue or on its markets, volume, statements, controls or systems. --- # Synthetic example hour Summary: The synthetic example hour is one sealed hour and the hour before it, as one download, for the synthetic venue `example` and its channel `trades`. It holds no market data. It includes both daily manifests and the test key set that their signatures verify against. Use it to run [command-line verification](https://noxfze.com/docs/verify) before your first sealed hour arrives, or to test your own implementation of [record format, version 1](https://noxfze.com/docs/format). ## Download [example-hour.tar](https://noxfze.com/docs/example-hour.tar): 21504 bytes, SHA-256 `45eab923b72291d31d626a2930a17c42524644430d39df69121897c3b2c5f88c`. Unpack it with `tar -xf example-hour.tar`. It holds the directory `example-hour/`: ```text 391 example-hour/expected.json 142 example-hour/keys.json 1026 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-05/hour=23/manifest.json 216 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-05/hour=23/manifest.json.sig 307 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-05/hour=23/raw.jsonl.zst 2013 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-05/hour=23/trades.parquet 245 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-05/manifest.json 216 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-05/manifest.json.sig 1863 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-06/hour=00/manifest.json 216 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-06/hour=00/manifest.json.sig 318 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-06/hour=00/raw.jsonl.zst 2052 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-06/hour=00/trades.parquet 306 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-06/manifest.json 216 example-hour/recorder=r1/venue=example/channel=trades/date=2026-01-06/manifest.json.sig ``` - `expected.json`: the expected result of a verifier that makes every check of the format. - `keys.json`: the test key set, a JWK Set (RFC 7517), used only for synthetic test data. ## The two synthetic hours | Hour (UTC) | Status | Reasons | Files | Previous manifest (BLAKE3) | |---|---|---|---|---| | 2026-01-05 23:00 to 00:00 | `complete` | none | `raw.jsonl.zst` (3 rows), `trades.parquet` (2 rows) | `null`, the start of the chain | | 2026-01-06 00:00 to 01:00 | `partial` | `reconnect`, `clock_offset_unknown` | `raw.jsonl.zst` (4 rows), `trades.parquet` (3 rows) | `05a9316fa40d8f7ea43cd1c6cbb27c88c979059466054d6cae45150c4aded1e8` | ## Expected result `expected.json` states the verdict `pass` with no errors, for 2 hours on 2 days: | Hour (UTC) | Status | |---|---| | 2026-01-05 23:00 | `complete` | | 2026-01-06 00:00 | `partial` | The synthetic hour 2026-01-06 00:00 UTC is `partial`, and its manifest states why. Its reasons are `reconnect` (a replica reconnected during the hour) and `clock_offset_unknown` (at least one frame has no receipt with a clock offset). A partial hour still passes: the checks show that the hour is intact and consistent, and its manifest states what was incomplete. --- # Starting a record Summary: A record starts with a written request and an order form that both sides sign. Each sealed hour is delivered into storage you own, through a write-only key you give Nox. The record opens with a 30-day pilot at no fee, then continues for a monthly fee set out in the order form. Nox works in writing, by email. ## 1. Write to Nox [Email contact@noxfze.com](mailto:contact@noxfze.com?subject=Venue%20record%20request%20%28documentation%29) with your venue, its public channels and the instruments to record. [Contact](https://noxfze.com/contact) lists what to include. Nox works in writing: the order form, the storage setup and every report arrive by email. Scope: perpetual and spot instruments. Event, outcome and prediction contracts are outside scope and are never recorded. ## 2. The order form Nox replies in writing, with the written order form. It sets out the 30-day pilot at no fee and the fixed monthly fee after it, set by the number of instruments recorded. It also sets out how you may cite the record. Each citation that names Nox FZE states that your venue commissioned the record. It also carries the statement in [what one sealed hour holds](https://noxfze.com/docs#what-one-sealed-hour-holds). The record starts once both sides sign the order form and your bucket and write-only key are in place. ## 3. Prepare storage you own - **A bucket in storage you own.** Object storage reachable over HTTPS with an S3-compatible API. Each sealed hour is written under the [directory layout of the record format](https://noxfze.com/docs/format#layout). - **A write-only key.** The key lets Nox write objects into the bucket and nothing else. Nox needs no permission to read, list or delete objects. - **Versioning or object lock.** Nox recommends enabling object versioning or object lock on the bucket. Each delivered object then keeps its first version if it is later overwritten or deleted. You send the bucket's endpoint and the key by email, as the storage setup message from Nox describes. ## 4. The pilot The pilot runs for 30 days, on the instruments you choose, at no fee. A recorder dedicated to your venue receives your public channels through your public interfaces, as any outside client would. Each UTC hour is sealed and delivered into storage you own within 15 minutes after it closes. If your storage or the recorder is unavailable, the hour arrives later, and the object times in your bucket show when. From the first pilot hour, every UTC hour has a manifest, including an hour in which Nox received no messages. You can verify any delivered hour with [command-line verification](https://noxfze.com/docs/verify) or in your browser with [Verification](https://noxfze.com/verify). --- # Questions venues ask Summary: Short answers to what a venue asks before a record starts: what is recorded, who holds it, how an hour is verified, its price and how it starts. Each answer links to the page that states it in full. ## What does Nox FZE do for a venue? Nox FZE records your venue's public market data and seals each UTC hour into a hash chain, delivered into storage you own. A recorder dedicated to your venue receives your public channels as any outside client would. Each sealed hour arrives within 15 minutes after it closes, unless your storage or the recorder is unavailable. Anyone you share an hour with can verify it with openly available tools. ## What exactly is recorded? Nox records the public channels your venue publishes, such as trades, order book and funding, on the instruments you choose. Each hour holds the frames exactly as received, a normalized form of trades and the order book, and a manifest. The normalized form keeps every value as your venue sent it, and each row references the frame it came from. [Record format, version 1](https://noxfze.com/docs/format) defines every file and field. ## Who holds the record, and where? Your venue holds the record, in a bucket in storage you own. Nox writes each sealed hour into it through a write-only key, under the [directory layout of the record format](https://noxfze.com/docs/format#layout). The key gives Nox no permission to read, list or delete objects. You choose whom you share the record with. ## How does anyone check an hour? Anyone with a sealed hour can recompute each file's hash against its manifest, and the link to the hour before, with openly available tools. [Command-line verification](https://noxfze.com/docs/verify) gives the commands for `jq`, `b3sum` and `zstd`. The [synthetic example hour](https://noxfze.com/docs/example) is a download to try them on. [Verification](https://noxfze.com/verify) checks the file hashes and the chain link in your browser, and nothing is uploaded. ## What happens when data is missing? Every gap Nox detects is declared in the hour's manifest, and no message is estimated or filled in. The manifest lists each break Nox detects in your venue's message sequence, and each reconnection. Its completeness status is `complete`, `partial` or `missing`, with the reasons. Every UTC hour has a manifest, including an hour in which Nox received no messages. ## Does Nox need access to the venue's systems or private data? No: Nox receives your public channels through your public interfaces, as any outside client would. The one access Nox needs is a write-only key to a bucket you own. The key lets Nox write objects and nothing else. Nox needs no access to your internal systems and no private data. ## Does Nox sell or share the venue's record? No: Nox FZE does not sell, license or redistribute your venue's record. Your venue shares it, from storage it owns, with whom it chooses. The write-only key gives Nox no permission to read, list or delete the hours it delivers. ## How is it priced? A record is priced as a fixed monthly fee, set by the number of instruments recorded and stated in the written order form. The 30-day pilot carries no fee. [Starting a record](https://noxfze.com/docs/start) describes the order form. ## How does a record start, and how long does it take? A record starts once both sides sign the order form and your bucket and write-only key are in place. It opens with a 30-day pilot on the instruments you choose. From then on, each UTC hour is delivered within 15 minutes after it closes, unless your storage or the recorder is unavailable. [Starting a record](https://noxfze.com/docs/start) gives each step. ## What does Nox need from the venue? Nox needs three things from your venue: a bucket in storage you own, a write-only key to it, and a signed order form. The bucket is object storage reachable over HTTPS with an S3-compatible API. [Contact](https://noxfze.com/contact) lists what your first email includes. ## What happens to the record if the venue or Nox stops? Every delivered hour stays in your storage, and the write-only key gives Nox no permission to delete it; with versioning or object lock on, no delivered version can be overwritten. Each hour follows [record format, version 1](https://noxfze.com/docs/format), which is published in full. Anyone can still verify every delivered hour with openly available tools, and the hash chain ends at the last delivered hour. ## Who is Nox FZE, and where is it established? Nox FZE is a Free Zone Establishment with Limited Liability in the Umm Al Quwain Free Trade Zone, United Arab Emirates, independent and privately held. It was incorporated on 2025-12-05 and holds License No. 11054, issued by the Umm Al Quwain Free Trade Zone Authority. The [legal notice](https://noxfze.com/legal) gives its registered office, license and licensed activity. ## How is the format versioned? The record format has a major version, which every manifest states as `format_version`. Within version 1, only optional manifest fields and new columns may be added, and readers ignore fields they do not know. A verifier rejects a manifest with an unknown major. These pages show only the contract version, [record format, version 1](https://noxfze.com/docs/format). ## How does an AI agent make a request? An AI agent makes a request by email to contact@noxfze.com, with the subject "Venue record request (agent)". The file [llms.txt](https://noxfze.com/llms.txt) states this for agents. [The complete documentation as one text file](https://noxfze.com/llms-full.txt) holds every page, and each page has a Markdown version. ## How does Nox communicate? Nox FZE communicates in writing, by email. The order form, the storage setup and every report arrive by email from an address ending in @noxfze.com. The legal notice lists the [official channels](https://noxfze.com/legal#official-channels) of Nox FZE. --- # Contact Summary: Nox FZE works in writing. Send requests by email to contact@noxfze.com. ## What to include - Your venue's legal name. - The instruments to record, and the public channels your venue publishes for them, such as trades, order book and funding. - Where the record is to be delivered: a bucket in object storage your venue owns, reachable over HTTPS with an S3-compatible API. - The date you want the record to start. - Who signs the order form for your venue. [Email contact@noxfze.com](mailto:contact@noxfze.com?subject=Venue%20record%20request%20%28contact%29) with the subject "Venue record request (contact)". ## What happens next Nox FZE replies in writing, with the written order form. The record starts once both sides sign the order form and your bucket and write-only key are in place. It opens with the 30-day pilot at no fee that [Starting a record](https://noxfze.com/docs/start) describes. After the pilot, the record continues for a fixed monthly fee, set by the number of instruments recorded and stated in the order form. ## Other requests Privacy, legal and press requests go to the same address, contact@noxfze.com, with a subject that names the topic.