---
name: cisco-psirt-openvuln-api-ingestion
description: "How to get Cisco PSIRT openVuln API data into a pandas DataFrame and Parquet: access, the request, the format, limits, quirks and terms."
---

# Load recent Cisco advisories into pandas and Parquet

Source entry: https://signal-lab-jet.vercel.app/datasets/cisco-psirt-openvuln-api
Provider: https://developer.cisco.com/docs/psirt/
Checked against the provider's documentation: 2026-11-01

## Access
- Create a no-charge Cisco.com account and register a service application for the Cisco PSIRT openVuln API.
- Store the application credentials in CISCO_CLIENT_ID and CISCO_CLIENT_SECRET; exchange them for a one-hour OAuth bearer token.

## Request
```bash
curl -H "Authorization: Bearer $CISCO_OPENVULN_TOKEN" -H 'Accept: application/json' 'https://apix.cisco.com/security/advisories/v2/latest/10'
```

## Format
JSON with an advisories array; records can include advisoryId, advisoryTitle, bugIDs, cves, cvssBaseScore, cwe, productNames, firstPublished, lastUpdated, status, version, severity, summary and CSAF or publication URLs.

## Load into pandas and Parquet
Needs Python 3 with requests, pandas and pyarrow.
```python
"""Latest Cisco PSIRT advisories -> pandas -> Parquet. Needs free app credentials."""
import json
import os
import requests
import pandas as pd

token_response = requests.post(
    "https://id.cisco.com/oauth2/default/v1/token",
    data={"client_id": os.environ["CISCO_CLIENT_ID"],
          "client_secret": os.environ["CISCO_CLIENT_SECRET"],
          "grant_type": "client_credentials"},
    timeout=60,
)
token_response.raise_for_status()
token = token_response.json()["access_token"]
url = "https://apix.cisco.com/security/advisories/v2/latest/10"
r = requests.get(url, headers={"Authorization": f"Bearer {token}",
                               "Accept": "application/json"}, timeout=60)
r.raise_for_status()
payload = r.json()
df = pd.json_normalize(payload.get("advisories", []), sep=".")
for column in df.columns:
    if df[column].map(lambda value: isinstance(value, (list, dict))).any():
        df[column] = df[column].map(lambda value: json.dumps(value) if isinstance(value, (list, dict)) else value)
for column in ("firstPublished", "lastUpdated"):
    if column in df:
        df[column] = pd.to_datetime(df[column], errors="coerce", utc=True)
df.to_parquet("cisco_psirt_latest.parquet", index=False)
print(len(df), "Cisco advisories", df["lastUpdated"].max().isoformat())
```
Not run: it needs a free API key.

## Limits
- Rate limit: 5 calls per second, 30 calls per minute and 5,000 calls per day per application.
- Broad result sets are paginated with pageIndex and pageSize.
- OAuth access tokens in the provider example expire after 3,600 seconds.

## Quirks
- Advisories can change after first publication; keep firstPublished, lastUpdated, status and version.
- Arrays such as cves, bugIDs, cwe and productNames are JSON-encoded before Parquet export.
- A 429 response indicates quota exhaustion; respect Retry-After when the header is present.

## Terms and attribution
- API clients must be used for deployments with Cisco products or services and may not substantially replicate the underlying Cisco service.
- Credentials must remain confidential, may not be embedded in open-source projects and must be encrypted in transit.
- Terms page: https://developer.cisco.com/site/license/cisco-api-license/

## Sources
- https://developer.cisco.com/docs/psirt/: "The Cisco PSIRT openVuln API can retrieve the Cisco advisory information in either .json or .xml format."
- https://developer.cisco.com/docs/psirt/authentication/: "The Cisco PSIRT openVuln API applications require an API "access token" in order to authenticate each individual API request."
- https://developer.cisco.com/docs/psirt/browsing-sorting-filterting-and-rate-limits/: "5000 calls per day"
- https://developer.cisco.com/site/license/terms-and-conditions/: "There is no charge for Cisco DevNet registration."

## Help improve this skill
Missing a source, or see something to improve? Call the MCP tool suggest_source or feedback (or POST /api/suggest or /api/feedback). Reviewed ideas: https://signal-lab-jet.vercel.app/agent-suggestions

Information for educational purposes only. Free tiers, limits and licenses belong to the providers and may change; check the provider's own terms before using the data.
