Download material contracts (Exhibit 10) from SEC filings
Find 8-Ks that report a new material agreement (Item 1.01), list their Exhibit 10 contracts and download them: credit agreements, purchase agreements, warrants and amendments.
Material contracts are filed as Exhibit 10: credit agreements, merger and purchase agreements, employment agreements, leases, warrants and their amendments. They are the primary source for loan covenants, deal terms and executive pay arrangements, and they are full text, often tens of thousands of words.
They show up in three places:
- 8-K Item 1.01 (entry into a material definitive agreement), often with the contract attached
- 10-Q and 10-K Item 6 / Item 15 exhibit lists, where many companies file the contract a quarter later
- Registration statements (S-1, S-4), which attach the material contracts of the business
This tutorial uses the first: it reads the newest Item 1.01 8-Ks and downloads their Exhibit 10 documents.
The script
The helpers are the same as in Download 8-K Exhibit 99: exhibits() reads the document table of a filing index page, to_text() strips HTML.
import html
import os
import re
import requests
BASE = "https://secfeedapi.com"
HEADERS = {"Authorization": f"Bearer {os.environ['SECFEED_KEY']}"}
def get(path, **params):
r = requests.get(f"{BASE}{path}", params=params, headers=HEADERS, timeout=120)
r.raise_for_status()
return r
def exhibits(index_url):
"""[(type, description, url)] from the filing index page's document table."""
page = get("/v1/download", url=index_url).text
rows = re.findall(r'<td scope="row">([^<]*)</td>\s*<td scope="row"><a href="([^"]+)">[^<]*</a>.*?</td>\s*<td scope="row">([^<]*)</td>',
page, flags=re.S)
return [(typ.strip(), desc.strip(), "https://www.sec.gov" + href.replace("/ix?doc=", "")) for desc, href, typ in rows]
def to_text(doc):
doc = re.sub(r"(?is)<(head|script|style).*?</\1>", " ", doc)
doc = re.sub(r"(?i)<br\s*/?>|</(p|div|tr|h\d)>", "\n", doc)
return html.unescape(re.sub(r"<[^>]+>", " ", doc)).replace("\xa0", " ")
# 1. 8-Ks reporting a new material definitive agreement (Item 1.01)
events = get("/v1/form-8k", item="1.01", startDate="2026-10-08", size=8).json()["filings"]
os.makedirs("ex10", exist_ok=True)
found = 0
for e in events:
# 2. the Exhibit 10 documents attached to each 8-K
ex10 = [x for x in exhibits(e["url"]) if re.fullmatch(r"EX-10(\.\d+)?", x[0])] # not EX-101 (XBRL)
if not ex10:
continue # many companies file the contract later, with the next 10-Q
print(f"{e['company']} ({e['filed']})")
for typ, desc, url in ex10:
doc = get("/v1/download", url=url).text
open(os.path.join("ex10", url.rsplit("/", 1)[1]), "w").write(doc)
text = to_text(doc)
lines = [" ".join(l.split()) for l in text.splitlines() if len(l.split()) >= 2]
# contract titles are usually a short line in capitals near the top
title = next((l for l in lines[:60] if l.isupper() and len(l) < 90 and re.search(r"AGREEMENT|AMENDMENT|PLAN|NOTE|INDENTURE|LEASE", l)),
next((l for l in lines if not l.upper().startswith("EXHIBIT")), ""))
print(f" {typ:<8} {len(text.split()):>7,} words {title[:80]}")
found += 1
if found == 4:
break
print(f"\n{found} of {len(events)} Item 1.01 8-Ks had Exhibit 10 attached")
Output
ADC Therapeutics SA (2026-10-13)
EX-10.1 17,969 words SECURITIES PURCHASE AGREEMENT
EX-10.2 6,343 words THIS WARRANT AND THE SHARES ISSUABLE
EX-10.3 6,371 words SECOND AMENDMENT TO LOAN AGREEMENT
EX-10.4 847 words AMENDMENT TO WARRANT TO PURCHASE
EX-10.5 4,407 words AMENDMENT NO. 2 TO PURCHASE AND SALE AGREEMENT
Select Water Solutions, Inc. (2026-10-13)
EX-10.1 106,864 words CREDIT AGREEMENT
Mitesco, Inc. (2026-10-13)
EX-10.1 72 words October 6, 2026
EX-10.2 13,835 words THE ISSUANCE AND SALE OF THE SECURITIES REPRESENTED BY THIS CERTIFICATE NOR THE
EX-10.3 22,772 words SECURITIES PURCHASE AGREEMENT (the “Agreement”), dated as of October _____, 2026
3 of 8 Item 1.01 8-Ks had Exhibit 10 attached
Reading it
- Only some Item 1.01 8-Ks attach the contract. Three of eight here. The rest describe the agreement in the 8-K text and file the document later as an exhibit to the next 10-Q, which Regulation S-K allows.
- One event, many contracts. ADC Therapeutics filed a financing package: a securities purchase agreement, a warrant, a loan agreement amendment, a warrant amendment and a purchase agreement amendment.
- Size varies a lot. A credit agreement can run past 100,000 words (Select Water Solutions). A 72 word exhibit is usually a short letter or a cover page.
- Watch the XBRL exhibits.
EX-101.SCH,EX-101.LABand similar are XBRL files, not contracts. The script matchesEX-10andEX-10.nexactly to skip them.
Variations
- Contracts in periodic reports. Search 10-Q and 10-K filings, then apply the same
exhibits()filter. Exhibits incorporated by reference to an earlier filing are not attached again, so only new contracts appear. - Full-text search inside contracts. Full-Text Search indexes exhibits too: search for
"financial covenant" "consolidated leverage ratio"withformTypes=8-Kto find credit agreements by their terms. - Track a counterparty. Search exhibit text for a lender's or partner's name to list every company that signed with it.