Home / Guides / Exhibits
Exhibits

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.LAB and similar are XBRL files, not contracts. The script matches EX-10 and EX-10.n exactly 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" with formTypes=8-K to 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.

Next steps

More exhibits guides

Run this guide with your own key

500 free API calls a month. Every example on this page works on the free plan.

Get free API key →