API
Newly funded startups and their open roles, as JSON, the day we find them. Pull them into your CRM, a spreadsheet, a script, or an AI tool.
- Filter companies by round, funding date, location, and whether they are hiring; roles by location, remote, department, and seniority.
- Sync mode returns only what changed since your last pull, so a nightly job stays small.
- 5,000 rows a day, 120 calls a minute, full history.
- MCP server for Claude, ChatGPT, Cursor, and other AI tools on the same key (setup).
Includes everything in Fresh Membership. Cancel anytime in Settings. Already a member? Upgrade in Settings, Billing. Use cases and a sync example are on the developers page.
Try it now, no key
5 real companies from our free tier (first seen at least 7 days ago), in the same shape the API returns. Limited to 20 calls an hour.
curl https://bloomwatch.co/api/v1/sampleExample response
GET /companies?fundedWithinDays=7&hasJobs=true, one row shown, example values:
{
"data": [
{
"id": "cmexample01",
"name": "Example Robotics",
"domain": "example.com",
"fundingRound": "Series A",
"roundAmount": 18000000,
"roundCurrency": "USD",
"roundCloseDate": "2026-10-21T00:00:00.000Z",
"locationHq": "Austin, TX",
"investorNames": ["Example Ventures"],
"industry": "Robotics",
"employeeCountEstimate": 35,
"careersUrl": "https://example.com/careers",
"openJobCount": 6,
"firstSeenAt": "2026-10-22T06:00:12.000Z"
}
],
"total": 214,
"nextOffset": 50
}Getting started
Read-only JSON API for newly funded companies and their open roles. Included with the API plan. Create a key in Settings, then send it on every call.
OpenAPI spec and types
The full schema is at https://bloomwatch.co/api/v1/openapi.json (OpenAPI 3.1, no key needed). Import it into Postman or Insomnia, or generate TypeScript types:
npx openapi-typescript https://bloomwatch.co/api/v1/openapi.json -o bloomwatch.d.tsCommand-line client
The open-source BloomWatch CLI prints companies and jobs as terminal tables. One file, no dependencies, Node 20.12 or newer:
export BLOOMWATCH_KEY=bw_live_YOUR_KEY
npx bloomwatch companies --days 7 --jobsAuthentication
curl -H "Authorization: Bearer bw_live_YOUR_KEY" https://bloomwatch.co/api/v1/status- Missing, unknown, or revoked key: 401.
- Plan without API access (free, lapsed, or Fresh Membership, which includes MCP only): 402 with an
upgradeUrl. Renew and the same key works again. - Up to 2 active keys per account. Revoke a key in Settings at any time.
Errors
Every error is JSON with a message and a stable code: {"error":"Invalid API key.","code":"invalid_key"}. Branch on code, not the message.
- 401:
missing_key,invalid_key,revoked_key - 402:
plan_required, withupgradeUrl - 400:
bad_param. 404:not_found. 500:internal - 429:
rate_limited(minute limit) ordaily_cap(rows per day)
Limits
- 120 calls per minute per account. Over it: 429 with
Retry-After. - 5,000 rows per day per account, reset at 00:00 UTC. Over it: 429 naming the reset time.
- Up to 200 rows per call (
limit, default 50). - Every response carries
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(Unix seconds),X-RateLimit-Rows-Limit, andX-RateLimit-Rows-Remaining.
GET /companies
Companies, newest funding first.
curl -H "Authorization: Bearer $BLOOMWATCH_KEY" \
"https://bloomwatch.co/api/v1/companies?fundedWithinDays=7&round=Series%20A&hasJobs=true&limit=50"limit,offset: paging. Responses includetotalandnextOffset(null on the last page).fundedWithinDays: round closed in the last N days.round: exact round name, any case (Seed, Series A, Series B).hasJobs: true or false.location(orcountry): city, state, or country of the HQ. "NYC", "New York", and "New York, NY" match the same companies; "Germany" or "DE" the country.
Fields: id, name, domain, fundingRound, fundingRoundEstimate (round guessed from the round size, only when fundingRound is null), roundAmount, roundCurrency, roundCloseDate, locationHq, hqCity, hqRegion, hqCountry (ISO code), investorNames, industry, industries, oneLineSummary, employeeCountEstimate, techStack, remotePolicy, careersUrl, openJobCount, firstSeenAt, updatedAt.
GET /jobs
Open roles, newest first, each with the company's funding inlined.
curl -H "Authorization: Bearer $BLOOMWATCH_KEY" \
"https://bloomwatch.co/api/v1/jobs?postedWithinDays=3&round=Seed&location=NYC&seniority=Senior&limit=100"limit,offset: paging, same as above.postedWithinDays: posted in the last N days (first seen, when the posting has no date).round: the company's round.companyId: roles at one company.remote: true for remote roles only, false for on-site or hybrid only.location: city, state, or country. "NYC", "New York", and "New York, NY" return the same roles; "California" the state; "Germany" or "DE" the country.department: text match on the team, any case (Engineering, Sales).seniority: Intern, Junior, Mid, Senior, Lead, Staff, Principal, or Director.employmentType: full_time, part_time, contract, temporary, or internship.
Fields: id, title, url (the company's own posting), location (as the job board writes it), city, region, countryCode (ISO), isRemote, remoteScope ("Remote, US"), department, employmentType, seniority, salary (min, max, currency, period; null when the posting states no pay), firstSeenAt, postedAt, closedAt, updatedAt, and company (id, name, domain, fundingRound, fundingRoundEstimate, roundAmount, roundCurrency, roundCloseDate, locationHq, hqCity, hqRegion, hqCountry). closedAt is null on every role this list returns.
GET /companies/{id} and /jobs/{id}
One record by its id, in data. Counts as 1 row. Unknown id: 404.
curl -H "Authorization: Bearer $BLOOMWATCH_KEY" https://bloomwatch.co/api/v1/companies/cmabc123
{"data":{"id":"cmabc123","name":"Acme",...,"openJobCount":4}}- A job id keeps resolving after the role closes or leaves the 45-day window, with
closedAtset when the role is gone.
Sync: updatedSince and cursor
To keep a copy in step, pull once, then only what changed. Pass updatedSince (ISO 8601) on the first call, then the nextCursor from each response as cursor. Works on /companies and /jobs, with the same filters.
curl -H "Authorization: Bearer $BLOOMWATCH_KEY" "https://bloomwatch.co/api/v1/jobs?updatedSince=2026-10-01T00:00:00Z&limit=200"
{"data":[...],"total":4210,"limit":200,"nextCursor":"eyJ1Ijoi...","hasMore":true}
curl -H "Authorization: Bearer $BLOOMWATCH_KEY" "https://bloomwatch.co/api/v1/jobs?cursor=eyJ1Ijoi...&limit=200"- Rows come oldest change first, by
updatedAt. A row added or changed during your walk shows up later in it, never skipped. hasMorefalse means you are caught up. Keep the lastnextCursorand call with it again later for new changes.- In sync mode
/jobsalso returns closed and older roles, withclosedAtset, so you can remove them. totalis the rows left from your cursor.offsetcannot be combined with sync.updatedAtmoves on any change to the record, so some synced rows have no visible field change.
GET /status
Freshness and coverage. Counts as 0 rows.
curl -H "Authorization: Bearer $BLOOMWATCH_KEY" https://bloomwatch.co/api/v1/status
{"lastIngestAt":"2026-10-25T06:00:12.000Z","companyCount":1234,"jobCount":5678,"sourceCount":12}Field notes
roundAmountis a number in whole currency units:35000000withroundCurrencyUSD is $35M.roundCurrencyis an ISO 4217 code: USD, EUR, GBP, CAD, AUD, CHF, SEK, INR, JPY, SGD, ILS. There is no currency conversion.firstSeenAtis when BloomWatch first saw the company or role, not when it was founded, funded, or posted. UseroundCloseDateandpostedAtfor those, when known.domainandcareersUrlare null when the website could not be confirmed.- An open role was first seen in the last 45 days and is still on the company's job board.
- Dates are ISO 8601 in UTC. Missing values are null.
CORS
GET is allowed from any origin, so the API works from a browser. Keep keys out of public pages: anyone with your key uses your limits.
Terms
No resale or redistribution of the data, and no building a competing dataset. Keys can be revoked on abuse. Need higher limits? Email bloomwatchsupport@zeninfinity.com.