# GET /v1/trades

> Independent. Not affiliated with, endorsed by or sponsored by Novig.

Canonical: https://novigapi.com/docs/endpoints/trades
Facts checked: 2026-11-12

GET /v1/trades lists executed Novig trades with price, quantity, outcome and timestamp, newest first, for one market or a whole league. Recent fills are at most about 10 seconds old on paid plans. Older fills come from Novig's daily trades.csv, which starts on 3 Aug 2026 according to its index checked 12 Nov 2026. (Source: [Novig docs: Trades CSV](https://docs.novig.com/public-data/trades.md))

## What it returns

Every fill we have seen, newest first, from two sources: our polling of Novig's public trades route (`source: api`) and the taker side of Novig's daily trades.csv (`source: csv`). Use it for volume-weighted prices, steam detection or your own candles. Without `market_id` the default window is the last hour and never more than a day; with one, the last 30 days by default.

## Parameters

Query and path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| market_id | string | No | Only trades on this market. Without it, the whole tape, newest first. |
| since | string (ISO 8601) | No | Only trades at or after this time. Free reads only the last 7 days. |
| limit | integer | No | Rows per page, 1 to 1,000. Default 100. Free returns at most 100. |
| cursor | string | No | `meta.next_cursor` from the previous page. |


## Request

```bash
curl -s "https://novigapi.com/api/v1/trades?market_id=01a1d00f-ec01-71c0-9776-0facc97e44a7&limit=2" \
  -H "Authorization: Bearer nv_..."
```

## Response

Market and outcome ids and the two prices are real (the last traded prices on Cooper Flagg 1.5 steals on 12 Nov 2026). Trade ids, quantities and times are illustrative, because the capture holds no individual fills. A trade's `observed_at` is its fill time.

```json
{
  "data": [
    {
      "trade_id": "01a1d0f2-6b3c-7e10-9a41-2c7d55e0b1a3",
      "market_id": "01a1d00f-ec01-71c0-9776-0facc97e44a7",
      "outcome_id": "01a1d00f-ec01-71c0-9776-0fc320d7d309",
      "price": 0.585,
      "qty": 2500,
      "ts": "2026-11-12T17:21:40.000Z",
      "source": "api",
      "observed_at": "2026-11-12T17:21:40.000Z",
      "source_age_seconds": 0,
      "edge_cached": true
    },
    {
      "trade_id": "01a1d0f1-9e02-7c55-8d10-7b3e9a4f6c21",
      "market_id": "01a1d00f-ec01-71c0-9776-0facc97e44a7",
      "outcome_id": "01a1d00f-ec01-71c0-9776-0fb0230cbd18",
      "price": 0.415,
      "qty": 1200,
      "ts": "2026-11-12T17:18:05.000Z",
      "source": "api",
      "observed_at": "2026-11-12T17:18:05.000Z",
      "source_age_seconds": 0,
      "edge_cached": true
    }
  ],
  "meta": {
    "observed_at": "2026-11-12T17:18:05.000Z",
    "source_age_seconds": 357,
    "edge_cached": true,
    "next_cursor": "eyJ0cyI6IjIwMjYtMTEtMTJUMTc6MTg6MDUuMDAwWiIsImlkIjoiMDFhMWQwZjEtOWUwMi03YzU1LThkMTAtN2IzZTlhNGY2YzIxIn0",
    "limit": 2,
    "count": 2,
    "plan": "developer",
    "credits_charged": 3,
    "credits_remaining": 9874,
    "credit_policy": "credits_v1"
  }
}
```

## Fields

Response fields

| Field | Type | Description |
| --- | --- | --- |
| trade_id | string | Novig trade id for API fills; `csv:<date>:<line>` for rows from trades.csv, which carries no trade id. |
| market_id | string | Novig market id. |
| outcome_id | string or null | The outcome that was bought. Join to `outcomes[].name` from [GET /v1/markets/{id}](https://novigapi.com/docs/endpoints/market) for its label. |
| price | number | Fill price as a probability. |
| qty | integer | Contracts filled, each paying $0.01. |
| ts | string (ISO 8601) | Fill time in UTC. |
| source | string | `api` (our intraday polling) or `csv` (Novig's daily file). |
| observed_at | string (ISO 8601) or null | When our collector last read this row from Novig. |
| source_age_seconds | integer or null | Seconds between that read and our answer. |
| edge_cached | boolean | True when the value came through Novig's public CDN, which may serve a copy up to its cache time (5 to 10 seconds) older. |
| meta.next_cursor | string or null | Pass as `cursor` to get the next page. Null on the last page. |
| meta.limit, meta.count | integer | The page size used and the rows on this page. |
| meta.observed_at | string (ISO 8601) | When our collector read the oldest row in this answer from Novig's public catalog. Each row also carries its own `observed_at`. |
| meta.source_age_seconds | integer | Seconds between that read and our response. On paid plans this stays at about 10 or less. |
| meta.edge_cached | boolean | True when Novig's edge cache served any of the reads, so the source copy may itself be a few seconds old. |
| meta.plan, credits_charged, credits_remaining, credit_policy | string, integer | Your plan, what this call cost, the credits left this month and the credit rules version. |


## Credit cost

Weighted 3x: 3 credits per call per 100 rows requested (the `limit` you send, default 100, maximum 1,000; Free pages hold at most 100 rows). A default page costs 3 credits. Errors and 304 Not Modified cost 0; the `X-Credits-Cost` header and `meta.credits_charged` state the price of every call.

## Python

```python
import os
import requests

KEY = os.environ["NOVIGAPI_API_KEY"]  # nv_...
HEADERS = {"Authorization": f"Bearer {KEY}"}

mid = "01a1d00f-ec01-71c0-9776-0facc97e44a7"
r = requests.get("https://novigapi.com/api/v1/trades", params={"market_id": mid, "since": "2026-11-12T00:00:00Z", "limit": 1000}, headers=HEADERS, timeout=10)
fills = r.json()["data"]
over_id = "01a1d00f-ec01-71c0-9776-0fb0230cbd18"  # Over 1.5
over = [t for t in fills if t["outcome_id"] == over_id]
contracts = sum(t["qty"] for t in over)
vwap = sum(t["price"] * t["qty"] for t in over) / contracts if contracts else None
print("Over VWAP", vwap, "on", contracts, "contracts")
```

## JavaScript

```javascript
const KEY = process.env.NOVIGAPI_API_KEY; // nv_...
const headers = { Authorization: "Bearer " + KEY };

const mid = "01a1d00f-ec01-71c0-9776-0facc97e44a7";
const res = await fetch("https://novigapi.com/api/v1/trades?market_id=" + mid + "&limit=100", { headers });
const { data } = await res.json();
const dollars = data.reduce((sum, t) => sum + (t.qty * t.price) / 100, 0);
console.log(data.length + " fills, $" + dollars.toFixed(2) + " traded");
```

## Notes and edge cases

- Novig's trades.csv has one row per side (taker and maker) and carries no names; we keep the taker row, one per fill, with its market and outcome.
- Novig publishes the CSV for an Eastern day at about 5 a.m. ET the next morning. Until then, that day's fills come only from our intraday polling.
- Parlay (COMBO) fills in trades.csv are not attached to a single market and are left out of this endpoint.
- Polling cannot prove it saw every fill on a very busy market between reads; the next morning's CSV fills any gap.

## Sources

- [Novig API reference: List trades](https://docs.novig.com/api-reference/catalog/list-trades.md)
- [Novig docs: Trades CSV](https://docs.novig.com/public-data/trades.md)
- [Novig docs: Exchange Data](https://docs.novig.com/public-data/overview.md)
- [Novig exchange data files (data.novig.com)](https://data.novig.com)

---

Get a free API key: https://novigapi.com/sign-up . Docs: https://novigapi.com/docs . MCP: https://novigapi.com/api/mcp . Operated by Stunning Couches LLC. Independent. Not affiliated with, endorsed by or sponsored by Novig.
