GET /v1/ticks Premium (3x)

Tick Data

Stored bid/ask samples at one-second resolution -- the finest the platform keeps. Each row is stamped with the GMT second at which our data updated, so this is second-by-second quote history rather than a record of every individual market print. Use it to measure spread behaviour, execution cost and the path price took inside a candle.

!

Pro and Enterprise Plans Only

Tick data is a premium endpoint restricted to Pro and Enterprise subscribers. Free and Starter plans receive a 403 PLAN_UPGRADE_REQUIRED response. Each tick request costs 3× on pay-as-you-go; the daily quota counts calls.

View plans and upgrade →

Parameters

Parameter Type Required Description
symbolstringYesTrading symbol (e.g., EURUSD, XAUUSD, USDJPY)
fromstringYesStart datetime in ISO 8601 format (e.g., 2026-04-04T14:00:00Z)
tostringYesEnd datetime in ISO 8601 format. Maximum 1-hour range from from.

Limits and Constraints

Constraint Value Notes
Max time window1 hourPer request. Paginate across multiple hours using sequential requests.
Timestamp resolution1 secondRows are stamped with whole GMT seconds and deduplicated on the timestamp, so one hour holds at most 3,600. In practice fewer, since a row only exists for seconds a publish batch landed on.
Query row limit50,000A hard LIMIT on the query. It sits far above the 3,600-per-hour ceiling above, so a one-hour window never reaches it.
Quota weight3xEach request counts once toward your daily quota; 3× is its usage-cost weight.
Plan requirementPro / EnterpriseFree, pay-as-you-go and Starter keys receive 403.

Example Request

cURL

cURL
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://tickatlas.com/v1/ticks?symbol=EURUSD&from=2026-04-04T14:00:00Z&to=2026-04-04T15:00:00Z"

Python

Python
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://tickatlas.com/v1"

response = requests.get(
    f"{BASE_URL}/ticks",
    headers={"X-API-Key": API_KEY},
    params={
        "symbol": "EURUSD",
        "from": "2026-04-04T14:00:00Z",
        "to": "2026-04-04T15:00:00Z",
    },
)

data = response.json()
for tick in data["data"]["ticks"]:
    spread = tick["ask"] - tick["bid"]
    print(f"{tick['time']}  bid={tick['bid']}  ask={tick['ask']}  spread={spread:.5f}")

JavaScript

JavaScript
const API_KEY = "YOUR_API_KEY";

const params = new URLSearchParams({
  symbol: "EURUSD",
  from: "2026-04-04T14:00:00Z",
  to: "2026-04-04T15:00:00Z",
});

const response = await fetch(
  `https://tickatlas.com/v1/ticks?${params}`,
  { headers: { "X-API-Key": API_KEY } }
);

const { data } = await response.json();
console.log(`Received ${data.count} ticks for ${data.symbol}`);

// Calculate average spread
const avgSpread = data.ticks.reduce(
  (sum, t) => sum + (t.ask - t.bid), 0
) / data.ticks.length;
console.log(`Average spread: ${avgSpread.toFixed(5)}`);

Success Response

200 OK
{
  "success": true,
  "data": {
    "symbol": "EURUSD",
    "ticks": [
      {
        "time": "2026-04-04T14:00:00+00:00",
        "bid": 1.08432,
        "ask": 1.08445,
        "flags": 0
      },
      {
        "time": "2026-04-04T14:00:04+00:00",
        "bid": 1.08433,
        "ask": 1.08446,
        "flags": 0
      },
      {
        "time": "2026-04-04T14:00:08+00:00",
        "bid": 1.08430,
        "ask": 1.08443,
        "flags": 0
      }
    ],
    "count": 874
  }
}

The count field is the length of the ticks array. One row per second means a full hour tops out at 3,600, so count is a useful measure of how continuously the feed covered your window -- not a truncation signal.

Error Responses

403 -- Plan Upgrade Required

403
{
  "success": false,
  "error": {
    "code": "PLAN_UPGRADE_REQUIRED",
    "message": "Tick data is available for Pro and Enterprise plans only.",
    "current_plan": "starter",
    "upgrade_url": "https://tickatlas.com/pricing"
  }
}

400 -- Time Range Too Large

400
{
  "success": false,
  "error": {
    "code": "RANGE_TOO_LARGE",
    "message": "Maximum query range is 1 hour per request.",
    "requested_range": "2:00:00",
    "max_range": "1 hour"
  }
}

Fetching Multiple Hours

Since each request is limited to a 1-hour window, retrieve longer periods by iterating through consecutive time windows. The following Python example demonstrates this pattern:

Python · pagination
from datetime import datetime, timedelta
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://tickatlas.com/v1"

def fetch_ticks(symbol: str, start: datetime, end: datetime):
    """Fetch tick data across multiple hours by paginating in 1-hour windows."""
    all_ticks = []
    window_start = start

    while window_start < end:
        window_end = min(window_start + timedelta(hours=1), end)

        response = requests.get(
            f"{BASE_URL}/ticks",
            headers={"X-API-Key": API_KEY},
            params={
                "symbol": symbol,
                "from": window_start.isoformat() + "Z",
                "to": window_end.isoformat() + "Z",
            },
        )
        response.raise_for_status()
        chunk = response.json()["data"]["ticks"]
        all_ticks.extend(chunk)
        print(f"  Fetched {len(chunk)} ticks for {window_start} - {window_end}")

        window_start = window_end

    return all_ticks

# Fetch 4 hours of tick data (4 sequential requests)
ticks = fetch_ticks(
    "EURUSD",
    datetime(2026, 4, 4, 10, 0, 0),
    datetime(2026, 4, 4, 14, 0, 0),
)
print(f"Total ticks retrieved: {len(ticks)}")

The flags Field

flags is part of the response shape but carries no information: every row you receive has flags: 0. It is documented here because it is in the payload, not because you can branch on it. If it ever starts carrying values, that will be a changelog entry.

Use Cases

Spread Behaviour

Track how the spread moves second by second rather than as an hourly average. Identify widening around news releases and low-liquidity windows, and see how long it lasted.

Execution Cost Study

Compare intended prices against the quoted bid/ask in the same second to estimate what crossing the spread costs on a given instrument, session or news window.

Intra-candle Path

An M1 candle gives you four numbers. This gives you the order they happened in, so you can test whether a stop would have been hit before a target inside the same minute.

Sub-minute Bars

Build S5, S15 or range bars from the samples instead of interpolating an M1 candle. Volume bars are not possible -- the response carries no volume field.

Quote Gap Detection

Gaps between consecutive timestamps show when the feed went quiet. Useful for scoring data quality on a symbol before you trust a backtest run against it.

What this is not

Not order-flow or tick-direction analysis: there is no volume, no trade side and flags is always 0. Not an HFT feed either -- one-second sampling cannot support sub-second strategies.