USPTO Patent Center vs EPO Register Status Codes
USPTO and EPO encode the same prosecution milestones in incompatible vocabularies: the USPTO exposes free-form transaction codes and numeric application-status codes through Patent Center and the Patent Examination Data System, while the EPO Register and INPADOC deliver WIPO ST.27 legal-status event categories. A docketing engine that reasons over both portfolios must collapse these two dialects into one canonical status enum, deterministically, before any deadline logic runs.
This page contrasts the two encodings field by field, gives a representative mapping table from office codes to a shared internal status, and provides a focused Python normalizer that fails closed on any unmapped code. It sits directly beneath USPTO Data Schema Mapping, reuses the canonical-event discipline established there, and complements the field-level serialization differences documented in USPTO PAIR vs Patent Center Data Structures.
Why the two encodings do not line up
The mismatch is structural, not cosmetic. The USPTO models prosecution as a stream of transactions — every mailing, response, and internal action appends a short document code to the file wrapper, and a separate coarse application status summarizes where the case sits. The EPO, by contrast, publishes a procedural status in the European Patent Register and, for downstream consumers, a normalized legal-status event stream through INPADOC that follows the WIPO ST.27 categorization. One system is transaction-granular and US-specific; the other is event-categorical and designed for cross-office exchange.
Three consequences matter for docketing. First, cardinality differs: a single canonical status such as “under examination” corresponds to many USPTO transaction codes but to one ST.27 examination category. Second, the trigger semantics differ: a USPTO MN/=. transaction (mailing of a Notice of Allowance) opens a non-extendable issue-fee window under 35 U.S.C. § 151, whereas the EPO’s equivalent — a communication under Rule 71(3) EPC that grant is intended — opens a four-month response window with entirely different consequences. Third, terminal states are asymmetric: a US case is “abandoned”; a European application is “deemed to be withdrawn.” Treating these as the same string is safe only after both are mapped to one canonical ABANDONED.
Operational Action: Never let raw office status strings reach your deadline engine. Normalize at the ingestion boundary so downstream rule code sees only the canonical enum, and pin the mapping tables to a version so a code you have never seen becomes a reviewable alert rather than a silent default.
USPTO: transaction codes, PEDS status, and Patent Center
Patent Center is the USPTO’s current filing and file-wrapper interface, and the Patent Examination Data System (PEDS) is the bulk, machine-readable channel that exposes the same records as structured JSON and XML. Two fields carry status. The transaction history is a list of dated document codes — CTNF (non-final rejection mailed), CTFR (final rejection mailed), MN/=. (Notice of Allowance mailed), N271 (issue notification), and ABN (abandonment) are representative examples drawn from the file-wrapper vocabulary. Alongside the transactions, PEDS carries a coarse appStatus string and a numeric appStatusCode; for example code 30 is “Docketed New Case — Ready for Examination”, 150 is “Patented Case”, and 161 is “Abandoned — Failure to Respond to an Office Action”.
The transaction stream is authoritative for when a deadline-bearing event occurred, because it carries the mailing date; the numeric status is a convenient summary but lags the transaction and should never be the sole trigger. A docketing feed therefore reads both, prefers the transaction date as the anchor, and uses the numeric code as a corroborating cross-check. Retrieve these through the sanctioned USPTO Open Data Portal rather than scraping the Patent Center UI while the API is healthy.
EPO Register, INPADOC, and WIPO ST.27 categories
The European Patent Register publishes a human-readable procedural status — phrases such as “Examination is in progress”, “Communication under Rule 71(3) EPC” (intention to grant), “The patent has been granted”, and “The application is deemed to be withdrawn”. For automation, the durable representation is the legal-status event stream delivered through INPADOC and the EPO’s Open Patent Services, which follows WIPO Standard ST.27, the recommendation for the exchange of patent legal-status data.
ST.27 assigns every legal-status event to a standardized category — filing, examination, grant, lapse, reinstatement, discontinuation, and so on — plus a more granular event code. The category is the level a cross-office docketing system should key on, because event codes vary by office while the categories are stable and internationally agreed. INPADOC then supplies the effective date and the affected contracting states. Critically, a lapse in one designated state does not lapse the whole grant, so the ST.27 lapse category must be resolved per state before it collapses to a canonical status — a nuance the EPO Register Sync Architecture feed has to preserve.
Operational Action: Load the full ST.27 category table from the WIPO standard, not from a hand-typed subset, and record which INPADOC event code produced each canonical status so a restoration under Rule 135 EPC or re-establishment under Article 122 EPC can be reconstructed downstream.
A canonical status mapping table
The table maps representative office signals to a shared internal status and states the docketing consequence each carries. It is deliberately many-to-one on the USPTO side and category-keyed on the EPO side.
| Canonical status | USPTO Patent Center / PEDS signal | EPO Register / INPADOC (ST.27) | Docketing implication |
|---|---|---|---|
FILED |
appStatusCode 19/20, pre-exam processing |
ST.27 filing category | Start priority and PCT clocks; no response window yet |
UNDER_EXAMINATION |
CTNF / CTFR; appStatusCode 41 |
ST.27 examination; Register “Art. 94(3) communication” | Opens a response window (37 CFR § 1.136 / Rule 132 or Art. 94(3)) |
ALLOWED |
MN/=. Notice of Allowance mailed |
Register “Rule 71(3) intention to grant” | US: non-extendable issue-fee window; EPO: 4-month Rule 71(3) window |
GRANTED |
N271; appStatusCode 150 “Patented Case” |
ST.27 grant; Register “the patent has been granted” | Switch case to the maintenance-fee / annuity track |
ABANDONED |
ABN; appStatusCode 161 |
Register “deemed to be withdrawn” (Art. 94(4)) | Open the revival / further-processing window |
LAPSED |
Maintenance fee unpaid (37 CFR § 1.362) | ST.27 lapse; INPADOC lapse in a contracting state | Start the grace-period / restoration clock, per state |
RESTORED |
Petition to revive granted (37 CFR § 1.137) | ST.27 reinstatement; Rule 135 / Art. 122 relief | Reopen the previously closed deadlines |
The ALLOWED row is the sharpest divergence: the same canonical state carries a non-extendable US issue-fee period but an extendable European response period, so the canonical status is only a routing key — the actual arithmetic still branches on office. Reconcile the cross-office national-phase timing separately in USPTO vs EPO National Phase Entry Differences.
Mapping office codes to a canonical enum
The normalizer keeps two lookup tables — one per office — and a single entry point that fails closed. An unmapped code raises rather than defaulting to a benign status, because a silently swallowed grant or lapse is a missed-deadline vector. Validation at the boundary uses Pydantic so a malformed record never reaches the deadline engine.
from datetime import date
from enum import Enum
from typing import Literal
from pydantic import BaseModel, Field
class CanonicalStatus(str, Enum):
FILED = "FILED"
UNDER_EXAMINATION = "UNDER_EXAMINATION"
ALLOWED = "ALLOWED"
GRANTED = "GRANTED"
ABANDONED = "ABANDONED"
LAPSED = "LAPSED"
RESTORED = "RESTORED"
# USPTO: file-wrapper transaction codes AND numeric PEDS app-status codes
# both collapse to the same canonical status. Source: USPTO Open Data Portal
# (https://developer.uspto.gov/) and PEDS (https://ped.uspto.gov/).
USPTO_MAP: dict[str, CanonicalStatus] = {
"CTNF": CanonicalStatus.UNDER_EXAMINATION, # non-final rejection mailed
"CTFR": CanonicalStatus.UNDER_EXAMINATION, # final rejection mailed
"MN/=.": CanonicalStatus.ALLOWED, # Notice of Allowance mailed
"N271": CanonicalStatus.GRANTED, # issue notification
"ABN": CanonicalStatus.ABANDONED, # abandonment
"30": CanonicalStatus.FILED, # docketed, ready for exam
"41": CanonicalStatus.UNDER_EXAMINATION, # non-final action mailed
"150": CanonicalStatus.GRANTED, # patented case
"161": CanonicalStatus.ABANDONED, # failure to respond
}
# EPO: keyed on the WIPO ST.27 event category as delivered via INPADOC / OPS.
# Load the authoritative category set from WIPO ST.27, Annex I
# (https://www.wipo.int/standards/en/pdf/03-27-01.pdf); this is a subset.
EPO_ST27_MAP: dict[str, CanonicalStatus] = {
"FILING": CanonicalStatus.FILED,
"EXAMINATION": CanonicalStatus.UNDER_EXAMINATION,
"INTENTION_TO_GRANT": CanonicalStatus.ALLOWED, # Rule 71(3) EPC
"GRANT": CanonicalStatus.GRANTED,
"DISCONTINUATION": CanonicalStatus.ABANDONED, # deemed withdrawn / refused
"LAPSE": CanonicalStatus.LAPSED,
"REINSTATEMENT": CanonicalStatus.RESTORED, # Rule 135 / Art. 122
}
_TABLES: dict[str, dict[str, CanonicalStatus]] = {
"USPTO": USPTO_MAP,
"EPO": EPO_ST27_MAP,
}
def to_canonical(office: Literal["USPTO", "EPO"], raw_code: str) -> CanonicalStatus:
"""Map an office status/event code to the canonical enum, failing closed.
A code the pinned table does not recognize raises — an unmapped grant or
lapse must surface for human confirmation, never default silently.
"""
table = _TABLES.get(office)
if table is None:
raise ValueError(f"Unknown office: {office!r}")
canonical = table.get(raw_code.strip())
if canonical is None:
raise ValueError(
f"Unmapped {office} status code {raw_code!r} — verify against source taxonomy"
)
return canonical
class NormalizedStatusEvent(BaseModel):
"""The single shape both offices are reduced to before docketing."""
office: Literal["USPTO", "EPO"]
raw_code: str = Field(min_length=1, max_length=16)
canonical: CanonicalStatus
effective_date: date
jurisdiction: str # ISO office code; ST.27 lapses resolve per contracting state
@classmethod
def from_raw(cls, office: Literal["USPTO", "EPO"], raw_code: str,
effective_date: date, jurisdiction: str) -> "NormalizedStatusEvent":
return cls(
office=office,
raw_code=raw_code,
canonical=to_canonical(office, raw_code),
effective_date=effective_date,
jurisdiction=jurisdiction,
)
# Verify: both dialects reach one status.
# to_canonical("USPTO", "MN/=.") is CanonicalStatus.ALLOWED
# to_canonical("EPO", "INTENTION_TO_GRANT") is CanonicalStatus.ALLOWED
Deadline implications once the status is canonical
Canonicalization routes a case to the right rule set, but the arithmetic still depends on the originating office. An ALLOWED US case starts a non-extendable three-month issue-fee window; an ALLOWED European case starts the four-month period to reply to the Rule 71(3) communication, which is extendable by further processing. An ABANDONED US case can be revived on a petition showing the delay was unintentional under 37 CFR § 1.137; a DISCONTINUATION-derived European case reopens through further processing under Rule 135 EPC or re-establishment under Article 122 EPC, and the contrast between those two European remedies is worked through in EPO Further Processing vs Re-establishment of Rights. Feeding these normalized events into the shared Automated Deadline Calculation & Rule Engines keeps the office-specific branch in one place.
Operational Action: Keep the canonical enum small and status-oriented, and push office-specific arithmetic into the rule engine keyed on (canonical, office). Expanding the enum to encode office nuances re-couples the two dialects you just separated.
Known pitfalls
- Numeric status lag. The PEDS
appStatusCodecan trail the transaction that actually opened the deadline. Anchor on the dated transaction and treat the numeric status as corroboration, not the trigger. - Per-state EPO lapse. An INPADOC lapse event names specific contracting states; collapsing it to a single
LAPSEDfor the whole family drops still-live national rights. Resolve the affected states before you set status. - Unmapped codes. Both offices add and rename codes. A default-to-benign branch converts a new grant or lapse code into silence — the exact failure the USPTO Data Schema Mapping layer refuses. Raise, alert, and route to review instead.
- Register text drift. The EPO Register’s human-readable phrases are localized and can be reworded; key on the ST.27 event delivered by INPADOC, never on a scraped Register string.
Frequently Asked Questions
Is a USPTO numeric application-status code enough to drive docketing on its own?
appStatusCode is a coarse summary that can lag the file-wrapper transaction which actually opened a deadline. Anchor the docket on the dated transaction code (for example CTNF or MN/=.) and use the numeric status only as a corroborating cross-check, because the transaction carries the mailing date the statutory window runs from.
What is WIPO ST.27 and why key EPO status on it rather than the Register text?
Does mapping USPTO and EPO to one canonical status make their deadlines identical?
ALLOWED US case opens a non-extendable issue-fee window, while an ALLOWED European case opens the extendable four-month Rule 71(3) response period. The arithmetic still branches on the originating office; the enum just ensures both portfolios enter the correct rule set.
How should the mapper behave when it meets a status code it has never seen?
Related
- USPTO Data Schema Mapping — the parent normalization layer this status mapping plugs into.
- USPTO PAIR vs Patent Center Data Structures — the field-level serialization differences behind the same records.
- EPO Register Sync Architecture — the feed that supplies ST.27 events and per-state lapse data.
- EPO Further Processing vs Re-establishment of Rights — the two European remedies a
RESTOREDstatus can resolve to. - Automated Deadline Calculation & Rule Engines — the engine that consumes the normalized status events.
↑ Back to USPTO Data Schema Mapping