Metadata-Version: 2.4
Name: pangolinfo-ip
Version: 0.2.0
Summary: Pangolinfo IP Compliance API - WIPO design patent search and PACER US patent litigation lookup.
Project-URL: Homepage, https://docs.pangolinfo.com
Project-URL: Documentation, https://docs.pangolinfo.com
Project-URL: Repository, https://github.com/Pangolin-spg/pangolinfo-ip
Project-URL: Free API Key, https://tool.pangolinfo.com
Author-email: "PANGOLIN INFO TECH PTE. LTD." <support@pangolinfo.com>
License-Expression: MIT
License-File: LICENSE
Keywords: api,ip-compliance,litigation,pacer,pangolinfo,patent,sdk,wipo
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Description-Content-Type: text/markdown

# pangolinfo-ip

Pangolinfo IP Compliance API — WIPO design patent search and PACER US patent litigation lookup.

> Built and maintained by [PANGOLIN INFO TECH PTE. LTD.](https://www.pangolinfo.com)

## Installation

```bash
pip install pangolinfo-ip
```

## Quick start

```python
from pangolinfo_ip import IPClient

client = IPClient(token="your_bearer_token")

# WIPO design patent search
result = client.wipo_search(irn="DM123456", ds="US", source="USID")
print(result["total"], len(result["hits"]))

# PACER US patent litigation lookup
result = client.pacer_search(patent_number="D1234567")
print(result["total"], len(result["hits"]))
```

## Authentication

All requests require a Bearer token. Get a free API key at
[tool.pangolinfo.com](https://tool.pangolinfo.com).

```python
client = IPClient(token="your_bearer_token")
```

## Methods

### `client.wipo_search(irn, ds, source, **kwargs)`

Search the WIPO design patent database.

**Required parameters:**

| Parameter | Type | Description |
|---|---|---|
| `irn` | `str` | International registration number |
| `ds` | `str` | Specify country |
| `source` | `str` | Data source — `USID` / `CNID` / `JPID` / `EMID` / `HAGUE` etc. |

**Optional keyword arguments:**

| Parameter | Type | Description |
|---|---|---|
| `ed` | `str` | Expiration date |
| `from_` | `int` | Page start position |
| `hol` | `str` | Right holder |
| `id` | `str` | Unique identifier |
| `id_search` | `str` | ID variant (sent as `idSearch`) |
| `lcs` | `str` | Design classification (Locarno, e.g. `"30-01"`) |
| `prod` | `str` | Product description keyword |
| `rd` | `str` | Registration date |
| `num` | `int` | Items per page |
| `status` | `str` | Legal status — `ACT` / `PEND` / `DEL` |
| `enable_litigation` | `bool` | Smart Risk Control Mode. When `True`, chains WIPO results to PACER US litigation lookup. Default `False`. |

**Response** (returned directly, unwrapped):

```json
{
  "total": 42,
  "hits": [
    {
      "ID": "...",
      "IRN": "...",
      "SOURCE": "USID",
      "STATUS": "ACT",
      "RD": "...",
      "HOL": "...",
      "PROD": "...",
      "LCS": "30-01",
      "DS": "US",
      "DC": "...",
      "DOC": "...",
      "IMG": "...",
      "IMG_DATA": "...",
      "DETAIL_URL": "...",
      "DETAIL_DATA": {}
    }
  ]
}
```

When `enable_litigation=True`, each hit additionally contains
`litigationStatus`, `caseTotal`, and `cases[]`.

**Example — with litigation risk control:**

```python
result = client.wipo_search(
    irn="DM123456",
    ds="US",
    source="USID",
    enable_litigation=True,
)
for hit in result["hits"]:
    print(hit["IRN"], hit.get("litigationStatus"), hit.get("caseTotal"))
```

### `client.pacer_search(...)`

Search PACER US patent litigation records.

At least one of `patent_number`, `company_name`, or `case_number` is required.

**Parameters:**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `patent_number` | `str` | one of three | Patent number (exact match) |
| `company_name` | `str` | one of three | Plaintiff/Defendant company name (prefix match) |
| `case_number` | `str` | one of three | Court case number, e.g. `"3:90-cv-00003"` |
| `from_` | `int` | optional | Case pagination offset (default `0`) |
| `size` | `int` | optional | Cases per page (default `10`) |
| `entry_size` | `int` | optional | Timeline records per case (default `50`) |

**Response** (`data` field is returned):

```json
{
  "total": 3,
  "hits": [
    {
      "docketId": "...",
      "docketNumber": "3:90-cv-00003",
      "caseId": "...",
      "caseName": "Acme v. Beta",
      "court": "N.D. Cal.",
      "courtId": "...",
      "assignedTo": "...",
      "suitNature": "...",
      "jurisdiction": "...",
      "status": "...",
      "dateFiled": "...",
      "dateTerminated": "...",
      "parties": [],
      "patentNumbers": ["D1234567"],
      "entryTotal": 12,
      "entries": []
    }
  ]
}
```

**Example:**

```python
# By patent number
result = client.pacer_search(patent_number="D1234567")

# By company name with pagination
result = client.pacer_search(
    company_name="Acme",
    from_=0,
    size=20,
    entry_size=100,
)

# By case number
result = client.pacer_search(case_number="3:90-cv-00003")
```

## Parameter name conversion

Python snake_case parameters are converted to the API's expected names
automatically:

| Python | API |
|---|---|
| `patent_number` | `patentNumber` |
| `company_name` | `companyName` |
| `case_number` | `caseNumber` |
| `from_` | `from` |
| `entry_size` | `entrySize` |
| `enable_litigation` | `enable_litigation` (unchanged) |

## Error handling

```python
from pangolinfo_ip import IPClient
from pangolinfo_ip.exceptions import AuthenticationError, APIError, TimeoutError

try:
    with IPClient(token="...") as client:
        result = client.wipo_search(irn="DM123456", ds="US", source="USID")
except AuthenticationError:
    print("Invalid token")
except APIError as e:
    print(f"API error (code={e.code}): {e}")
except TimeoutError:
    print("Request timed out")
```

## Context manager

`IPClient` supports the context manager protocol, ensuring the underlying HTTP
connection is closed:

```python
with IPClient(token="...") as client:
    result = client.pacer_search(patent_number="D1234567")
```

## Links

- **Documentation:** [docs.pangolinfo.com](https://docs.pangolinfo.com)
- **Get a free API key:** [tool.pangolinfo.com](https://tool.pangolinfo.com)
- **Source code:** [github.com/Pangolin-spg/pangolinfo-ip](https://github.com/Pangolin-spg/pangolinfo-ip)

## License

MIT — © PANGOLIN INFO TECH PTE. LTD.
