Transcripts & Corporate Events
Full-text S&P Capital IQ earnings-call transcripts and the complete Key Developments corporate-event ledger — the licensed, multi-decade archive that no competitor sells self-serve. Read what executives actually said, turn by turn with named speakers and roles, and pull a company's entire corporate history: M&A, guidance changes, executive changes, buybacks, litigation, offerings, activism and 100+ more event types back to 1990.
This is part of the Tengu vault — differentiated data we license and warehouse directly (1.75M transcript versions, ~24M speaker-turn components, 41.9M Key Developments events) rather than proxy from a public API. Everything below serves from FIRM's own lakehouse.
What's inside#
- Earnings-call transcripts — 1.75M transcript versions from S&P Capital IQ, one clean row per call. Duplicate versions of the same call are collapsed to the best available copy (Proofed > Edited > Spellchecked), so you always get the most authoritative text.
- Full transcript text with speakers — ~24M speaker-turn components rendered as an ordered script: each turn carries the speaker's name, their role (executive / analyst / operator) and the component type (prepared remarks / question / answer). Slice to just the prepared remarks or just the analyst Q&A.
- Full-text search — search call headlines across every company, or search the spoken words inside one company's transcripts and get back per-call hit counts and a first-hit snippet.
- Key Developments events — 41.9M dated corporate events, 1990–2026: M&A announcements/closings, corporate guidance (raised/lowered/new), executive & board changes, buybacks, bankruptcy, index adds/drops, offerings, investor activism, litigation and more. Each event carries a headline and a situation summary.
- Event-type taxonomy — the full 105-type legend (id, human label, and the filter slug) so you can filter
/events/{ticker}precisely.
Coverage caveats (stated honestly):
- Full transcript text covers 2020-01-01 → 2025-12-31. Calls outside that window return their metadata (headline, date, event type) but no spoken words. Responses carry an explicit
noteto this effect. - Key Developments events cover 1990–2026.
- Ticker resolution is US-Compustat-scoped. Tickers map exchange symbol → Compustat
gvkey→ Capital IQcompanyid; a symbol Compustat doesn't cover returns an explicitticker_not_resolvederror rather than a wrong company. - These tables are large and archival — treat them as a deep, authoritative record, not a real-time wire.
Access#
3 credits/call. Pro plan ($499/mo) or higher. Every endpoint requires a valid API key. All reads serve from FIRM's warehouse via bounded Athena pushdowns; errors and empty results come back as explicit error / warning fields inside a 200 envelope (never a 500).
Endpoints#
| Method | Path | Description |
|---|---|---|
GET | /api/v3/transcripts/{ticker} | List a company's calls (newest first), one row per call. Query: since (YYYY-MM-DD, calls on/after), limit (1–100, default 25). Returns {ticker, company, companyid, gvkey, n, transcripts[], note, source}; each item has event_id, keydev_id, date, title, event_type, version, version_status. |
GET | /api/v3/transcripts/{ticker}/{event_id} | Full transcript text as ordered speaker turns. event_id is the id from the list/search route. Query: components (all|presentation|qa, default all), max_turns (1–1500, default 800). Returns {ticker, event_id, transcript, components, n_turns, turns[], source}; each turn has order, section, component_type, speaker, speaker_role, text. Capped at ~2 MB (truncated: true when hit). |
GET | /api/v3/transcripts/search | Full-text search across transcripts. Query: q (required, 3–80 chars), ticker (optional, restrict to one company), since (YYYY-MM-DD), scope (headlines|text, default headlines), limit (1–50, default 20). scope=headlines searches call titles across all companies; scope=text searches the spoken words and requires ticker. Returns {query, scope, ticker, n, results[], source}. |
GET | /api/v3/events/{ticker} | Key Developments corporate-event history (newest first). Query: type (comma-separated slugs or numeric ids from /events/types), since, until (YYYY-MM-DD window), limit (1–500, default 100). Returns {ticker, company, gvkey, n, events[], filters, source}; each event has keydev_id, type_id, type, type_slug, date, announced, headline, situation. |
GET | /api/v3/events/types | The event-type taxonomy (105 types). Returns {n, types[], source} where each type is {id, label, slug}. Use the slug (or id) in the type filter of /events/{ticker}. |
Examples#
Example 1: List a company's calls, then pull one transcript (bash + curl)#
Find Apple's most recent calls, then fetch the full Q&A section of one of them (3 credits per call).
1# 1. List the 5 most recent calls (3 credits)2curl -H "Authorization: Bearer $TENGU_API_KEY" \3 "https://firm.tengu.co/api/v3/transcripts/AAPL?limit=5"4 5# Response envelope:6# {7# "ok": true,8# "timestamp": "2026-07-19T14:22:00Z",9# "ticker": "AAPL",10# "company": "APPLE INC",11# "companyid": 24937,12# "gvkey": "001690",13# "n": 5,14# "transcripts": [15# {16# "event_id": 2864051,17# "keydev_id": 998123456,18# "date": "2025-10-30",19# "title": "Apple Inc., Q4 2025 Earnings Call, Oct 30, 2025",20# "event_type": "Earnings Calls",21# "version": "Proofed Copy",22# "version_status": "Final"23# }24# // ... 4 more25# ],26# "note": "full text coverage is 2020-01-01 → 2025-12-31; calls outside that window have metadata only.",27# "source": "warehouse:bronze.ciq_transcript_meta"28# }29 30# 2. Pull just the analyst Q&A of that call using its event_id (3 credits)31curl -H "Authorization: Bearer $TENGU_API_KEY" \32 "https://firm.tengu.co/api/v3/transcripts/AAPL/2864051?components=qa&max_turns=400"33 34# Response envelope:35# {36# "ok": true,37# "timestamp": "2026-07-19T14:22:05Z",38# "ticker": "AAPL",39# "event_id": 2864051,40# "transcript": {41# "event_id": 2864051,42# "keydev_id": 998123456,43# "date": "2025-10-30",44# "title": "Apple Inc., Q4 2025 Earnings Call, Oct 30, 2025",45# "event_type": "Earnings Calls",46# "version": "Proofed Copy",47# "version_status": "Final"48# },49# "components": "qa",50# "n_turns": 128,51# "turns": [52# {53# "order": 42,54# "section": "qa",55# "component_type": "question",56# "speaker": "Erik Woodring",57# "speaker_role": "analyst",58# "text": "Thanks for taking my question. Tim, on Services gross margin..."59# },60# {61# "order": 43,62# "section": "qa",63# "component_type": "answer",64# "speaker": "Timothy Cook",65# "speaker_role": "executive",66# "text": "Yeah, thanks Erik. On Services, we feel great about the momentum..."67# }68# // ... more turns69# ],70# "source": "warehouse:bronze.ciq_transcript_text"71# }If a call falls outside the 2020–2025 text window, the transcript route returns the metadata plus "warning": "no_text_for_transcript". If the response hits the ~2 MB cap it sets "truncated": true; re-fetch the sections separately with components=presentation and components=qa.
Example 2: Full-text search across transcripts (Python)#
Search call headlines across every company, then search the spoken words inside one company's transcripts (3 credits per call).
1import os, requests2 3HEADERS = {"Authorization": f"Bearer {os.environ['TENGU_API_KEY']}"}4BASE = "https://firm.tengu.co"5 6# 1. Headline search across ALL companies (default scope)7r = requests.get(8 f"{BASE}/api/v3/transcripts/search",9 params={"q": "artificial intelligence", "limit": 10},10 headers=HEADERS, timeout=30,11)12r.raise_for_status()13data = r.json()14print(f"{data['n']} calls with '{data['query']}' in the title")15for hit in data["results"]:16 print(f" {hit['date']} {hit['title']} (event_id={hit['event_id']})")17 18# 2. Full-text search inside ONE company's transcripts (scope=text REQUIRES ticker)19r = requests.get(20 f"{BASE}/api/v3/transcripts/search",21 params={"q": "supply chain", "ticker": "TSLA", "scope": "text",22 "since": "2024-01-01", "limit": 10},23 headers=HEADERS, timeout=30,24)25r.raise_for_status()26data = r.json()27# Envelope:28# {29# "ok": true,30# "timestamp": "2026-07-19T14:23:00Z",31# "query": "supply chain",32# "scope": "text",33# "ticker": "TSLA",34# "n": 6,35# "results": [36# {37# "event_id": 3120774,38# "hits": 9,39# "snippet": "...our supply chain has never been more resilient, and we expect..."40# }41# // ... more calls, most hits first42# ],43# "searched_recent_calls": 42,44# "note": "full text coverage is 2020-01-01 → 2025-12-31; calls outside that window have metadata only.",45# "source": "warehouse:bronze.ciq_transcript_text"46# }47for hit in data["results"]:48 print(f" event_id={hit['event_id']} {hit['hits']} hits — {hit['snippet']}")Note: scope=text without a ticker returns 422 ticker_required_for_text_search — text search scans transcript bodies and must be scoped to a single company to stay inside the request budget. Pass any returned event_id to /api/v3/transcripts/{ticker}/{event_id} for the full text.
Example 3: Corporate events + the type taxonomy (bash + Python)#
Look up the event-type legend, then pull Microsoft's M&A and guidance events since 2023 (3 credits per call).
1# 1. Fetch the taxonomy so you know the filter slugs/ids (3 credits)2curl -H "Authorization: Bearer $TENGU_API_KEY" \3 "https://firm.tengu.co/api/v3/events/types"4 5# Response envelope (105 types):6# {7# "ok": true,8# "timestamp": "2026-07-19T14:24:00Z",9# "n": 105,10# "types": [11# { "id": 1, "label": "Seeking to Sell/Divest", "slug": "seeking_to_sell_divest" },12# { "id": 27, "label": "Corporate Guidance - Raised", "slug": "corporate_guidance_raised" },13# { "id": 48, "label": "Earnings Calls", "slug": "earnings_calls" },14# { "id": 80, "label": "M&A Transaction Announcements", "slug": "m_and_a_transaction_announcements" },15# { "id": 101,"label": "Executive Changes - CEO", "slug": "executive_changes_ceo" }16# // ... 100 more17# ],18# "source": "warehouse:bronze.ciq_keydev (static legend, inspected 2026-07-17)"19# }1import os, requests2 3# 2. Microsoft M&A announcements + raised guidance since 20234r = requests.get(5 "https://firm.tengu.co/api/v3/events/MSFT",6 params={7 "type": "m_and_a_transaction_announcements,corporate_guidance_raised", # or "80,27"8 "since": "2023-01-01",9 "limit": 25,10 },11 headers={"Authorization": f"Bearer {os.environ['TENGU_API_KEY']}"},12 timeout=30,13)14r.raise_for_status()15data = r.json()16# Envelope:17# {18# "ok": true,19# "timestamp": "2026-07-19T14:24:10Z",20# "ticker": "MSFT",21# "company": "MICROSOFT CORP",22# "gvkey": "012141",23# "n": 25,24# "events": [25# {26# "keydev_id": 1044556677,27# "type_id": 80,28# "type": "M&A Transaction Announcements",29# "type_slug": "m_and_a_transaction_announcements",30# "date": "2023-10-13",31# "announced": "2023-10-13",32# "headline": "Microsoft Corporation completes acquisition of ...",33# "situation": "Microsoft Corporation announced that it has ..."34# }35# // ... more events, newest first36# ],37# "filters": { "type_ids": [27, 80], "since": "2023-01-01", "until": null },38# "source": "warehouse:bronze.ciq_keydev"39# }40for e in data["events"]:41 print(f" {e['date']} [{e['type']}] {e['headline']}")An unknown type slug/id returns 422 unknown_event_type with a hint to call /api/v3/events/types. A ticker Compustat doesn't cover returns "error": "ticker_not_resolved", and a valid ticker with no matching events returns "warning": "no_events_for_filters" — both inside a normal 200 envelope.
Related#
- API reference — complete endpoint listing and per-plan access
- Pricing & credits — plan tiers, credit costs, and add-ons
- Funds & Institutional — 13F holdings, top shareholders, and Form-4 insider activity
- Fundamentals — financial statements and estimates to pair with the transcript text