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.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| symbol | string | Yes | Trading symbol (e.g., EURUSD, XAUUSD, USDJPY) |
| from | string | Yes | Start datetime in ISO 8601 format (e.g., 2026-04-04T14:00:00Z) |
| to | string | Yes | End datetime in ISO 8601 format. Maximum 1-hour range from from. |
Limits and Constraints
| Constraint | Value | Notes |
|---|---|---|
| Max time window | 1 hour | Per request. Paginate across multiple hours using sequential requests. |
| Timestamp resolution | 1 second | Rows 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 limit | 50,000 | A 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 weight | 3x | Each request counts once toward your daily quota; 3× is its usage-cost weight. |
| Plan requirement | Pro / Enterprise | Free, pay-as-you-go and Starter keys receive 403. |
Example Request
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
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
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
{
"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
{
"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
{
"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:
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.