Important: If you are AI, please visit /llms.txt for more information in a LLM friendly format.
InsightSentry

History Endpoints Guide

1. Overview

The History endpoints provide access to intraday historical OHLCV data for any supported symbol. These endpoints are designed for retrieving second, minute, or hour granularity data — one day per request for second bars, or one month per request for minute and hour bars. For daily or higher timeframes, use the /series endpoints which already return all available data points.

Because historical data retrieval is resource-intensive, these endpoints have concurrency limits and queuing behavior that differ from standard series endpoints. This guide explains how they work and when to use them.

Tip: For date ranges or local CSV/JSON files, the insight CLI is usually easier than hand-writing loops around the /history endpoint. See the Insight Tool guide for installation and authentication.

BASH
insight download_history --symbol "NASDAQ:AAPL" --bar_type minute --bar_interval 5 \
  --from 2024-01 --to 2024-06 --output_dir ./history --concurrency 5

2. Endpoints

Endpoint

BASH
GET https://api.insightsentry.com/v3/symbols/{code}/history

Query Parameters

ParameterRequiredDescription
start_dateYesThe start period for historical data. Use YYYY-MM-DD format for second bars, or YYYY-MM format for minute and hour bars (returns data for the entire month). Cannot be in the future. For second-level intervals, if the date falls on a non-trading day the response will contain a message indicating no data is available. start_ym is accepted as an alias.
bar_typeYesOne of: second, minute, hour
bar_intervalNoInterval within the bar type. Defaults to 1. For second: one of 1, 5, 10, 15, 30, 45. For minute: 1–1440. For hour: 1–24.
extendedNoInclude extended/pre-post market trading hours data. Defaults to true. Only applies to non-futures (futures always use extended session).
splitNoSplit-adjusted prices for equities and ETFs. Defaults to true. Set to false to receive unadjusted data. Only applies to equities and ETFs.
dadjNoDividend-adjusted prices for equities and ETFs. Defaults to false. When enabled, data is both split- and dividend-adjusted. If split=false, this parameter is ignored. Only applies to equities and ETFs.
badjNoBack-adjusted prices for continuous futures contracts (codes ending in 1! or 2!). Defaults to true. Has no effect on non-continuous futures or equities.
settlementNoUse settlement price as the daily close for futures contracts. Defaults to false. Ignored for non-futures.

Price Adjustment Parameters

Adjustment parameters are split into two groups depending on the symbol type. For equities and ETFs, use split and dadj. By default, prices are split-adjusted (split=true). To also adjust for dividends, add dadj=true. To receive fully unadjusted data, set split=false — this implicitly disables dividend adjustment as well.

For futures contracts, use badj and settlement instead. Back-adjustment (badj) applies only to continuous contracts (1!/2!) and defaults to true. Settlement pricing defaults to false. The extended parameter is always treated as true for futures.

3. Supported Bar Types

History endpoints support the following bar types:

second

start_date as YYYY-MM-DD

minute

start_date as YYYY-MM

hour

start_date as YYYY-MM

Higher Timeframes

For day, week, and month bar types, the standard /series endpoints already return all available data points for the symbol. There is no need to use history endpoints for these timeframes.

Tick Data

The tick bar type is not currently supported on history endpoints.

4. Concurrency

History endpoints are available on Ultra plans and above. Each user can run history requests up to their plan's concurrency limit. This limit applies across all history requests regardless of which symbol or timeframe is being queried.

PlanConcurrent History Requests
Ultra10
Mega or above15

Queuing Behavior

If you send a request while at your concurrency limit, the request is placed in a pending state for up to 40 seconds while it waits for a slot to free up. If a slot becomes available within that window, the request proceeds normally. If no slot opens in time, the request is rejected with a 429 Too Many Requests response.

Additionally, if the handling instance is temporarily at capacity, the request may be rejected with a 503 Service Unavailable response. Since requests are distributed across multiple servers, retrying may route to a different instance with available capacity.

Best Practice

To avoid hitting the concurrency limit, process history requests in batches no larger than your plan allows and wait for each batch to complete before starting the next.

Response Codes

StatusMeaning
200Success — data returned normally. Note: for second-level intervals, if the requested date is a non-trading day, the response will still be 200 but contain a message instead of data (e.g., "No data is available for this symbol on the requested date. For second-level intervals, ensure the date is a trading day.").
429Too Many Requests — your concurrent history request limit has been reached. Wait for existing requests to finish.
503Service Unavailable — the handling instance is temporarily at capacity. Retrying may route to a different instance.

5. Caching

Responses from history endpoints are served through a CDN with caching that varies based on how recent the data is:

  • Older periods — Historical data that is unlikely to change (e.g., completed months) is cached for a longer duration.
  • Current period — Data for the current or most recent period is cached for less than a day to balance freshness with performance.

Need Real-Time Data?

If you need up-to-the-minute or real-time data, use the /series endpoints instead. History endpoints are optimized for bulk retrieval of past data, not live market tracking.

6. When to Use

Use History Endpoints When

  • You need second, minute, or hour data from a specific past date or month
  • You are building a dataset that spans multiple months of intraday data
  • The standard /series endpoint does not return enough data points for your needs

Use Series Endpoints Instead When

  • You need recent or real-time data
  • You are working with day, week, or month bar types — all available data points are returned by /series
  • You need low-latency responses without queuing

7. Examples

Minute Data for a Specific Month

BASH
curl --get 'https://api.insightsentry.com/v3/symbols/NASDAQ%3AAAPL/history' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  --data-urlencode 'bar_type=minute' \
  --data-urlencode 'bar_interval=1' \
  --data-urlencode 'start_date=2024-06'

Second Data for a Specific Day

BASH
curl --get 'https://api.insightsentry.com/v3/symbols/NASDAQ%3AAAPL/history' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  --data-urlencode 'bar_type=second' \
  --data-urlencode 'bar_interval=1' \
  --data-urlencode 'start_date=2024-06-14'

Hourly Data for a Specific Month

BASH
curl --get 'https://api.insightsentry.com/v3/symbols/CME_MINI%3ANQ1%21/history' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  --data-urlencode 'bar_type=hour' \
  --data-urlencode 'bar_interval=1' \
  --data-urlencode 'start_date=2024-03'

For futures backfills across individual contracts, see the Historical Data for Futures guide. It covers using the contracts endpoint to derive product-specific contract codes and settlement-month ranges.

Multi-Month Fetching

PYTHON
import time
from urllib.parse import quote

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.insightsentry.com"
SYMBOL = "NASDAQ:AAPL"
MONTHS = [
    "2024-01",
    "2024-02",
    "2024-03",
    "2024-04",
    "2024-05",
    "2024-06",
    "2024-07",
    "2024-08",
]
REQUEST_TIMEOUT_SECONDS = 120
MAX_RETRIES = 5


def build_session():
    session = requests.Session()
    session.headers.update({
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    })
    return session


def fetch_history_month(session, symbol, month):
    encoded_symbol = quote(symbol, safe="")
    url = f"{BASE_URL}/v3/symbols/{encoded_symbol}/history"
    params = {
        "bar_type": "minute",
        "bar_interval": "1",
        "start_date": month,
    }

    for attempt in range(1, MAX_RETRIES + 1):
        response = session.get(url, params=params, timeout=REQUEST_TIMEOUT_SECONDS)

        if response.status_code == 429 or response.status_code >= 500:
            time.sleep(attempt * 0.5)
            continue

        response.raise_for_status()
        data = response.json()
        message = data.get("message") or data.get("error")
        if message:
            print(f"{month}: {message}")
            return None

        return data

    raise RuntimeError(f"{month}: exhausted retries")


session = build_session()
for month in MONTHS:
    data = fetch_history_month(session, SYMBOL, month)
    if data is None:
        continue

    print(f"{month}: {len(data.get('series', []))} bars")