Skip to main content

Export Schemas

An export schema defines how raw exchange data is transformed into structured columns in your exported CSV files. Each column maps to either system metadata (like timestamps) or a value extracted from the exchange’s JSON message.

Built-in vs custom schemas

Every account has access to built-in schemas like raw and normalized_trades. You can use them by name when creating an export:
{
  "datastream_id": 123,
  "start_time": "2024-01-15T10:00:00Z",
  "end_time": "2024-01-16T10:00:00Z",
  "schema": "normalized_trades"
}
To see all available schemas (built-in + your custom ones), use the List export schemas endpoint. When built-in schemas don’t fit your needs, you can create a custom schema with exactly the columns you want.

Schema structure

A schema has a name, a stream_type it applies to, a list of columns, and an optional unfold configuration:
{
  "name": "my_trades",
  "stream_type": "trade",
  "unfold": {
    "bybit_linear": { "path": "data" }
  },
  "columns": [
    { "output_column": "ts", "meta": { "value": "collection_timestamp_ns" } },
    { "output_column": "price", "data": { ... } }
  ]
}
Each column has an output_column (the column name in output) and exactly one of:
  • meta — extract a system metadata value
  • data — extract from the exchange’s JSON message, with per-exchange rules

Meta columns

Meta columns extract system-level values that are consistent across all exchanges:
ValueDescription
collection_timestamp_nsWhen Ticksupply received the message (nanoseconds)
You can control the output format with the format field:
FormatOutputExample
ns (default)Nanoseconds since epoch1705312800000000000
usMicroseconds since epoch1705312800000000
msMilliseconds since epoch1705312800000
sSeconds since epoch1705312800
iso8601ISO 8601 string2024-01-15T10:00:00Z
{
  "output_column": "timestamp",
  "meta": {
    "value": "collection_timestamp_ns",
    "format": "ms"
  }
}

Data columns

Data columns extract values from the exchange’s raw JSON message. Because different exchanges use different JSON structures, you provide extraction rules per exchange.
{
  "output_column": "price",
  "data": {
    "binance": {
      "json": { "path": "p", "type": "decimal(18)" }
    },
    "bybit_linear": {
      "json": { "path": "p", "type": "decimal(18)" }
    }
  }
}

JSON extraction

Each exchange extractor has a json field with:
  • path — dot-notation path into the JSON message (e.g., "p", "data.price", "info.amount")
  • type — output data type
TypeUse forExample
decimal(N)Prices, quantities (N = decimal places)decimal(18)
f64Floating-point values like percentagesf64
i64Integer values like trade IDsi64
stringText values like side (“Buy”/“Sell”)string
boolBoolean flagsbool
Use decimal(18) for financial values like price and quantity. It preserves exact precision, unlike f64 which can introduce floating-point rounding.

Transforms

When the raw value needs post-processing, add a transform — a SQL expression where {v} is the extracted value. A common example: Binance represents trade side as a boolean (m = is the buyer the market maker?), while most downstream systems expect "buy" or "sell":
{
  "output_column": "side",
  "data": {
    "binance": {
      "json": { "path": "m", "type": "bool" },
      "transform": "CASE WHEN {v} THEN 'sell' ELSE 'buy' END"
    },
    "bybit_linear": {
      "json": { "path": "S", "type": "string" }
    }
  }
}
Other transform examples:
Use caseTransform
Convert to lowercaselower({v})
Divide by 100{v} / 100
Default for nullscoalesce({v}, 0)
Extract substringsubstring({v}, 1, 3)

Unfold

Some exchanges pack multiple events into a single WebSocket message as a JSON array. For example, Bybit trade messages look like:
{
  "topic": "publicTrade.BTCUSDT",
  "data": [
    { "p": "50000.00", "v": "0.001", "S": "Buy" },
    { "p": "50001.00", "v": "0.002", "S": "Sell" }
  ]
}
Without unfold, this entire message would become one row. With unfold, each element in the data array becomes its own row — so the example above produces two rows. Configure unfold per exchange by specifying the path to the array:
{
  "unfold": {
    "bybit_linear": { "path": "data" },
    "bybit_spot": { "path": "data" },
    "bybit_inverse": { "path": "data" }
  }
}
After unfolding, your column path values reference fields inside each array element. So "path": "p" extracts the p field from each individual trade object — not from the top-level message.
Unfold only applies to exchanges that batch events. Exchanges like Binance that send one event per message don’t need unfold rules — just omit them.

Creating schemas

Dashboard

The dashboard schema editor is the easiest way to create schemas. It provides a visual builder where you select exchanges, configure JSON paths and data types per column, set up unfold rules, and see a live JSON preview. You can switch between the visual editor and the raw JSON view at any time.

API

To create a schema programmatically, use the Create export schema endpoint. Here’s a complete trade schema covering Binance and Bybit Linear with unfold:
curl -X POST https://api.ticksupply.com/v1/export-schemas \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my_trades",
    "stream_type": "trade",
    "unfold": {
      "bybit_linear": { "path": "data" }
    },
    "columns": [
      {
        "output_column": "timestamp_ns",
        "meta": { "value": "collection_timestamp_ns", "format": "ns" }
      },
      {
        "output_column": "price",
        "data": {
          "binance": { "json": { "path": "p", "type": "decimal(18)" } },
          "bybit_linear": { "json": { "path": "p", "type": "decimal(18)" } }
        }
      },
      {
        "output_column": "quantity",
        "data": {
          "binance": { "json": { "path": "q", "type": "decimal(18)" } },
          "bybit_linear": { "json": { "path": "v", "type": "decimal(18)" } }
        }
      },
      {
        "output_column": "side",
        "data": {
          "binance": {
            "json": { "path": "m", "type": "bool" },
            "transform": "CASE WHEN {v} THEN '\''sell'\'' ELSE '\''buy'\'' END"
          },
          "bybit_linear": { "json": { "path": "S", "type": "string" } }
        }
      }
    ]
  }'
This produces a CSV with columns: timestamp_ns, price, quantity, side — normalized across both exchanges.

Using schemas with exports

Once you have a schema (created via dashboard or API), you can reference it three ways when creating an export: By name — for built-in or saved custom schemas:
{ "schema": "my_trades" }
By ID — for custom schemas:
{ "schema": "sch_0194a1b2c3d4e5f6a7b8c9d0e1f2a3b4" }
Inline — for ad-hoc schemas without saving:
{
  "schema": {
    "columns": [
      { "output_column": "ts", "meta": { "value": "collection_timestamp_ns" } },
      { "output_column": "price", "data": { "binance": { "json": { "path": "p", "type": "decimal(18)" } } } }
    ]
  }
}

Next steps

Create Export Schema

Save a reusable schema via the API

Create Export

Use your schema to export data

List Export Schemas

View all available schemas

Quickstart

End-to-end guide from subscription to export
Last modified on April 5, 2026