Exchange Delisting Notices (Form 25)
Form 25 and 25-NSE notices striking a security from a national exchange, with the exchange that filed it, the issuer, the class of security, and the SEC rule provision - which separates an involuntary delisting from a preferred series simply reaching maturity.
edgar_delisting_notices - the dataset name to pass to the Obscura API.
What one row means
One **Form 25** notification that a class of securities is being removed from listing and registration on a national securities exchange - a DELISTING, dated, attributed to an exchange and an issuer, and identified down to the individual class of security. Nothing else in this catalogue carries a delisting as a first-class event. `edgar_filings` records that a `25-NSE` exists; the derived SPAC view flags `is_delisted` as a boolean over form types. Neither says WHICH exchange, WHICH class of security, or UNDER WHICH RULE - and the last of those is the difference between a company being thrown off the exchange and a preferred series simply maturing. # THE FORM COMES IN TWO SHAPES AND ONLY ONE IS STRUCTURED * **`25-NSE` / `25-NSE/A` - filed BY THE EXCHANGE.** A ~4 KB submission whose payload is a `notificationOfRemoval` XML document: exchange, issuer, file number, the class of security in words, the rule provision relied on, and the signer. The schema is `X0203` and it has not changed - verified byte-shape identical on samples from 2008-02-29 (American Stock Exchange), 2011, 2019, 2024 (NYSE, Nasdaq) and 2026-02-13. Every structured column below comes from here. ~420 filings a quarter. * **`25` / `25/A` - filed BY THE ISSUER**, withdrawing voluntarily. **HTML prose, no XML at all**, with the rule provision expressed as a ballot-box glyph inside filer-specific markup. ~30 filings a quarter. These rows carry the header facts and `filed_by_exchange = false`, and every XML-derived column is NULL. Nothing is inferred from the prose: see the dataset doc for why the checkbox is not parsed. # ONE NOTICE IS TWO ARCHIVE PATHS A `25-NSE` associates the EXCHANGE and the ISSUER, and EDGAR indexes it under both CIK paths - measured over three dissemination days spanning 2024-2026, **all 12 `25-NSE` accessions have exactly two paths, never one and never three**, while both `25` accessions have one. The row is keyed on the accession so an exchange-filed delisting is one event rather than two. See `docs/datasets/edgar_delisting_notices.md` and `docs/availability/edgar_delisting_notices.md`.
One row per One row per Form 25 submission (25, 25/A, 25-NSE, 25-NSE/A), keyed by its ACCESSION. One submission removes ONE class of security from ONE exchange, so the row is also one (issuer, exchange, security class) delisting event - an issuer delisting its common stock and its warrants files two separate notices and gets two rows, which is correct because they are two events with two rule provisions. The key is the accession and NOT the archive path because EDGAR indexes an exchange-filed notice under BOTH the exchange's CIK path and the issuer's: measured over three dissemination days spanning 2024-2026, all 12 25-NSE accessions carry exactly two index paths. Keying on the path would double every exchange-filed delisting and, worse, would attribute one of the two copies to the exchange rather than the issuer..
Point-in-time availability
Every Obscura dataset carries available_date: the calendar day the publisher made the row
available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the
same thing on every dataset in the catalog.
For edgar_delisting_notices: filing_join: available_date is the EDGAR DISSEMINATION day, taken from the bronze object's own day partition, never from the header's FILED AS OF DATE (SEC back-dates that field on 4.88 % of the EDGAR corpus). WHY this family carries no separate event date: a Form 25 IS a publication - the notification to the SEC and the market is the act, and the removal it announces takes effect ten days LATER under Rule 12d2-2(d)(1), so the only other date in play is in the future and cannot be an occurred_on. signature_date, the day the exchange's officer signed the notice, is stored as its own named column and is NOT the conformed event date: it equalled the dissemination day on 7 of 7 sampled notices spanning 2008-2026, so promoting it would assert a distinction that has not been observed. Evidence class B; see docs/availability/edgar_delisting_notices.md.
Refresh cadence
Obscura refreshes edgar_delisting_notices every 6 hours - the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.
Schema - 27 columns
The full public column list for edgar_delisting_notices, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/edgar_delisting_notices.
| Column | Type | Description |
|---|---|---|
| accession | text · not null | PK. SEC accession number of the notification, e.g. `0000876661-24-000276`. On an exchange-filed notice the accession prefix is the EXCHANGE's own CIK (`0000876661` NYSE, `0001354457` Nasdaq, `0001143313` the former American Stock Exchange), because the exchange is the transmitting filer. |
| filename | text · not null | The ISSUER's SEC EDGAR Archives path for this notice (`edgar/data/{issuer_cik}/{accession}.txt`), derived from the payload rather than from whichever of the notice's two index rows was walked - so it is the same value on every ingestion path, and it is the ISSUER's path deliberately, because that is the side a consumer joins on. The join key into `edgar_filings`. |
| available_date | date | Public availability date: the EDGAR DISSEMINATION day, recovered from the bronze object's day partition. The point-in-time anchor and the only date a backtest may key on - and on a delisting that matters, because the notice is what tells the market the listing is ending. |
| accepted_at | timestamp with time zone | When SEC ACCEPTED the submission (`<ACCEPTANCE-DATETIME>`), US-Eastern wall clock under a UTC type. Provenance only. NULL on a row ingested from the dissemination feed, whose envelope does not carry this stamp - a fact about the envelope, not a decoder gap. |
| filed_as_of | date | SEC's LEGAL filing date (`FILED AS OF DATE`). Kept for parity with `edgar_filings`; never an availability date. |
| signature_date | date | The date the exchange's officer signed the notification (`<signatureData><signatureDate>`). Deliberately NOT the conformed event date: it equalled the dissemination day on 7 of 7 sampled notices spanning 2008-2026, so it carries no observed distinction from `available_date`, and the removal itself takes effect ten days after filing rather than on this day. NULL on an issuer-filed `25`, which states its date only in prose. |
| form_type | text · not null | The submission type exactly as EDGAR states it: `25-NSE`, `25-NSE/A`, `25` or `25/A`. Measured as the complete family on five quarterly form indexes spanning 2011-2026. |
| is_amendment | boolean · not null | TRUE when this is an amendment (`25/A` or `25-NSE/A`) correcting an earlier notice. Uncommon - 16 of 431 in 2026Q1 - and derived from `form_type`; the migration CHECKs the derivation rather than trusting the writer. |
| filed_by_exchange | boolean · not null | **WHO IS DELISTING WHOM.** TRUE for a `25-NSE`/`25-NSE/A`, where the EXCHANGE files to strike the security; FALSE for a `25`/`25/A`, where the ISSUER files to withdraw voluntarily. It is also the flag that says whether the structured columns on this row can be populated at all: only the exchange-filed shape carries the `notificationOfRemoval` XML. Derived from `form_type`, and CHECKed in the migration. |
| has_structured_notice | boolean · not null | TRUE when the submission carried the machine-readable `notificationOfRemoval` payload that fills `security_description`, `rule_provision` and the signature columns. The direct test of whether those columns being NULL on this row means "not stated" or "not machine-readable" - FALSE on every issuer-filed `25`, whose body is HTML prose. |
| exchange_cik | bigint | Central Index Key of the EXCHANGE filing the notification, from `<exchange><cik>`. NULL on an issuer-filed `25`, where no exchange is a party to the submission. |
| exchange_name | text | **WHICH EXCHANGE the security is being removed from**, as the exchange states its own name: `NEW YORK STOCK EXCHANGE LLC`, `Nasdaq Stock Market LLC`, `NYSE American LLC`, `Cboe BZX Exchange, Inc.`, `AMERICAN STOCK EXCHANGE LLC`. Together with `exchange_cik` this is a stable venue key - the CIK survives the renames the name does not. |
| issuer_cik | bigint | **Central Index Key of the ISSUER being delisted.** From `<issuer><cik>` on an exchange-filed notice and from the header's `FILER:` block on an issuer-filed one, so it is populated on every row - this is the column the dataset is joined on. |
| issuer_name | text | The issuer's name, e.g. `GLOBAL PARTNERS LP`, `SPIRE INC`, `Theseus Pharmaceuticals, Inc.`. |
| issuer_file_number | text | The issuer's Exchange Act file number, e.g. `001-32593` - the registration the listing hangs off, and the join back to the issuer's other Section 12(b) filings. |
| sic_code | integer | The issuer's SIC code from its own header block. |
| state_of_incorporation | text | The issuer's state or country of incorporation as an EDGAR code (`MA`, `DE`, `E9` Cayman Islands). |
| issuer_city | text | The issuer's city, from `<issuer><address>` on an exchange-filed notice or the header's business address otherwise. |
| issuer_state | text | The issuer's state-or-country code from the same address block. |
| security_description | text | **WHICH CLASS OF SECURITY is being removed**, in the exchange's own words (`<descriptionClassSecurity>`): `Depositary Shares, each representing a 1/1,000th interest in a share of 5.90% Series A Cumulative Redeemable Perpetual Preferred Stock`, `9.75% Series A Fixed-to-Floating Rate Cumulative Redeemable Perpetual Preferred Units`, `Partial Principal Protected Notes linked to the S&P 500 Index`. **This is the column that separates a company delisting from a routine instrument retirement** - most Form 25 volume is preferreds, warrants and structured notes reaching maturity, not common stock leaving an exchange. Free text, deliberately not normalised into a class enum: the exchanges write it as prose and any bucketing would be our inference rather than their statement. NULL on an issuer-filed `25`. |
| rule_provision | text | **UNDER WHICH RULE the security is being struck**, verbatim from `<ruleProvision>` - the reason for the delisting, stated by the exchange: `17 CFR 240.12d2-2(a)(1)` (the class was called for redemption, maturity or retirement), `(a)(2)` (it expired by its own terms), `(a)(3)` (all classes of the series were removed), `(a)(4)` (it was substituted or replaced), `(b)` (**the exchange complied with its own rules to strike the class - an involuntary delisting**), `(c)` (voluntary withdrawal by the issuer). NULL on an issuer-filed `25`, where it is a ballot-box glyph in HTML rather than a stated value. |
| rule_paragraph | text | The rule provision reduced to its paragraph alone - `a1`, `a2`, `a3`, `a4`, `b`, `c` - for grouping and filtering without string matching on a CFR citation. Derived purely from `rule_provision` in this row; NULL when that is NULL or does not match the citation shape. |
| signature_name | text | Name of the exchange officer who signed the notification (`<signatureName>`). |
| signature_title | text | That officer's title (`<signatureTitle>`), e.g. `Analyst, Regulation`, `Analyst, Market Watch`, `Manager, Corporate Actions and Proxy Rulings`. |
| schema_version | text | The `notificationOfRemoval` schema version the exchange filed against (`<schemaVersion>`), `X0203` on every sampled notice from 2008 to 2026. Stored so a future schema change is visible in the data rather than as a silent shift in which columns fill. |
| document_count | integer | Number of documents in the submission (`PUBLIC DOCUMENT COUNT:`). 2 on a typical exchange-filed notice (the XML plus an `EX-99.25` rule-provision notice), 1 on an issuer-filed one. |
| exhibits | jsonb · not null | Ordered JSON array of every document in the submission as `[{"type":…,"sequence":…,"filename":…,"description":…}]`. The `EX-99.25` member is the exchange's rule-provision notice - on NYSE it states the intended removal date and the trading-suspension date in prose, and on Nasdaq it is a two-word stub. That inconsistency is measured and is exactly why no removal date is extracted into a column; the inventory points at the document instead. |
Access edgar_delisting_notices
Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.
import obscura
client = obscura.Client("obs_live_…")
df = client.query(
dataset="edgar_delisting_notices",
symbols=["NVDA", "AAPL"],
start="2024-01-01",
)
Create a free account Browse all 122 datasets
Frequently asked questions
What is in the edgar_delisting_notices dataset?
Form 25 and 25-NSE notices striking a security from a national exchange, with the exchange that filed it, the issuer, the class of security, and the SEC rule provision - which separates an involuntary delisting from a preferred series simply reaching maturity. One **Form 25** notification that a class of securities is being removed from listing and registration on a national securities exchange - a DELISTING, dated, attributed to an exchange and an issuer, and identified down to the individual class of security. Nothing else in this catalogue carries a delisting as a first-class event. `edgar_filings` records that a `25-NSE` exists; the derived SPAC view flags `is_delisted` as a boolean over form types. Neither says WHICH exchange, WHICH class of security, or UNDER WHICH RULE - and the last of those is the difference between a company being thrown off the exchange and a preferred series simply maturing. # THE FORM COMES IN TWO SHAPES AND ONLY ONE IS STRUCTURED * **`25-NSE` / `25-NSE/A` - filed BY THE EXCHANGE.** A ~4 KB submission whose payload is a `notificationOfRemoval` XML document: exchange, issuer, file number, the class of security in words, the rule provision relied on, and the signer. The schema is `X0203` and it has not changed - verified byte-shape identical on samples from 2008-02-29 (American Stock Exchange), 2011, 2019, 2024 (NYSE, Nasdaq) and 2026-02-13. Every structured column below comes from here. ~420 filings a quarter. * **`25` / `25/A` - filed BY THE ISSUER**, withdrawing voluntarily. **HTML prose, no XML at all**, with the rule provision expressed as a ballot-box glyph inside filer-specific markup. ~30 filings a quarter. These rows carry the header facts and `filed_by_exchange = false`, and every XML-derived column is NULL. Nothing is inferred from the prose: see the dataset doc for why the checkbox is not parsed. # ONE NOTICE IS TWO ARCHIVE PATHS A `25-NSE` associates the EXCHANGE and the ISSUER, and EDGAR indexes it under both CIK paths - measured over three dissemination days spanning 2024-2026, **all 12 `25-NSE` accessions have exactly two paths, never one and never three**, while both `25` accessions have one. The row is keyed on the accession so an exchange-filed delisting is one event rather than two. See `docs/datasets/edgar_delisting_notices.md` and `docs/availability/edgar_delisting_notices.md`.
How do I avoid look-ahead bias with edgar_delisting_notices?
Filter on edgar_delisting_notices.available_date, the day the publisher made the row public. For this dataset that date is derived as follows - filing_join: available_date is the EDGAR DISSEMINATION day, taken from the bronze object's own day partition, never from the header's FILED AS OF DATE (SEC back-dates that field on 4.88 % of the EDGAR corpus). WHY this family carries no separate event date: a Form 25 IS a publication - the notification to the SEC and the market is the act, and the removal it announces takes effect ten days LATER under Rule 12d2-2(d)(1), so the only other date in play is in the future and cannot be an occurred_on. signature_date, the day the exchange's officer signed the notice, is stored as its own named column and is NOT the conformed event date: it equalled the dissemination day on 7 of 7 sampled notices spanning 2008-2026, so promoting it would assert a distinction that has not been observed. Evidence class B; see docs/availability/edgar_delisting_notices.md. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get edgar_delisting_notices?
As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="edgar_delisting_notices". The column schema is public at https://api.obscura.trade/v1/catalog/edgar_delisting_notices.
Can I filter edgar_delisting_notices by company or symbol?
Yes. edgar_delisting_notices carries issuer_cik, the column the API's symbols filter resolves against.
How often is edgar_delisting_notices updated?
Obscura refreshes edgar_delisting_notices on a every 6 hours schedule - that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.