Skip to content
ProspectAPIs

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.

MethodPathWhat it does
POST/v1/watchlistsCreate. The signing secret is in this response and nowhere else.
GET/v1/watchlistsList your watchlists, without their secrets.
GET/v1/watchlists/:idOne watchlist.
DELETE/v1/watchlists/:idDelete it; its delivery history goes with it.
POST/v1/watchlists/:id/testSend a signed sample to the webhook now. 5 a minute per account.
GET/v1/watchlists/:id/deliveriesThe 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.

bash
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"}'
201 Created
{
  "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.

200 OK
{ "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.

POST to your webhook_url
{
  "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://..."
  }
}
HeaderMeaning
Prospect-Signaturet=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 with your secret over the string <t>.<raw body>.
Prospect-Delivery-IdThe delivery id, the same on every retry of one delivery. Use it to drop duplicates. Not sent on tests.
User-AgentProspectAPIs-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.

Node.js
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.

bash
curl https://api.prospectapis.com/v1/watchlists/$WATCHLIST_ID/deliveries \
  -H "Authorization: Bearer $PROSPECTAPIS_KEY"
statusMeaning
pendingMatched and waiting for the next delivery pass.
deliveredYour webhook answered 2xx. This is the only state that is charged.
retryThe send failed; it was refunded and goes out again on a later pass.
failedThree attempts failed, a day passed without credit, or the round no longer matches. Not charged.
no_creditThe account could not pay one record. Waits up to a day, then goes out once it can.
sendingIn 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.