API Reference · Your Data

Your Alert Feed

Watchlist alerts that fired for your organisation, newest first: a new CVE matched something you watch, or an existing match crossed a notification threshold. Each alert names what matched (vendor / product / version), why it matched (match_reason), and why you were notified (notification_reason).

This is a feed, and it is designed to be polled: pass since with the created_at of the newest alert you have processed, and you get only what fired after it — usually an empty page, for one credit.

GET
/v1/my/alerts

Cost: 1 credit per successful call · Scope: api:org

Query parameters

unseen_onlybooleanoptional

true to return only alerts not yet marked seen in the dashboard.

sincestring (timestamp)optional

Only alerts created strictly after this RFC 3339 timestamp (e.g. 2026-08-18T00:00:00Z). The polling parameter.

limitintegeroptional

Page size, 1–200. Default 50. Out-of-range is a 400, not a silent clamp.

cursorstringoptional

Opaque pagination cursor from a previous page's next_cursor. Replay the same filters with it.

Request

curl "https://api.precursorintelligence.com/functions/v1/my/alerts?since=2026-08-18T00:00:00Z" \
  -H "Authorization: Bearer $PRECURSOR_API_KEY"

Response

200 OK
{
  "data": {
    "count": 1,
    "items": [
      {
        "id": "d0187a3c-2b1f-4e2a-8f3d-6a51b9e0c774",
        "cve_id": "CVE-2026-31017",
        "vulnerability_title": "Nginx HTTP/3 request smuggling",
        "severity": "HIGH",
        "cvss_score": 8.1,
        "epss_score": 0.42876,
        "vendor": "f5",
        "product": "nginx",
        "version": null,
        "match_reason": "Watched product: f5/nginx",
        "notification_reason": "new_cve",
        "published_date": "2026-08-18",
        "seen": false,
        "created_at": "2026-08-18T06:15:09+00:00"
      }
    ],
    "next_cursor": null,
    "has_more": false,
    "generated_at": "2026-08-19T09:30:00+00:00"
  },
  "meta": {
    "request_id": "8b16efb8-9a6c-4ace-b817-11cbee626d08",
    "api_version": "1.3.0",
    "credits": { "charged": 1, "remaining": 9998 }
  }
}

Response fields

data.items[].match_reasonstringoptional

What in your watchlist this CVE matched.

data.items[].notification_reasonstringoptional

Why the alert fired (e.g. a new CVE appeared for a watched product, or a tracked score moved).

data.items[].seenbooleanoptional

Whether the alert has been marked seen in the dashboard. The API is read-only — it cannot mark alerts seen.

data.items[].created_atstringoptional

When the alert fired — feed the newest value back as since on your next poll.

data.next_cursorstring | nulloptional

For walking history beyond one page. Follow until null, replaying the same filters. Opaque — do not parse it.

The intended polling loop

  1. First call: GET /my/alerts?limit=50, remember the newest created_at.
  2. Every poll after: GET /my/alerts?since=<that timestamp> — one credit, usually zero rows.
  3. Page with cursor only if a single poll returns has_more: true.

Errors

StatuserrorWhen
400invalid_since, invalid_limit, invalid_cursorA parameter failed validation. Free — rejected before billing.
401invalid_authorizationMissing or malformed Authorization header.
401unauthorizedInvalid/revoked key, IP not allowlisted, or the key lacks the api:org scope.
402insufficient_creditsOrganisation credit balance is below 1.
405method_not_allowedOnly GET and OPTIONS are accepted.
500internalUnexpected server error (credit auto-refunded).

See Errors for the full error reference.