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

# Export

> GET /v1/export. The ledger as of an instant, as a FactBlock bundle that stands on its own.

Returns a `tar.gz` of a [FactBlock](https://github.com/factagora/factblock) bundle in the JSONL profile: a manifest with the declarations, plus `nodes.jsonl`, `edges.jsonl`, and `resolutions.jsonl`. The `factblock` library converts it to the Parquet profile. Every row carries `known_at` and the backfill batch that attests it, so the file answers as-of reads without this server.

Unlike the other reads, export does not select on validity. A bundle is the ledger, not a view of it; the reader applies `valid_at` itself.

## Query parameters

<ParamField query="as_of" type="timestamp or date" required>
  Only rows learned at or before this instant are exported. Rows learned later are absent from the file, so a bundle exported as of T never leaks what was learned after T.
</ParamField>

<ParamField query="space" type="string">
  Scope to one space: its nodes, the edges between them, and the resolutions on them. Omit for the whole tenant.
</ParamField>

<ParamField query="category" type="string">
  Scope to one topic label: those nodes, the edges between them, and the resolutions on them. Combines with `space`.
</ParamField>

## Response

`200 application/gzip`, `Content-Disposition: attachment; filename="factblock.tar.gz"`. The archive unpacks to one directory, `factblock/`.

| File | Content |
| - | - |
| `factblock.json` | `factblock_version`, `namespace` (tenant, plus space when given), `source` (`tckg/<version>`), `exported_as_of`, `declarations` (facts in force at `as_of`, the backfill batches referenced by the rows) |
| `nodes.jsonl` | One node per line: `id`, `kind`, `space`, `statement`, `category`, `payload`, `asserted_at`, `valid_from`, `valid_to`, `known_at`, `attestation`, `fact_key`, `fact_value` |
| `edges.jsonl` | One edge per line, `lag` as an ISO 8601 duration |
| `resolutions.jsonl` | One verdict per line: `target_id`, `value`, `outcome`, `method`, `ruleset`, `resolver`, `decided_at`, `known_at`, `attestation` |

Embeddings are not exported. The bundle declares no embedding model, so the vectors would not be usable (`declarations.embedding` is null).

<CodeGroup>
  ```bash Export and validate theme={null}
  curl -s -G "$TCKG/v1/export" --data-urlencode "as_of=2024-08-01" --data-urlencode "space=user:randy" \
    -H "Authorization: Bearer $TCKG_TOKEN" -o factblock.tar.gz
  tar xzf factblock.tar.gz
  pip install git+https://github.com/factagora/factblock   # PyPI release pending
  python -m factblock validate factblock
  python -m factblock scan factblock --as-of 2024-05-01
  python -m factblock to-parquet factblock factblock-pq     # Parquet profile for Spark, DuckDB, Databricks
  ```

  ```python Query the file with DuckDB theme={null}
  import factblock, duckdb
  r = factblock.scan("factblock", as_of="2024-05-01")
  nodes = r.nodes
  duckdb.sql("select id, statement, superseded_by from nodes")
  r.certificate   # what the file hid to answer as of May
  ```

  ```sql Or in DuckDB with no Python theme={null}
  -- duckdb -init duckdb/factblock.sql   (from the factblock repo)
  select id, statement, superseded_by
    from factblock_nodes('factblock-pq', factblock_day('2024-05-01'));
  select * from factblock_certificate('factblock-pq', factblock_day('2024-05-01'));
  -- or on the bare files: rows are sorted by known_at, so an as-of read is one predicate
  select id from read_parquet('factblock-pq/nodes.parquet') where known_at <= timestamptz '2024-05-01';
  ```
</CodeGroup>

## Both ways: `factblock sync`

Export is one direction. The `factblock` library's `sync` moves rows between a folder and this ledger in both directions, by identity: nodes by `id`, edges by `(source, target, type, asserted_at)`, resolutions by `(target, decided_at)`. What only the folder has is written here under the folder's own backfill batches, so a 2024 transcript you extracted locally is known here as of 2024, not today. What only the ledger has (verdicts, rows other writers added to the space) is appended to the folder with the ledger's `known_at`. Nothing is changed in place, and running it again is a no-op.

```bash theme={null}
export TCKG_TOKEN=...                                                   # the tenant's API key
factblock sync brain/ https://tckg.factagora.com --space tckg:...       # push what is new here, pull what is new there
factblock sync brain/ https://tckg.factagora.com --space tckg:... --push-only
factblock sync copy/  https://tckg.factagora.com --space tckg:... --pull-only   # into a folder that does not exist yet: a clone
```

Under the hood it is this API: one `GET /v1/export?as_of=` for the pull, and one `POST /v1/memories` per batch for the push, each carrying that batch as its `backfill` declaration. Rows that carry a `space` keep it; the rest take `--space`. Resolutions are never pushed: verdicts are the ledger's to make. The folder stays a valid bundle after every sync, so `factblock validate` and `scan` keep working on it offline.

<Note>
  The validator checks the five FactBlock invariants (three clocks, attested knowledge time, append-only, typed edges, declared facts). An export from tckg passes all of them; the smoke suite proves the round trip on every commit.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.