Bulk earnings calls

Download every earnings-call transcript as CSV files. Each file holds one fiscal quarter of full transcripts for all companies. One route lists every file together with a signed download link. Add year and period to get one file.

Signed download URLs are valid for one hour after URL generation. Start each file download within this window. If a URL expires, request a new one.

GET/v3.0.0/earnings-calls/bulk

Plan Access

Free

(Your plan)

Individual

$29/mo

Professional

$89/mo

Request
curl "https://api.roic.ai/v3.0.0/earnings-calls/bulk?apikey=YOUR_API_KEY"
Response
200 OK
{
  "data": [
    {
      "id": "bulk_FEGbDNbMZzbiwcG-vJwxAT",
      "dataset": "earnings-calls",
      "year": 2026,
      "period": "q1",
      "format": "csv",
      "compression": "gzip",
      "size": 49424494,
      "sha256": "bd9b729a0e5ad3a53618f5d73faba7fbdfa0a8371fd5bfce97661dea31480397",
      "updated_at": "2026-09-08T01:59:05.203Z",
      "url": "https://bulk.roic.ai/earnings-calls/v3/2026/q1.csv.gz?verify=1789064631-<mac>",
      "expires_at": "2026-09-08T19:23:51.178Z"
    },
    {
      "id": "bulk_of0jPZPSPDYxRXofw1lUPd",
      "dataset": "earnings-calls",
      "year": 2026,
      "period": "q2",
      "format": "csv",
      "compression": "gzip",
      "size": 66855815,
      "sha256": "70b196ab2f583622726fc6c4034ef67480ab1060b653e9a3e76f27f50d29036b",
      "updated_at": "2026-09-08T01:59:09.359Z",
      "url": "https://bulk.roic.ai/earnings-calls/v3/2026/q2.csv.gz?verify=1789064631-<mac>",
      "expires_at": "2026-09-08T19:23:51.178Z"
    }
  ],
  "next_page_url": null,
  "previous_page_url": null
}

Available files

Browse the files and download them from the browser. Downloads require a Professional or Enterprise plan. The route returns the same list with your API key.

Files90 files, 3.49 GB compressed

Fiscal yearPeriodSize
2027
Q1
4.4 MB
2027
Q2
1.7 MB
2026
Q1
49.4 MB
2026
Q2
67.3 MB
2026
Q3
9.7 MB
2026
Q4
10.3 MB
2025
Q1
58.8 MB
2025
Q2
62.6 MB
2025
Q3
60.4 MB
2025
Q4
70.8 MB
2024
Q1
60.0 MB
2024
Q2
64.2 MB
2024
Q3
60.7 MB
2024
Q4
70.1 MB
2023
Q1
62.1 MB
2023
Q2
68.6 MB
2023
Q3
61.8 MB
2023
Q4
72.3 MB
2022
Q1
65.6 MB
2022
Q2
70.8 MB
2022
Q3
66.5 MB
2022
Q4
74.7 MB
2021
Q1
58.5 MB
2021
Q2
66.0 MB
2021
Q3
66.6 MB
2021
Q4
76.3 MB
2020
Q1
59.8 MB
2020
Q2
62.4 MB
2020
Q3
57.6 MB
2020
Q4
65.8 MB
2019
Q1
49.1 MB
2019
Q2
54.3 MB
2019
Q3
52.8 MB
2019
Q4
59.0 MB
2018
Q1
47.0 MB
2018
Q2
49.9 MB
2018
Q3
51.0 MB
2018
Q4
55.5 MB
2017
Q1
44.8 MB
2017
Q2
47.9 MB
2017
Q3
47.6 MB
2017
Q4
51.8 MB
2016
Q1
43.5 MB
2016
Q2
46.0 MB
2016
Q3
45.6 MB
2016
Q4
50.4 MB
2015
Q1
40.7 MB
2015
Q2
44.7 MB
2015
Q3
43.7 MB
2015
Q4
47.1 MB
2014
Q1
35.9 MB
2014
Q2
41.1 MB
2014
Q3
41.6 MB
2014
Q4
45.1 MB
2013
Q1
35.5 MB
2013
Q2
38.3 MB
2013
Q3
37.7 MB
2013
Q4
40.3 MB
2012
Q1
26.4 MB
2012
Q2
30.4 MB
2012
Q3
31.7 MB
2012
Q4
35.5 MB
2011
Q1
14.3 MB
2011
Q2
18.6 MB
2011
Q3
18.8 MB
2011
Q4
25.3 MB
2010
Q1
17.1 MB
2010
Q2
16.3 MB
2010
Q3
15.4 MB
2010
Q4
15.6 MB
2009
Q1
18.4 MB
2009
Q2
17.4 MB
2009
Q3
17.4 MB
2009
Q4
18.1 MB
2008
Q1
21.1 MB
2008
Q2
24.4 MB
2008
Q3
25.1 MB
2008
Q4
26.4 MB
2007
Q1
3.1 MB
2007
Q2
7.4 MB
2007
Q3
13.5 MB
2007
Q4
21.9 MB
2006
Q1
2.6 MB
2006
Q2
3.0 MB
2006
Q3
3.6 MB
2006
Q4
4.1 MB
2005
Q2
12 KB
2005
Q3
357 KB
2005
Q4
2.4 MB
2004
Q4
10 KB

Parameters

Query parameters

yearintegeroptional

Return only the files of this year. Fundamentals and earnings calls use the fiscal year, stock prices use the calendar year. A year without files returns an empty list.

Example: 2026Min: 1900Max: 2100
periodstringoptional

Return only the files of this fiscal quarter: q1, q2, q3, or q4.

Example: q2Values: q1q2q3q4

Response

Each item is one file with its size, its SHA-256 digest, and a signed url. Items are sorted newest fiscal year first, then quarter order. Without filters the list holds every file, so the page URLs are always null. The example response is cut after two files. The response is not cached because every link expires one hour after the request.

Response fields

dataarray of objects

Array of file resources, newest year first. Without filters the array holds every available file, so the page URLs are always null.

+ Show child attributes
idstring

Stable identifier of the file, prefixed bulk_. It is derived from the storage path, so a rebuilt file keeps the same ID.

datasetstring

Dataset the file belongs to: fundamentals, earnings-calls, or stock-prices. The value is plural even for the singular /fundamental/bulk route.

yearnumber

Year of the data in the file. Fundamentals and earnings calls use the fiscal year. Stock prices use the calendar year.

periodstring

Slice of the year in the file. Fundamentals: annual, quarterly, or ttm. Earnings calls: q1 through q4. Stock prices: two-digit month 01 through 12.

formatstring

Always csv. The first row is a header row, and values obey RFC 4180.

compressionstring

Always gzip. Decompress the file before you read the CSV.

sizenumber

Size of the compressed .csv.gz file in bytes. The decompressed CSV is about three to four times larger.

sha256string

SHA-256 hex digest of the compressed file exactly as delivered. Compare it with the digest of your download before you decompress.

updated_atstring

ISO 8601 timestamp of the last rebuild of this file.

urlstring

Signed download link on bulk.roic.ai. Send a plain GET request without your API key and keep the verify token intact. Treat the link as a secret. The file host refuses links without a valid token.

expires_atstring

ISO 8601 timestamp after which url stops working, one hour after the request. Call the route again for fresh links if they expire before you start a download.

next_page_urlnullable

Relative URL of the next page, or null on the last page. Never contains your API key.

previous_page_urlnullable

Relative URL of the previous page, or null on the first page.

File contents

Each file is a gzip-compressed CSV with a header row. Rows are sorted by symbol. One row is one call. The transcript column holds the full text of the call with each speaker turn on its own line.

ColumnTypeMeaning
idstringStable call ID with the ecall_ prefix, the same as the API.
symbolstringExchange-qualified ticker, for example NASDAQ:AAPL.
fiscal_yearintegerFiscal year that the call reports on.
fiscal_quarterintegerFiscal quarter that the call reports on, from 1 to 4.
datedateDate of the call in YYYY-MM-DD format.
transcriptstringFull transcript text. Speaker turns are separated by line breaks.

The first rows of the fiscal 2026 Q2 file, with the transcript text cut short:

id,symbol,fiscal_year,fiscal_quarter,date,transcript
ecall_wq5rd85raHX4Jm,AMEX:ACCS,2026,2,2026-08-11,"Forrest MacConnell: Welcome to ACCESS Newswire's Second Quarter 2026 Earnings Conference Call. ...
Brian Balbirnie: Thank you, Forrest, and good morning, everyone, ...
Steven Knerr: Thank you, Brian, and good morning, everyone. ..."

Transcripts contain line breaks and quotes, escaped as RFC 4180 requires. Use a real CSV parser. Do not split the file on line breaks.

Fiscal years run ahead of calendar years for some companies, so files for the next fiscal year can already exist. The route is the authoritative answer for what exists.

Download, verify, and decompress

Run these commands to download one quarter, verify the digest, and decompress the file. Replace YOUR_API_KEY with your key.

# 1. Get the link and the digest of one file
RESP=$(curl -s -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.roic.ai/v3.0.0/earnings-calls/bulk?year=2026&period=q2")
URL=$(echo "$RESP" | jq -r '.data[0].url')
SHA=$(echo "$RESP" | jq -r '.data[0].sha256')
 
# 2. Download the file before the link expires
curl -o roic-earnings-calls-2026-q2.csv.gz "$URL"
 
# 3. Verify the digest
echo "$SHA  roic-earnings-calls-2026-q2.csv.gz" | shasum -a 256 -c
 
# 4. Decompress and keep the archive for the examples below
gunzip -k roic-earnings-calls-2026-q2.csv.gz

To read the transcripts in Python, raise the field size limit first. A transcript can be longer than the default limit of the csv module.

import csv
import gzip
import sys
 
csv.field_size_limit(sys.maxsize)
 
with gzip.open("roic-earnings-calls-2026-q2.csv.gz", "rt", newline="") as csv_file:
    for row in csv.DictReader(csv_file):
        print(row["symbol"], row["date"], len(row["transcript"]))

Errors

StatusCodeCause
400invalid_parameterperiod is not q1, q2, q3, or q4, or year is not a number.
401authentication_requiredThe API key is missing. Related codes: invalid_api_key and multiple_authentication_methods.
402bulk_download_restrictedThe plan does not include bulk downloads.
429rate_limit_exceededThe request limit is reached. Retry after Retry-After.

A year without files returns an empty data array. The file host bulk.roic.ai blocks a link without a valid verify token or after expires_at. Call the route again for fresh links.