API reference
Watchlists
Written and maintained by The ProspectAPIs team
A watchlist is a saved set of funding filters plus an https webhook. Each new funding round that matches is POSTed to your webhook, signed, so you hear about a raise without polling, and you pay only for the records a watchlist delivers.
$0.02
per delivered record, free records first
15 min
between delivery passes
20
active watchlists per account
Routes
All take your API key. Managing watchlists is free; only a delivered record is charged.
| Method | Path | What it does |
|---|---|---|
| POST | /v1/watchlists | Create. The signing secret is in this response and nowhere else. |
| GET | /v1/watchlists | List your watchlists, without their secrets. |
| GET | /v1/watchlists/:id | One watchlist. |
| DELETE | /v1/watchlists/:id | Delete it; its delivery history goes with it. |
| POST | /v1/watchlists/:id/test | Send a signed sample to the webhook now. 5 a minute per account. |
| GET | /v1/watchlists/:id/deliveries | The last 50 deliveries and their outcome. |
Create
name is 1 to 100 characters. filters needs at least one of round, min_amount_usd, max_amount_usd, company, domain, investor and country, validated exactly as GET /v1/funding validates them; date windows and paging do not apply. webhook_url must be https on a public host, on port 443 or a port from 1024 to 65535. Unknown fields are a 400, and a 21st active watchlist is a 409.
curl -X POST https://api.prospectapis.com/v1/watchlists \
-H "Authorization: Bearer $PROSPECTAPIS_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Series A robotics",
"filters": {"round": "series_a", "company": "robot", "min_amount_usd": 5000000},
"webhook_url": "https://hooks.example.com/funding"}'{
"id": "a41f0c2e-...",
"name": "Series A robotics",
"filters": { "round": "series_a", "company": "robot", "min_amount_usd": "5000000" },
"webhook_url": "https://hooks.example.com/funding",
"active": true,
"paused_reason": null,
"created_at": "2026-10-02T09:00:00Z",
"secret": "whsec_..."
}Store secret now: it is never shown again. A watchlist sees rounds that arrive after it is created, not the back catalogue; use GET /v1/funding for history.
Test
POST /v1/watchlists/:id/test sends a signed sample event, marked "test": true, to your webhook straight away so you can build the receiver. It is free and limited to 5 a minute per account.
{ "delivered": true, "http_status": 200, "error": null }What your webhook receives
One POST per matching round, with a JSON body. data is the funding record, with the same fields as GET /v1/funding.
{
"type": "funding_event.matched",
"delivery_id": "5e1c9b70-...",
"watchlist_id": "a41f0c2e-...",
"delivered_at": "2026-10-02T09:15:01Z",
"data": {
"id": "2b9a6c1e-...",
"company_name": "Acme Robotics",
"company_domain": "acme.com",
"round_stage": "series_a",
"amount_usd": 18000000,
"announced_at": "2026-10-02",
"lead_investors": ["Example Ventures"],
"source_url": "https://..."
}
}| Header | Meaning |
|---|---|
| Prospect-Signature | t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 with your secret over the string <t>.<raw body>. |
| Prospect-Delivery-Id | The delivery id, the same on every retry of one delivery. Use it to drop duplicates. Not sent on tests. |
| User-Agent | ProspectAPIs-Webhooks/1.0 |
Verify the signature
Compute the HMAC over the raw bytes you received, before parsing them, and compare in constant time. Reject an old t so a captured request cannot be replayed later.
import crypto from "node:crypto";
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected), b = Buffer.from(String(parts.v1 || ""));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Delivery, retries and billing
A delivery pass runs every 15 minutes and sends up to 50 new matches per watchlist. Each send waits up to 10 seconds and does not follow redirects. A 2xx answer marks the delivery delivered and charges one record ($0.02, free records first). Anything else is refunded and retried on a later pass, up to three attempts in all. If the account cannot pay, the delivery waits as no_credit for up to a day and goes out once there is credit. A round that is edited is pushed once.
curl https://api.prospectapis.com/v1/watchlists/$WATCHLIST_ID/deliveries \
-H "Authorization: Bearer $PROSPECTAPIS_KEY"| status | Meaning |
|---|---|
| pending | Matched and waiting for the next delivery pass. |
| delivered | Your webhook answered 2xx. This is the only state that is charged. |
| retry | The send failed; it was refunded and goes out again on a later pass. |
| failed | Three attempts failed, a day passed without credit, or the round no longer matches. Not charged. |
| no_credit | The account could not pay one record. Waits up to a day, then goes out once it can. |
| sending | In flight. A send stuck here from an interrupted pass is refunded and retried. |
Paused watchlists
A watchlist stops with active: false and a paused_reason when the API key that created it is revoked, when its filters are no longer valid, or after 10 failed sends in a row. A paused watchlist is not resumed: delete it and create a new one, with a working key and webhook. The new one picks up rounds that arrive after it is created.
From an agent
The MCP server exposes these routes as watchlist_create, watchlist_list, watchlist_get, watchlist_deliveries, watchlist_test and watchlist_delete, with the same key and credits.
Next steps
Create a free account to get a key. The quickstart covers authentication and errors, and pricing lists what each delivered record costs. Our guide to sales prospect research lists what else to look up on an account once its round arrives.