Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pyinpi

CI License: MIT

Python client for the French INPI « API PI » — the official diffusion API of the Institut national de la propriété industrielle serving the authoritative registries behind data.inpi.fr:

  • marques — French trademarks since 1976, EU trademarks (EUIPO) since 1996, international marks (WIPO) since 1891
  • brevets — French patents since 1902, EP and WO applications, French CCP/SPCs
  • dessins & modèles — French designs since 1910, international designs since 1979

⚠️ This targets the French INPI. Brazil's patent office is also called INPI; this library does not cover it.

Why this library exists

INPI publishes an official API, but integrating it is unusually hostile territory:

  • The documentation is a PDF of raw curl commands (v1.0, 2021) — there is no OpenAPI spec public without an account, and no official SDK in any language.
  • Authentication is a three-step, cookie-based flow: fetch an XSRF token, log in with it, then replay three cookies on every call — one of which must be renamed (refresh_token → session_token) or requests fail.
  • The search DSL uses French boolean operators (ET, OU, SAUF) with bracketed criterion/term couples, and subtle index semantics (Mark_Exp = exact expression vs NGram_Mark = contains).
  • Failure modes are easy to swallow: expired sessions come back as bare 401s and quota exhaustion returns a 429 that intermediate layers routinely turn into silently-empty results.

Every French legal-tech and IP-analytics team re-solves these problems privately. The established open source IP tooling — python-epo-ops-client for the EPO, patent_client for USPTO/EPO — does not cover INPI. pyinpi fills that gap with a typed, tested, documented client.

Install

pip install git+https://github.com/mounimb/pyinpi

(First PyPI release is planned; until then install from git.)

Getting credentials

  1. Create an account on data.inpi.fr.
  2. In Mon espace client → Mes accès APIs / FTP, request Accès APIs PI for the registries you need (marques / brevets / dessins & modèles).
  3. INPI emails you an activation link for a technical account; set its password on api-gateway.inpi.fr.
  4. Use that technical account's email/password with INPIClient — not your data.inpi.fr web login.

Quickstart

from pyinpi import INPIClient, query

with INPIClient("tech-account@example.org", "password") as inpi:
    # Trademarks containing "chidat", FR + EU + WO registries
    results = inpi.marques.search(query.mark("chidat"))

    # French marks in force, filed by a given applicant
    results = inpi.marques.search(
        query.et(query.any_of(["DEPOSANT", "DEPOTIT"], "INPI"), query.in_force()),
        collections=["FR"],
        size=100,
    )

    # Full XML notice, logo, and BOPI PDF of one mark
    notice_xml = inpi.marques.notice("FR4216963")
    logo = inpi.marques.image("FR4216963")
    bopi_pdf = inpi.marques.bopi("FR4221057")

    # Patents: title/abstract keyword search, then one notice
    hits = inpi.brevets.search("[(TIT OU ABFR)=(plasma* ET fusion*)]", collections=["FR", "EP"])
    notice_xml = inpi.brevets.notice("EP3813503")

    # Designs
    hits = inpi.modeles.search("[DesignTitle=fauteuil* roulant*]")

Raw DSL strings and the pyinpi.query builders are interchangeable everywhere.

The search DSL in 30 seconds

Each criterion/term couple is bracketed; operators are French; ? and * are wildcards:

You want DSL
Deposant named INPI [DEPOSANT=INPI]
Match several indexes [(DEPOSANT OU DEPOTIT)=INPI]
Terms combined [TIT=(taille* ET haie*)]
Couples combined [DEPOSANT=INPI] OU [DESI=180080012]
Exact trademark name [Mark_Exp=maison des innovateurs]
Trademark name contains [NGram_Mark=chidat]
In force today [ExpiryDate=20260723:99991231]

Useful marques indexes: ApplicationNumber, Mark_Exp, NGram_Mark, ClassNumber (Nice classes 1–45), ApplicantIdentifier (SIREN, FR only), DEPOSANT, DEPOTIT, Representative_LastName, ApplicationDate, ExpiryDate. Useful brevets indexes: TIT, ABFR, DEPN, PUBN, IPCR, CPC, DENM, TINM, INVNM, PUBD, DEPD, DLVD, PRD. See the official PDF for the full index tables.

Pagination caps (enforced client-side)

Registry collections size max position max
marques FR, EU, WO 200 500
brevets FR, EP, WO, CCP 500 500
modeles FR, WO 100 200

Note the consequence: you cannot page arbitrarily deep into a result set — narrow your query (dates, classes, collections) rather than crawling.

Errors you should care about

from pyinpi import AuthenticationError, QuotaExhaustedError

try:
    results = inpi.marques.search(query.mark("chidat"))
except QuotaExhaustedError:
    ...  # HTTP 429: account quota used up — back off; do NOT retry in a loop
except AuthenticationError:
    ...  # wrong credentials (technical account!) — the client already retried once

QuotaExhaustedError exists because the single most common INPI integration bug is a swallowed 429 that surfaces as "French trademarks silently disappeared from results". Expired sessions (401) are re-authenticated transparently, once per call.

If you proxy requests for many end users, pass forwarded_for= — INPI uses the x-forwarded-for header for per-user quota accounting.

Scope and roadmap

v0.1 returns raw JSON (search, lists) and XML/bytes (notices, images, PDFs) — the response envelopes are undocumented, so this version does not guess at typed models.

Planned: typed response models · pagination iterator · async client · CLI (pyinpi marques search ...) · original patent documents endpoint · PyPI release.

Contributions welcome — see CONTRIBUTING.md.

Related projects

Data licence

The data served by the API PI is subject to INPI's own reuse licences (see data.inpi.fr). This library is MIT; the data is not.

About

Python client for the French INPI API PI - trademarks, patents & designs (data.inpi.fr)

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages