{"openapi":"3.1.0","info":{"title":"Prova Verified Funding API","version":"1.1.0","description":"\n## The answer\nSend a company's website (`domain`), `name` or `linkedinSlug` to `POST /api/v1/funding-stages`. The answer has one of\nthree statuses:\n\n| Status | HTTP | Meaning |\n| --- | --- | --- |\n| `found` | `200` | `rounds` lists the company's funding rounds, newest first; `latest_round` is the newest one |\n| `not_found` | `200` | No funding found (`message` says why in words; a name that fits several companies lists `candidates`) |\n| `pending` | `202` | Still looking: send the same request again in a few seconds |\n\nEach round is `{stage, amount, currency, date, investors, source}`. `source` is `verified` (checked against the\nannouncement), `confirmed` (a dated news article states the same round), `database` (reported by a funding\ndatabase and not checked yet; its amounts can be US dollars as that database converted them) or `wikidata` (a stock-exchange listing\nfrom Wikidata). A company that went public has `company.public` (`{exchange, ticker}`) and its IPO is a round with\nstage `ipo`, which is its `latest_round`; `company.public` is null for a private company or one no longer listed.\n`total_raised` is the company's total funding to date when Prova has one (`{amount, currency, basis, as_of}`: `basis` is\n`stated_total`, a total an article states, or `sum_of_checked_rounds`, its checked rounds added up; `as_of` is the\nday it holds for), else null.\nErrors are `{\"error\": \"...\"}` with a 4xx or 5xx status.\n\n**Pricing.** A `found` answer is billed. A `not_found` answer saying \"No funding found for this company.\" is a\nno-funding answer: on hit-rate pricing it costs by that day's hit rate (found answers ÷ found and no-funding answers),\nless as the hit rate rises; otherwise it is free. `pending`, the other `not_found` answers (could not check just now,\nseveral companies have the name, send the website), an unchanged `304`, an invalid request and errors are free.\nDays are San Francisco days; today's no-funding answers are priced at today's hit rate so far, and the day is final at\nmidnight. In a bulk request each company counts as one lookup. `GET /api/v1/usage` shows your prices, the cost so\nfar and your balance.\n\n**Monthly spending limit.** `PUT /api/v1/usage/limit` with `{\"monthly\": 50}` (US dollars) sets one, and\n`{\"monthly\": null}` removes it; the dashboard does the same. There is no limit unless you set one. Once this month's\nlookups (San Francisco time) cost the limit or more, lookups get `402` and are not billed, until the 1st of the next month or\nuntil you raise or remove the limit. Lookups already running when the limit is reached still answer, free: a month\nnever costs more than its limit.\n\n**Credit.** On prepaid billing a lookup needs credit: while your balance, with payments on their way, is below the\nprice of a found answer, lookups get `402` with `balance` and are not billed. Top up on your dashboard and lookups\nstart again within 15 seconds. Lookups already running when the balance runs out are still billed, so it can end a few\ncents below zero. `GET /api/v1/usage` shows `credit`: from when lookups need it and whether they are paused now.\n\n`view: \"full\"` returns the same answer with each round's sources (type, link, date, the exact quote) and notes in\nwords. The sections below describe the earlier answers, which `view: \"raw\"` (the evidence answer as stored) and\n`view: \"simple\"` (the short answer) still return unchanged.\n\n## The evidence answer\nProva returns funding data it can prove. **Every canonical non-null value is backed by supporting evidence from a source\ndocument** listed in `evidence`, and unproven canonical fields come back **null with a reason**. Clearly labeled reported candidates and non-exact amounts preserve useful statements without presenting them as verified exact values. A value is published only\nwith one primary source (the company, a filing, a participating investor's own announcement) or two independent outlets; reprints and\nrewrites of one release count as one origin. An empty list never means a company raised nothing.\n\n## Authentication\nSend `Authorization: Bearer <key>`. Keys are issued per customer (tenant); the key itself is never stored, only its\nSHA-256. A revoked key stops working within 60 seconds.\n\n## Rate limits\nKeys have no per-minute limit unless one is set. A key with a limit has a token bucket holding that limit, refilling\ncontinuously, so you can burst up to the full minute at once. Its responses carry `X-RateLimit-Limit` and\n`X-RateLimit-Remaining`; over the limit you get `429` with `Retry-After` (seconds). A bulk request costs one token\nper item.\n\n## Answers, nulls and evidence\n`POST /api/v1/funding-stages` answers from stored, verified records only. It never guesses:\n\n| Situation | Response |\n| --- | --- |\n| Fresh stored facts without completed research for the requested scope | `200` with facts, coverage gaps and an enrichment `job_id` |\n| Completed research that found rounds, fresh enough | `200` with the answer and no duplicate search (under `auto`, new source material still starts research) |\n| Stale answer, `allow_stale` true (default) | `200` with saved facts and refresh state/job when eligible |\n| A name that fits several companies | `200` with `status: \"ambiguous\"` and candidates |\n| Completed scoped research found nothing within its 24-hour retry window | `200 unknown`; force or new material can make it eligible earlier |\n| Completed research found nothing and its retry window (`next_retry_at`) has passed, `refresh: \"auto\"` | New research even inside `max_age_seconds`, with a `job_id` (`202 pending` when nothing is stored) |\n| No usable answer, or `require_completed_research` needs ongoing work | `202 pending` with a job ID when work is queued |\n| `refresh: \"never\"` without an acceptable stored answer | `200 unknown` with an explicit reason, no new job. A completed search that found nothing reads `not_found` inside `max_age_seconds` or its retry window, and `stale` once both have passed |\n| Partial/failed research in backoff | Saved facts, or `200 unknown` with `research_deferred` (`research_incomplete` under `never`); no false completed negative. Once its `next_retry_at` passes, `auto` researches again |\n| New research exceeds the tenant's daily quota | Saved facts with `research.status: \"quota_exceeded\"`, or `429` without an acceptable answer |\n| Missing, extra or invalid input | `422` |\n\nEvery null field in a round has its reason in `null_reasons`:\n\n| Reason | Meaning |\n| --- | --- |\n| `undisclosed` | The sources say it was not disclosed |\n| `not_found` | No accepted claim was found; this is not proof of non-disclosure |\n| `not_stated_in_sources` | Assessed relevant sources do not state it |\n| `currency_ambiguous` | A numeric amount is understood but its currency is unresolved |\n| `non_exact_amount` | The source states an approximation, bound or range; see reported amounts |\n| `unsupported_format` | Relevant wording could not be normalized |\n| `not_yet_researched` | Relevant research has not been attempted |\n| `ambiguous_entity` | The company could not be identified with certainty |\n| `conflicting_sources` | Credible sources disagree; the field is withheld and sent to review |\n| `insufficient_evidence` | Stated, but not by a primary source or two independent ones |\n| `not_applicable` | The field does not apply to this round |\n| `pending_refresh` | A refresh is in progress |\n\n`rounds` is the source of truth; the flat arrays (`all_stages`, `amount`) line up with it by index. Each round maps accepted, reported and conflicting fields in `field_evidence`, alongside\n`evidence_ids`, and `evidence` holds each source's URL, type, publication date and the verbatim quote (at most 200\ncharacters; social posts are linked, never quoted). `latest_stage` is the newest qualifying equity round by\nannouncement date, or null; it never falls back to an older stage.\n\n## Country hint\n`country` (ISO 3166-1 alpha-2) narrows an ambiguous **name** to candidates whose recorded country or site-proven ccTLD\nmatches. A candidate is dropped only when it is proven to be elsewhere, and one company is returned only when it\npositively matches (the answer then carries `narrowed_by: \"country\"`). Generic ccTLDs such as .io, .ai and .co prove\nnothing. The hint is stored with the research job and passed to it.\n\n## Research scope and caching\nThe default `scope: \"history\"` includes historical rounds and the latest round. An optional `history_since` limits\nthat window; `scope: \"latest\"` requests a narrower search. Only unbounded history covers latest-only work,\nbecause the newest round can predate a history cutoff. `refresh` is `auto`, `force`, or `never`.\nForce bypasses retry windows but retains active-job coalescing, request limits, and a daily research quota if one is\nset (none by default). Joining an existing compatible job does not spend another research job.\n`require_completed_research: true` waits with 202 while requested work is active; `never` always takes precedence\nand returns a non-enqueuing unknown response if the requirement cannot be met.\n\nA job is finished once `GET /api/v1/jobs/{id}` shows a status other than `queued`, or when its `lookup.completed`\nwebhook arrives. To read the answer, post the same lookup again with `refresh: \"auto\"` (or `\"never\"`). `\"never\"` never starts work and always answers from storage. `\"auto\"` (the default) answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A `refresh: \"force\"` re-post is answered by the forced run you waited on only within 15 minutes of that run finishing (and within `max_age_seconds`); after that, force starts a new job and spends research quota. Poll with `refresh: \"auto\"`, never with `force`: a poller that keeps sending\n`force` queues new research every cycle.\nWith `refresh: \"never\"`, a completed search that found nothing reads `not_found` while it is inside `max_age_seconds`\nor its retry window (`next_retry_at`), and `stale` once both have passed. With the default `refresh: \"auto\"`, it\nreads `not_found` until its `next_retry_at` (24 hours after it completed); after that, the same lookup queues new\nresearch, even inside `max_age_seconds`, and a new job counts against the daily research quota.\n\n`research.completed_at` records completion for the requested scope/version. `checked_at` is the publication\nclock and cannot establish coverage. `allow_stale` governs time, not completeness. Before any research completion,\nthe publication clock determines whether stored facts are too old, and coverage is explicitly `monitor_only`.\nAfter completion, freshness uses the research-completion clock. Cooldowns can defer auto research even when\n`max_age_seconds` is zero; use `force` to explicitly request fresh work. Research may still stop with gaps.\n\nThe API reads company identity, the research state and the published revision on every request, in one database\nrequest (simultaneous reads coalesce). Published payloads are cached for up to 45 seconds by revision, so a new\nrevision reloads immediately. ETags are opaque response validators covering both published\ndata and research/request state. Send an ETag in `If-None-Match`; a fresh unchanged completed answer returns 304.\nThere is no shared CDN response cache. A cache expiry alone never means a web search was completed.\n\n## Webhooks\nSubscribe with `POST /api/v1/webhooks` (https only; the secret is shown once). Events:\n\n- `round.changed`: a company's published answer changed. Sent for the companies you have looked up (or the\n  `company_ids` you list), with the full new answer in `data` and its `revision`. A newer revision replaces an\n  undelivered older one, but retries can still arrive out of order: keep the highest `revision` per company.\n- `lookup.completed`: a research job you were waiting on finished (`status` done, unknown or failed). Its scope,\n  research outcome, a research summary and retry time are included; `input` is the request you sent, even when other\n  callers joined the same job. `company_id` is the job's final resolution of the identifier the job was created with,\n  which can be null or differ from what your own `input` resolves to: post your own lookup again to read your\n  answer. To read the answer, post the same lookup again with `refresh: \"auto\"` (or `\"never\"`). `\"never\"` never starts work and always answers from storage. `\"auto\"` (the default) answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A `refresh: \"force\"` re-post is answered by the forced run you waited on only within 15 minutes of that run finishing (and within `max_age_seconds`); after that, force starts a new job and spends research quota.\n- `webhook.test`: sent by `POST /api/v1/webhooks/{id}/test`.\n\nEach delivery is a POST with a JSON body and these headers:\n\n- `X-Prova-Delivery`: the delivery id (use it to ignore duplicates).\n- `X-Prova-Signature: t=<unix seconds>,v1=<hex>` where `v1` is HMAC-SHA256 over `\"<t>.<raw request body>\"` keyed\n  with your secret. Verify it against the raw bytes before parsing, compare in constant time, and reject a `t` more\n  than 5 minutes old.\n\n```js\nimport { createHmac, timingSafeEqual } from 'node:crypto'\nfunction verify(secret, header, rawBody) {\n  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))\n  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false\n  const want = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest()\n  const got = Buffer.from(parts.v1 ?? '', 'hex')\n  return got.length === want.length && timingSafeEqual(got, want)\n}\n```\n\n```python\nimport hmac, hashlib, time\ndef verify(secret: str, header: str, raw_body: bytes) -> bool:\n    parts = dict(p.split(\"=\", 1) for p in header.split(\",\"))\n    if abs(time.time() - int(parts[\"t\"])) > 300:\n        return False\n    want = hmac.new(secret.encode(), parts[\"t\"].encode() + b\".\" + raw_body, hashlib.sha256).hexdigest()\n    return hmac.compare_digest(want, parts.get(\"v1\", \"\"))\n```\n\nReply with any 2xx within 10 seconds; a delivery without a complete response status and headers after 15 seconds\nhas failed. Redirects are not followed. Failed deliveries are retried with exponential\nbackoff (1 minute, 3, 9, 27, 81, 243 minutes, then 12 hours) for 8 attempts in all, and a subscription is disabled\nafter 20 consecutive failures. Webhook URLs must resolve to public internet addresses.\n\n## Corrections\n`POST /api/v1/corrections` flags a field as wrong with evidence. It goes to human review and never changes an answer\nby itself; accepted corrections are published through the same evidence checks as everything else.\n","contact":{"email":"hi@cielpm.ai"}},"servers":[{"url":"https://api.provaapi.com","description":"Production API"},{"url":"/","description":"Current origin"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Funding","description":"Look up verified funding rounds"},{"name":"Jobs","description":"Research job status"},{"name":"Webhooks","description":"Signed notifications"},{"name":"Corrections","description":"Report a wrong value"},{"name":"Account","description":"Usage"},{"name":"Meta","description":"Health and documentation"}],"paths":{"/api/v1/funding-stages":{"post":{"tags":["Funding"],"operationId":"lookupFunding","summary":"Look up a company’s funding","description":"The standard answer (no `view`) is `found`, `not_found` or `pending` (202: send the same request again in a few seconds); only `found` is billed. With `view: \"raw\"` or `\"simple\"`, a 202 carries a `job_id`; follow it with `GET /api/v1/jobs/{id}` or the `lookup.completed` webhook. To read the answer, post the same lookup again with `refresh: \"auto\"` (or `\"never\"`). `\"never\"` never starts work and always answers from storage. `\"auto\"` (the default) answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A `refresh: \"force\"` re-post is answered by the forced run you waited on only within 15 minutes of that run finishing (and within `max_age_seconds`); after that, force starts a new job and spends research quota.","parameters":[{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"An ETag from an earlier answer; a fresh unchanged answer returns 304."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupRequest"},"examples":{"domain":{"value":{"domain":"example.com","max_age_seconds":86400,"allow_stale":true}},"name":{"value":{"name":"Example Robotics","country":"US"}},"linkedin":{"value":{"linkedinSlug":"example-robotics"}}}}}},"responses":{"200":{"description":"found or not_found (standard answer); with a view: a stored answer, an ambiguous name, or a recent unknown","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Answer"},{"$ref":"#/components/schemas/FullAnswer"},{"$ref":"#/components/schemas/NotFoundAnswer"},{"$ref":"#/components/schemas/FundingAnswer"},{"$ref":"#/components/schemas/SimpleFundingAnswer"},{"$ref":"#/components/schemas/Ambiguous"},{"$ref":"#/components/schemas/Unknown"}]}}},"headers":{"ETag":{"description":"Opaque validator of published data and research state","schema":{"type":"string"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"202":{"description":"Still looking (standard answer: pending); with a view: the requested research is queued or active","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/PendingAnswer"},{"$ref":"#/components/schemas/Pending"}]}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"304":{"description":"The answer matching If-None-Match is unchanged and fresh","headers":{"ETag":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/LimitReached"},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/funding-stages/bulk":{"post":{"tags":["Funding"],"operationId":"lookupFundingBulk","summary":"Look up to 100 companies at once","description":"Each item is validated and answered exactly like the single endpoint, and results come back in input order with the status each item would have had. A bad item gets its own 422 without failing the batch. Costs one rate-limit token per item. When the monthly spending limit is reached or the balance runs out during the batch, the items after it get 402 (not looked up, not billed).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkRequest"}}}},"responses":{"200":{"description":"One result per item, in input order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/LimitReached"},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"description":"The batch itself is invalid (not a list, empty, more than 100 items, or larger than your per-minute limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/jobs/{id}":{"get":{"tags":["Jobs"],"operationId":"getJob","summary":"Research job status","description":"When status is not queued, the job is finished. To read the answer, post the same lookup again with `refresh: \"auto\"` (or `\"never\"`). `\"never\"` never starts work and always answers from storage. `\"auto\"` (the default) answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A `refresh: \"force\"` re-post is answered by the forced run you waited on only within 15 minutes of that run finishing (and within `max_age_seconds`); after that, force starts a new job and spends research quota. A tenant key sees only the jobs it asked for, with its own country and the shared research summary, even when other callers joined the job.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/usage":{"get":{"tags":["Account"],"operationId":"getUsage","summary":"What your lookups cost so far","description":"`found` answers cost `pricing.found`. No-funding answers (\"No funding found for this company.\") cost the `pricing.no_funding` price for their day's hit rate (found ÷ found and no-funding); without hit-rate pricing that price is 0. Every other lookup (pending, could not check, several companies, an unchanged 304, an invalid request, an error) is free. A bulk request counts each company. Days are San Francisco days; today is priced at today's hit rate so far and is final at midnight. `balance` is your credit minus what every day cost (null without hit-rate pricing). Counts are written every few seconds, so the last seconds may not be included yet.","parameters":[{"name":"tenant_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Admin keys only: a tenant's account instead of the admin account"}],"responses":{"200":{"description":"Usage and cost","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/usage/limit":{"put":{"tags":["Account"],"operationId":"setSpendingLimit","summary":"Set or remove your monthly spending limit","description":"Once this month's lookups (San Francisco time) cost the limit or more, lookups get 402 and are not billed, until the 1st of the next month or until the limit is raised or removed. The new limit is in force at once and stays every month until changed. There is no limit unless one is set.","parameters":[{"name":"tenant_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Admin keys only: a tenant's account instead of the admin account"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["monthly"],"properties":{"monthly":{"type":["number","null"],"exclusiveMinimum":0,"maximum":1000000,"description":"US dollars a month, in whole cents (50 or 49.99); null removes the limit"}}},"examples":{"set":{"value":{"monthly":50}},"remove":{"value":{"monthly":null}}}}}},"responses":{"200":{"description":"The limit now in force","content":{"application/json":{"schema":{"type":"object","required":["limit"],"properties":{"limit":{"oneOf":[{"$ref":"#/components/schemas/SpendLimit"},{"type":"null"}]}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/billing/topup":{"post":{"tags":["Account"],"operationId":"topUp","summary":"Top up credits","description":"Without payment_method: a payment page (card or bank account) for this amount; send the browser to url. With the id of a saved payment method: it is charged now, and status says whether the credit was added (a card) or is on its way (a bank account, about 4 business days). Your dashboard does this for you.","parameters":[{"name":"tenant_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Admin keys only: a tenant's account instead of the admin account"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number","minimum":5,"maximum":25000,"description":"US dollars, in whole cents"},"payment_method":{"type":"string","description":"A saved payment method (GET /api/v1/billing/methods); left out: the payment page"}}},"examples":{"page":{"value":{"amount":500}},"saved":{"value":{"amount":500,"payment_method":"pm_123"}}}}}},"responses":{"200":{"description":"The payment page, or what the charge came to","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"enum":["succeeded","pending","failed"]},"message":{"type":["string","null"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"No such saved payment method","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not on prepaid billing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"The payment service failed; try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/billing/methods":{"get":{"tags":["Account"],"operationId":"listPaymentMethods","summary":"Saved cards and bank accounts","responses":{"200":{"description":"The default first","content":{"application/json":{"schema":{"type":"object","properties":{"methods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"label":{"type":"string"},"expires":{"type":["string","null"]},"default":{"type":"boolean"}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Not on prepaid billing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}},"post":{"tags":["Account"],"operationId":"addPaymentMethod","summary":"Add a card or bank account","description":"A page to save one; send the browser to url. It becomes the default when there is none.","responses":{"200":{"description":"The page","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Not on prepaid billing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/billing/methods/default":{"put":{"tags":["Account"],"operationId":"setDefaultPaymentMethod","summary":"Choose the default payment method","description":"Automatic top-ups charge it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}}}},"responses":{"200":{"description":"The new default","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"No such saved payment method","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/billing/methods/{id}":{"delete":{"tags":["Account"],"operationId":"removePaymentMethod","summary":"Remove a saved card or bank account","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"No such saved payment method","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/billing/payments/{id}/receipt":{"get":{"tags":["Account"],"operationId":"paymentReceipt","summary":"A payment's receipt","description":"Redirects to the receipt (a bank payment has one once it clears).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"The id in credits"}],"responses":{"302":{"description":"To the receipt"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"No such payment, or no receipt yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/billing/auto":{"put":{"tags":["Account"],"operationId":"setAutoTopup","summary":"Turn automatic top-ups on or off","description":"When your balance, with payments on their way, falls below `below`, one payment to your saved bank account or card brings it back to `to`. Checked every minute; one automatic top-up is on its way at a time. A declined payment turns them off (your usage shows why) until you save them again. Add credit once first: that saves the bank account or card.","parameters":[{"name":"tenant_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Admin keys only: a tenant's account instead of the admin account"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["auto"],"properties":{"auto":{"type":["object","null"],"required":["below","to"],"description":"null turns automatic top-ups off","properties":{"below":{"type":"number","minimum":0,"description":"US dollars, in whole cents"},"to":{"type":"number","maximum":100000,"description":"US dollars, at least 10 more than below"}}}}},"examples":{"on":{"value":{"auto":{"below":50,"to":500}}},"off":{"value":{"auto":null}}}}}},"responses":{"200":{"description":"Automatic top-ups now","content":{"application/json":{"schema":{"type":"object","required":["auto"],"properties":{"auto":{"type":["object","null"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"Not on prepaid billing, or no saved bank account or card yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/keys":{"get":{"tags":["Account"],"operationId":"listKeys","summary":"Your API keys (dashboard)","description":"From the dashboard, signed in with your email; an API key gets 403. Keys are never shown again after they are made: only their first characters.","responses":{"200":{"description":"Active keys, oldest first","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"prefix":{"type":"string","description":"The first 12 characters, to tell keys apart"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"created_by":{"type":["string","null"]}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Not signed in with your email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}},"post":{"tags":["Account"],"operationId":"createKey","summary":"Create an API key (dashboard)","description":"The answer is the only time the whole key is shown. At most 20 active keys.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":60}}}}}},"responses":{"201":{"description":"The new key","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"prefix":{"type":"string","description":"The first 12 characters, to tell keys apart"},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"},"created_by":{"type":["string","null"]}}},{"type":"object","properties":{"key":{"type":"string"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Not signed in with your email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"20 keys already","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/keys/{id}":{"patch":{"tags":["Account"],"operationId":"renameKey","summary":"Rename an API key (dashboard)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":60}}}}}},"responses":{"200":{"description":"Renamed","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Not signed in with your email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such active key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}},"delete":{"tags":["Account"],"operationId":"revokeKey","summary":"Revoke an API key (dashboard)","description":"The key stops working within a minute.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Not signed in with your email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such active key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/raised":{"get":{"tags":["Account"],"operationId":"listJustRaised","summary":"Startups that just raised (Just raised)","description":"Each company's newest round confirmed by an article and announced in the last 30 days, newest first, then the biggest. Without a key: the 3 newest and `total`. With a key or a dashboard sign-in whose account holds a running pass (POST /api/v1/raised/unlock): every one, a page at a time. Free; never billed as a lookup. Refreshed every few minutes.","security":[{},{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"The feed","content":{"application/json":{"schema":{"type":"object","properties":{"window_days":{"type":"integer"},"updated_at":{"type":["string","null"],"format":"date-time"},"total":{"type":"integer"},"unlocked":{"type":"boolean"},"free":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"},"pages":{"type":"integer"},"signed_in":{"type":"boolean"},"rounds":{"type":"array","items":{"type":"object","properties":{"company":{"type":"string"},"website":{"type":["string","null"]},"round":{"type":"string","description":"The round in words, like \"Series A\""},"stage":{"type":["string","null"]},"amount":{"type":["number","null"]},"currency":{"type":["string","null"]},"date":{"type":"string","format":"date"},"source_url":{"type":["string","null"],"format":"uri"},"investors":{"type":"array","items":{"type":"string"}}}}},"pass":{"type":"object","properties":{"price_usd":{"type":"number"},"days":{"type":"integer"},"active":{"type":"boolean"},"until":{"type":["string","null"],"format":"date-time"}}}}}}}},"401":{"description":"A key was sent and it is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The feed is unavailable just now","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/raised/unlock":{"post":{"tags":["Account"],"operationId":"unlockJustRaised","summary":"Unlock the whole Just raised feed","description":"Takes the pass's price from your prepaid balance and opens the whole feed for its days. A pass that is still running is returned as it is (`status: \"active\"`) and nothing is charged.","responses":{"200":{"description":"The pass","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"enum":["bought","active"]},"pass_until":{"type":"string","format":"date-time"},"price_usd":{"type":"number"},"charged_usd":{"type":"number"},"balance_usd":{"type":"number"}}}}}},"401":{"description":"Not signed in and no key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Balance too low: add credit first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A signed-in change not sent from the dashboard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not on prepaid billing, an admin key, or already unlocking","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not available yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ops/health":{"get":{"tags":["Account"],"operationId":"getOpsHealth","summary":"Service health (operator keys only)","description":"The worker's latest metrics snapshot (queues, ingestion, extraction and research outcomes, null rates, crawler and X usage) and every open alert. status is critical when the worker has been silent for 45 minutes or a critical alert is open, degraded when a warning is open, else ok. Tenant keys get 403.","responses":{"200":{"description":"Health","content":{"application/json":{"schema":{"type":"object","required":["status","worker_silent","alerts"],"properties":{"status":{"enum":["ok","degraded","critical"]},"worker_silent":{"type":"boolean"},"snapshot_age_seconds":{"type":["integer","null"]},"snapshot":{"type":["object","null"],"properties":{"taken_at":{"type":"string","format":"date-time"},"metrics":{"type":"object"}}},"alerts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"kind":{"type":"string"},"severity":{"enum":["info","warning","critical"]},"message":{"type":"string"},"details":{},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Not an operator key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/webhooks":{"post":{"tags":["Webhooks"],"operationId":"createWebhook","summary":"Subscribe to webhooks","description":"At most 20 subscriptions per tenant. The response is the only time the secret is shown.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/NeedsTenant"},"409":{"description":"Subscription limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}},"get":{"tags":["Webhooks"],"operationId":"listWebhooks","summary":"List your subscriptions","responses":{"200":{"description":"Subscriptions (without secrets)","content":{"application/json":{"schema":{"type":"object","required":["webhooks"],"properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/NeedsTenant"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/webhooks/{id}":{"delete":{"tags":["Webhooks"],"operationId":"deleteWebhook","summary":"Delete a subscription and its pending deliveries","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/NeedsTenant"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"operationId":"testWebhook","summary":"Queue a signed webhook.test delivery","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"Queued","content":{"application/json":{"schema":{"type":"object","required":["status","delivery_id"],"properties":{"status":{"const":"queued"},"delivery_id":{"type":"string","format":"uuid"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/NeedsTenant"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The subscription was disabled after repeated failures","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/api/v1/corrections":{"post":{"tags":["Corrections"],"operationId":"createCorrection","summary":"Report a wrong or missing value","description":"Goes to human review. It never changes an answer by itself.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrectionRequest"}}}},"responses":{"201":{"description":"Recorded for review","content":{"application/json":{"schema":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"const":"open"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"$ref":"#/components/responses/TooLarge"},"422":{"description":"Invalid input, or a name that matches several companies (candidates included)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/AuthUnavailable"}}}},"/openapi.json":{"get":{"tags":["Meta"],"operationId":"openapi","summary":"OpenAPI 3.1 JSON for API clients and LLMs","security":[],"responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/openAPI.json":{"get":{"tags":["Meta"],"operationId":"openapiAlias","summary":"Alias of /openapi.json","security":[],"responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/docs":{"get":{"tags":["Meta"],"operationId":"docs","summary":"Machine-readable API documentation for LLMs","description":"Returns the complete OpenAPI 3.1 JSON directly, including authentication, endpoints, request and response schemas, and examples. No JavaScript or authentication required. For the interactive guide, visit /guide.","security":[],"responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/reference":{"get":{"tags":["Meta"],"operationId":"reference","summary":"Rendered API reference for browsers","security":[],"responses":{"200":{"description":"HTML"}}}},"/guide":{"get":{"tags":["Meta"],"operationId":"guide","summary":"Beginner and intermediate guide with a live playground","security":[],"responses":{"200":{"description":"HTML"}}}},"/health":{"get":{"tags":["Meta"],"operationId":"health","summary":"Liveness","security":[],"responses":{"200":{"description":"\"ok\"","content":{"text/plain":{"schema":{"const":"ok"}}}}}}}},"webhooks":{"round.changed":{"post":{"summary":"round.changed delivery","parameters":[{"name":"X-Prova-Signature","in":"header","required":true,"schema":{"type":"string","pattern":"^t=\\d+,v1=[0-9a-f]{64}$"},"description":"t = unix seconds; v1 = hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the subscription secret"},{"name":"X-Prova-Delivery","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoundChangedEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else, a redirect, or no complete response status and headers within 15 s is retried."}}}},"lookup.completed":{"post":{"summary":"lookup.completed delivery","parameters":[{"name":"X-Prova-Signature","in":"header","required":true,"schema":{"type":"string","pattern":"^t=\\d+,v1=[0-9a-f]{64}$"},"description":"t = unix seconds; v1 = hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the subscription secret"},{"name":"X-Prova-Delivery","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupCompletedEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else, a redirect, or no complete response status and headers within 15 s is retried."}}}},"webhook.test":{"post":{"summary":"webhook.test delivery","parameters":[{"name":"X-Prova-Signature","in":"header","required":true,"schema":{"type":"string","pattern":"^t=\\d+,v1=[0-9a-f]{64}$"},"description":"t = unix seconds; v1 = hex HMAC-SHA256 of \"<t>.<raw body>\" keyed with the subscription secret"},{"name":"X-Prova-Delivery","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEvent"}}}},"responses":{"2XX":{"description":"Received. Anything else, a redirect, or no complete response status and headers within 15 s is retried."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A Prova API key"}},"headers":{"RateLimitLimit":{"description":"Requests allowed per minute","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the bucket now","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"Unauthorized":{"description":"Missing, unknown or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"Invalid input; the error says what to fix","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooLarge":{"description":"Request body over 256 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NeedsTenant":{"description":"Admin keys have no tenant; use a tenant key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Over your per-minute limit","content":{"application/json":{"schema":{"type":"object","required":["error","retry_after"],"properties":{"error":{"type":"string"},"retry_after":{"type":"integer"}}}}},"headers":{"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}}},"AuthUnavailable":{"description":"Keys could not be checked right now; retry shortly","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"The lookup failed; retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"LimitReached":{"description":"Not looked up and not billed. With `limit`: your monthly spending limit is reached; lookups start again on `limit.resets` (San Francisco time), or when the limit is raised or removed. With `balance`: your balance, with payments on their way, can't pay for a lookup; lookups start again within 15 seconds of a top-up.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","limit"],"properties":{"error":{"type":"string"},"limit":{"$ref":"#/components/schemas/SpendLimit"}}},{"type":"object","required":["error","balance"],"properties":{"error":{"type":"string"},"balance":{"$ref":"#/components/schemas/CreditNeeded"}}}]}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"NullReason":{"type":"string","enum":["undisclosed","not_found","ambiguous_entity","conflicting_sources","insufficient_evidence","not_applicable","pending_refresh","currency_ambiguous","unsupported_format","non_exact_amount","not_stated_in_sources","not_yet_researched","research_deferred","research_incomplete","stale"]},"JobReason":{"type":"string","enum":["undisclosed","not_found","ambiguous_entity","conflicting_sources","insufficient_evidence","not_applicable","pending_refresh","currency_ambiguous","unsupported_format","non_exact_amount","not_stated_in_sources","not_yet_researched","research_deferred","research_incomplete","stale","retry_limit","research_failed"],"description":"A null reason, or why a job failed: retry_limit (it kept failing and was given up) or research_failed"},"Country":{"type":"string","enum":["AD","AE","AF","AG","AI","AL","AM","AO","AQ","AR","AS","AT","AU","AW","AX","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ","BL","BM","BN","BO","BQ","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF","CG","CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CW","CX","CY","CZ","DE","DJ","DK","DM","DO","DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ","FK","FM","FO","FR","GA","GB","GD","GE","GF","GG","GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HK","HM","HN","HR","HT","HU","ID","IE","IL","IM","IN","IO","IQ","IR","IS","IT","JE","JM","JO","JP","KE","KG","KH","KI","KM","KN","KP","KR","KW","KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","ME","MF","MG","MH","MK","ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY","QA","RE","RO","RS","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO","SR","SS","ST","SV","SX","SY","SZ","TC","TD","TF","TG","TH","TJ","TK","TL","TM","TN","TO","TR","TT","TV","TW","TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE","YT","ZA","ZM","ZW"],"description":"ISO 3166-1 alpha-2 (case-insensitive on input)"},"LookupRequest":{"type":"object","description":"Exactly one of name, domain or linkedinSlug.","properties":{"name":{"type":"string","maxLength":500},"domain":{"type":"string","maxLength":500,"description":"Any URL or host; reduced to the registrable domain"},"linkedinSlug":{"type":"string","maxLength":500,"description":"The company slug or its linkedin.com/company URL"},"country":{"$ref":"#/components/schemas/Country"},"max_age_seconds":{"type":"integer","minimum":0,"default":604800,"description":"Maximum age of completed research for the requested scope; before any completion, the age of stored facts. Under `refresh: \"never\"` a run inside this age is answered from storage. Under `refresh: \"auto\"`, a run that found nothing, or a partial or failed run, is researched again once its `next_retry_at` passes, even inside this age, and so is any run when new source material arrives."},"allow_stale":{"type":"boolean","default":true,"description":"Allow older stored facts; does not require research completeness"},"scope":{"enum":["history","latest"],"default":"history"},"history_since":{"type":"string","format":"date","description":"Optional history start, permitted only with scope history"},"refresh":{"enum":["auto","force","never"],"default":"auto","description":"`force` bypasses retry windows; `never` does not enqueue any work. `auto` answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A repeated force is answered by the forced run it waited on only within 15 minutes of that run finishing; poll with auto."},"require_completed_research":{"type":"boolean","default":false,"description":"Return 202 while required work is active; with refresh never, return an explicit non-enqueuing unknown if unmet"},"view":{"enum":["full","raw","simple"],"description":"Leave out for the standard answer (found, not_found or pending). full: the same answer with each round's sources and notes. raw (the evidence answer as stored) and simple (the earlier short answer: company and Summary) keep their earlier shapes, including their detailed pending and unknown answers"}},"oneOf":[{"required":["name"]},{"required":["domain"]},{"required":["linkedinSlug"]}]},"Company":{"type":"object","required":["id","name","match_status"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"domain":{"type":["string","null"]},"linkedinSlug":{"type":["string","null"]},"match_status":{"type":"string","enum":["verified","name_only"],"description":"verified: bound by domain or SEC CIK"}}},"Investor":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"role":{"enum":["lead",null]}}},"Round":{"type":"object","required":["id","investors","null_reasons","evidence_ids"],"properties":{"id":{"type":"string","format":"uuid","description":"Changes when the company’s rounds are rebuilt"},"financing_type":{"enum":["equity","debt","grant","mixed","other",null]},"stage":{"oneOf":[{"type":"string","pattern":"^(pre_seed|seed|series_[a-h]|bridge|growth|grant|debt|crowdfunding|safe|convertible_note)(_extension)?$"},{"type":"null"}]},"amount":{"type":["number","null"],"description":"Exact amount of this round; never a range, valuation or lifetime total. Undisclosed is null, never 0."},"currency":{"type":["string","null"],"pattern":"^[A-Z]{3}$"},"amount_raw":{"type":["string","null"]},"reported_amounts":{"type":"array","items":{"$ref":"#/components/schemas/ReportedAmount"}},"reported_candidates":{"type":"array","items":{"$ref":"#/components/schemas/ReportedCandidate"}},"field_evidence":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/FieldEvidence"}},"announced_on":{"type":["string","null"],"format":"date"},"first_sale_on":{"type":["string","null"],"format":"date","description":"SEC Form D date of first sale"},"form_d_amount_sold":{"type":["number","null"]},"investors":{"type":"array","items":{"$ref":"#/components/schemas/Investor"}},"investor_list_completeness":{"type":"string","enum":["unknown","partial","complete"]},"status":{"type":"string","enum":["published","review"]},"parent_round_id":{"type":["string","null"],"format":"uuid","description":"For an *_extension round: the earlier round of the same base stage (within 24 months) it extends"},"verified_at":{"type":["string","null"],"format":"date-time","description":"When this round last passed the evidence rules; null for rounds held for review"},"null_reasons":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/NullReason"},"description":"Field name to the reason it is null"},"evidence_ids":{"type":"array","items":{"type":"string"}}}},"Evidence":{"type":"object","required":["id","url","source_type","quote"],"properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"source_type":{"type":"string","enum":["sec_form_d","press_wire","news","company_site","investor_site","search","company_confirmation","social","review","licensed"]},"quote":{"type":["string","null"],"maxLength":200,"description":"Verbatim from the source. Null for social posts, which are linked only."},"published_on":{"type":["string","null"],"format":"date"},"round_id":{"type":"string"},"fields":{"type":"array","items":{"type":"string"}},"state":{"enum":["accepted","reported","conflicting"]},"reason":{"type":["string","null"]},"derivation":{"$ref":"#/components/schemas/Derivation"}}},"ReportedAmount":{"type":"object","properties":{"raw":{"type":"string"},"relation":{"enum":["exact","approximate","greater_than","at_least","less_than","at_most","range","unparsed"]},"amount":{"type":["number","null"]},"lower":{"type":["number","null"]},"upper":{"type":["number","null"]},"currency":{"type":["string","null"]},"basis":{"enum":["this_round","lifetime_total","valuation","target"]},"evidence_ids":{"type":"array","items":{"type":"string"}},"state":{"enum":["reported","accepted","conflicting"]}}},"Summary":{"type":"object","required":["all_stages","amount","currency","dates","source","latest_stage","announcement_date","latest_source","investors"],"description":"The simple answer (also returned alone with view: \"simple\"). The arrays are aligned: entry i of all_stages, amount, currency, dates and source describes one round, oldest first. source \"verified\": every non-null value passed the evidence checks. source \"confirmed\": the round as a funding database reports it, with a news article dated with the round that states the same stage and amount (checked by code rules and a model answer of at least 0.9); rewrites of one release are one source, so this is not \"verified\". source \"metal\": the round as a funding database reports it, not confirmed; a verified round never contains its values. Latest follows chronology across both sources. A tie, a newer unknown financing type, or an active unresolved newer-event hold keeps latest null. Provider rows are removed only when a proven event association identifies the same verified round.","properties":{"all_stages":{"type":"array","items":{"type":["string","null"]},"description":"A standard stage slug. Stage wording with no standard stage is shown as a slug of that wording instead of null: series_a2, series_c_plus, pre_series_a, series_b_bridge, angel, venture (a database's unnamed venture round), corporate, private_equity. For a verified round this is the one such stage its sources report; null when the sources give no stage or disagree. For a provider round that the company's own announcement names, that stage (reported_rounds[].stage_correction)."},"amount":{"type":"array","items":{"type":["number","null"]}},"currency":{"type":"array","items":{"type":["string","null"]},"description":"For a metal or confirmed round, the currency a confirming article states for the same number, else USD: the database's amounts are US dollars it converted (reported_rounds[].currency_basis says which). For a verified round, null when the currency is not established."},"dates":{"type":"array","items":{"type":["string","null"],"format":"date"}},"source":{"type":"array","items":{"enum":["verified","confirmed","database","wikidata"]}},"latest_stage":{"oneOf":[{"type":"array","items":{"type":"string"},"maxItems":1},{"type":"null"}]},"announcement_date":{"type":["string","null"],"format":"date"},"latest_source":{"enum":["verified","confirmed","database","wikidata",null]},"investors":{"type":"array","items":{"type":"string"},"description":"Union across the listed rounds"},"data_status":{"enum":["finished","not_finished"],"description":"not_finished: the provider's full funding history is not collected yet (only the newest round from its company list), or its newest round has not been checked against public evidence yet. finished: both are done, whatever the check found. Always present in the simple answer."}}},"SimpleFundingAnswer":{"description":"The successful response for view: \"simple\". Pending, ambiguous and unknown responses keep their usual shapes.","allOf":[{"$ref":"#/components/schemas/Summary"},{"type":"object","required":["company","checked_at"],"properties":{"company":{"type":"object","required":["name","domain"],"properties":{"name":{"type":"string"},"domain":{"type":["string","null"]},"public":{"oneOf":[{"type":"object","required":["exchange","ticker"],"properties":{"exchange":{"type":["string","null"]},"ticker":{"type":["string","null"]}}},{"type":"null"}],"description":"Where the company trades while it is listed (then latest_stage is [\"ipo\"]); null otherwise"}}},"checked_at":{"type":"string","format":"date-time"},"job_id":{"type":"integer","description":"Present when the caller joined queued/active research"}}}]},"LatestSelection":{"type":"object","required":["signals","holds"],"description":"Chronology constraints preserved when a latest answer is withheld. Signals block a candidate on the same or an earlier date; active holds without a date block latest until resolved.","properties":{"signals":{"type":"array","items":{"type":"string","format":"date"}},"holds":{"type":"array","items":{"type":"object","required":["status","observed_on"],"properties":{"status":{"enum":["pending","confirmed"]},"observed_on":{"type":["string","null"],"format":"date"}}}}}},"ReportedRound":{"type":"object","description":"A round a funding database reports. Shown for coverage; never a verified field. verification: round_verified (the same round is in rounds[], see verified_round_id), not_confirmed (checked; no public announcement confirmed it), newer_round_found (evidence shows a later financing, so this round is history only), confirmed_by_article (a news article dated with the round states the same stage and amount; see confirmed_by), not_checked.","properties":{"source":{"type":"string","examples":["database"]},"label":{"type":"string"},"provider_url":{"type":["string","null"]},"external_id":{"type":"string"},"quote":{"type":["string","null"],"description":"For a round confirmed by an article: the sentence that states it, word for word, when it was kept"},"financing_type":{"enum":["equity","debt","grant","assistance","secondary","post_ipo","ipo","other","unknown"]},"exchange":{"type":["string","null"],"description":"An IPO (financing_type ipo): the stock exchange"},"ticker":{"type":["string","null"],"description":"An IPO: the ticker symbol"},"listed":{"type":"boolean","description":"An IPO: whether the company is still listed"},"delisted_on":{"type":["string","null"],"format":"date","description":"An IPO: when its last listing ended, when known"},"stage":{"type":["string","null"]},"stage_raw":{"type":["string","null"],"description":"The provider's wording; qualifiers such as extensions may be missing"},"stage_correction":{"type":["object","null"],"description":"The stage the company's own announcement (its site, or a wire release it issued) gives this provider round, e.g. \"Mediwhale initially raised $2 million in Series Pre-A funding in 2021\". The statement names the company, one stage and one year; its dollar amount, when stated, is within 30% of the provider's and fits no other round that year (without one, the year holds only this round). summary.all_stages shows this stage; stage keeps the provider's. Not a verified field.","properties":{"stage":{"type":"string"},"raw":{"type":"string"},"basis":{"enum":["company_announcement"]},"url":{"type":["string","null"],"format":"uri"},"quote":{"type":"string"}}},"amount":{"type":["number","null"]},"currency":{"type":["string","null"]},"currency_basis":{"enum":["provider","article","converted_by_provider",null],"description":"provider: the provider states the currency. article: a confirming article states this same number in that currency. converted_by_provider: USD, because the database converts its amounts to US dollars; the original currency is not stated. null when there is no amount."},"amount_note":{"type":["string","null"],"description":"Present when the currency is not stated by the provider: for converted_by_provider, says the amount is US dollars the provider converted"},"announced_on":{"type":["string","null"],"format":"date"},"investors":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"role":{"enum":["lead",null]}}}},"verification":{"enum":["round_verified","confirmed_by_article","not_confirmed","newer_round_found","not_checked","stock_exchange_listing"]},"confirmed_by":{"type":"array","items":{"type":"string","format":"uri"},"description":"The articles that confirmed this round (confirmed_by_article only)"},"verified_round_id":{"type":["string","null"],"format":"uuid"},"verified_round_basis":{"enum":["event_key","same_round_nearby",null],"description":"event_key means the evidence check linked this provider record to the verified event. same_round_nearby means the provider row is dated within 7 days of a verified round of the same stage (or an unstated verified stage with agreeing amounts), with amounts within 2% where comparable: the same round, shown once. Older records without a basis are not sufficient for deduplication."},"candidate_event_key":{"type":["string","null"],"description":"Identity of the candidate checked by the backfill. This is provenance only: it does not verify any reported value or prove a duplicate of a verified round."},"retrieved_at":{"type":["string","null"],"format":"date-time"}}},"ReportedCandidate":{"type":"object","properties":{"field":{"type":"string"},"value":{},"evidence_ids":{"type":"array","items":{"type":"string"}},"state":{"enum":["reported","conflicting"]},"reason":{"type":["string","null"]}}},"Derivation":{"type":"object","properties":{"method":{"enum":["explicit","document_region"]},"context":{"type":["string","null"]}},"description":"Whether currency is explicitly named or derived from a documented regional convention"},"FieldEvidence":{"type":"object","properties":{"state":{"enum":["accepted","reported","conflicting","unknown"]},"evidence_ids":{"type":"array","items":{"type":"string"}},"reason":{"type":["string","null"]},"explanation":{"type":"string"},"derivation":{"$ref":"#/components/schemas/Derivation"}}},"ResearchState":{"type":"object","properties":{"scope":{"enum":["history","latest"]},"history_since":{"type":["string","null"],"format":"date"},"version":{"type":"integer"},"coverage_status":{"enum":["monitor_only","partially_researched","researched_for_scope"],"description":"Scope completion is not a guarantee of exhaustive history"},"status":{"enum":["queued","cooldown","quota_exceeded","not_requested","complete","incomplete"]},"completed_at":{"type":["string","null"],"format":"date-time"},"last_attempt_at":{"type":["string","null"],"format":"date-time"},"next_retry_at":{"type":["string","null"],"format":"date-time"},"source_updated_at":{"type":["string","null"],"format":"date-time"},"outcome":{"enum":["complete","partial","failed",null]},"metadata":{"type":"object","description":"A summary every waiter may see: scope, stop reason, whether every planned search ran, counts (queries, pages, documents, remaining links), source families, missing fields, provider availability, and failures and unavailable routes counted by method and outcome. It never includes query text, URLs or any caller's request."},"job_id":{"type":"integer"}}},"PublishedAnswer":{"type":"object","required":["status","company","rounds","evidence","checked_at"],"properties":{"status":{"type":"string","enum":["partial","unknown"],"description":"partial: some rounds are known (history is never claimed complete)"},"company":{"$ref":"#/components/schemas/Company"},"all_stages":{"type":"array","items":{"type":["string","null"]},"description":"Stage of each round, by index"},"latest_stage":{"oneOf":[{"type":"array","items":{"type":"string"},"maxItems":1},{"type":"null"}]},"investors":{"type":"array","items":{"type":"string"},"description":"Union across rounds"},"amount":{"type":"array","items":{"type":["number","null"]},"description":"Amount of each round, by index"},"announcement_date":{"type":["string","null"],"format":"date"},"rounds":{"type":"array","items":{"$ref":"#/components/schemas/Round"}},"latest_stage_basis":{"const":"latest_known_equity_round_by_announcement_date"},"latest_funding_event":{"oneOf":[{"type":"object","description":"The newest dated round of any financing type (equity, debt, grant, mixed). Null when the newest round is unproven or two rounds tie.","properties":{"round_id":{"type":"string","format":"uuid"},"financing_type":{"type":["string","null"]},"stage":{"type":["string","null"]},"amount":{"type":["number","null"]},"currency":{"type":["string","null"]},"announced_on":{"type":["string","null"],"format":"date"}}},{"type":"null"}]},"latest_funding_event_basis":{"const":"latest_known_round_of_any_financing_type_by_announcement_date"},"verified_at":{"type":["string","null"],"format":"date-time","description":"Most recent verified_at across rounds"},"history_completeness":{"type":"string","enum":["unknown","complete"]},"reported_rounds":{"type":"array","items":{"$ref":"#/components/schemas/ReportedRound"},"description":"Provider-reported rounds, newest first, kept apart from verified rounds"},"reported_latest_round":{"oneOf":[{"$ref":"#/components/schemas/ReportedRound"},{"type":"null"}]},"reported_rounds_basis":{"const":"provider_reported_not_verified"},"public":{"oneOf":[{"type":"object","description":"The company's stock-exchange listing (its IPO is in reported_rounds, financing_type ipo); null for a company that never went public","properties":{"listed":{"type":"boolean"},"exchange":{"type":["string","null"]},"ticker":{"type":["string","null"]},"ipo_on":{"type":["string","null"],"format":"date"},"ipo_period":{"type":["string","null"],"description":"The IPO's year or month when its day is not known"},"delisted_on":{"type":["string","null"],"format":"date"},"source":{"type":"string"}}},{"type":"null"}]},"summary":{"$ref":"#/components/schemas/Summary"},"latest_selection":{"$ref":"#/components/schemas/LatestSelection"},"total_raised":{"oneOf":[{"type":"object","description":"The company's total funding raised to date as the standard answer gives it (TotalRaised), with the day it holds for and the article a stated total comes from","properties":{"amount":{"type":"number"},"currency":{"type":["string","null"]},"basis":{"type":["string","null"]},"as_of":{"type":["string","null"],"format":"date"},"source_url":{"type":["string","null"]}}},{"type":"null"}]},"evidence":{"type":"array","items":{"$ref":"#/components/schemas/Evidence"}},"checked_at":{"type":"string","format":"date-time"}}},"FundingAnswer":{"allOf":[{"$ref":"#/components/schemas/PublishedAnswer"},{"type":"object","required":["revision","freshness_status"],"properties":{"revision":{"type":"integer"},"freshness_status":{"type":"string","enum":["fresh","stale_refreshing","stale","enriching","unresearched"]},"research":{"$ref":"#/components/schemas/ResearchState"},"job_id":{"type":"integer","description":"Present when the caller joined queued/active research"},"narrowed_by":{"const":"country","description":"Present when the country hint chose among several companies with this name"}}}]},"AnswerRound":{"type":"object","additionalProperties":false,"required":["stage","amount","currency","date","investors","lead_investors","source"],"properties":{"stage":{"type":["string","null"],"description":"A stage slug as in Summary.all_stages: pre_seed, seed, series_a, series_b, ..., or ipo for the company going public; null when the sources give none"},"amount":{"type":["number","null"],"description":"The new money of this round in `currency`; null when not disclosed. Never a total raised or a valuation."},"currency":{"type":["string","null"],"pattern":"^[A-Z]{3}$"},"date":{"type":["string","null"],"format":"date","description":"When the round was announced"},"investors":{"type":"array","items":{"type":"string"}},"lead_investors":{"type":"array","items":{"type":"string"},"description":"The investors that led the round (also listed in investors); empty when the sources name no lead"},"source":{"enum":["verified","confirmed","database","wikidata"],"description":"verified: checked against the announcement. confirmed: a dated news article states the same round. database: reported by a funding database (or a funding database page the search read), not checked yet; its amounts can be US dollars as the database converted them. wikidata: an IPO from a stock-exchange listing in Wikidata, not checked yet."},"stage_source":{"const":"database","description":"Present only when the stage is the funding database's for this same round (its row within 7 days) because the article states none"}}},"OtherFunding":{"type":"object","additionalProperties":false,"required":["type","stage","amount","currency","date","investors","lead_investors","source"],"properties":{"type":{"enum":["debt","grant","assistance","secondary","post_ipo","other"],"description":"debt: a loan or other debt. grant: a grant or a prize. assistance: help that takes no shares, such as an accelerator program. secondary: a sale of existing shares (no new money for the company). post_ipo: an offering of a company already listed. other: money of another kind."},"stage":{"type":["string","null"],"description":"A stage slug as in Summary.all_stages: pre_seed, seed, series_a, series_b, ..., or ipo for the company going public; null when the sources give none"},"amount":{"type":["number","null"],"description":"The new money of this round in `currency`; null when not disclosed. Never a total raised or a valuation."},"currency":{"type":["string","null"],"pattern":"^[A-Z]{3}$"},"date":{"type":["string","null"],"format":"date","description":"When the round was announced"},"investors":{"type":"array","items":{"type":"string"}},"lead_investors":{"type":"array","items":{"type":"string"},"description":"The investors that led the round (also listed in investors); empty when the sources name no lead"},"source":{"enum":["verified","confirmed","database","wikidata"],"description":"verified: checked against the announcement. confirmed: a dated news article states the same round. database: reported by a funding database (or a funding database page the search read), not checked yet; its amounts can be US dollars as the database converted them. wikidata: an IPO from a stock-exchange listing in Wikidata, not checked yet."},"stage_source":{"const":"database","description":"Present only when the stage is the funding database's for this same round (its row within 7 days) because the article states none"}},"description":"Money that is not an equity round (a grant, a loan, a share sale...), with the same fields as a round plus its type. Listed in other_funding only where Prova lists it apart from rounds; elsewhere it is a row of rounds."},"AnswerCompany":{"type":"object","additionalProperties":false,"required":["name","domain","public"],"properties":{"name":{"type":["string","null"]},"domain":{"type":["string","null"]},"public":{"oneOf":[{"type":"object","additionalProperties":false,"required":["exchange","ticker"],"properties":{"exchange":{"type":["string","null"]},"ticker":{"type":["string","null"]}}},{"type":"null"}],"description":"Where the company is listed, while it is listed: its IPO is then its latest round (stage ipo). null for a private company or one no longer listed."}}},"Answer":{"type":"object","additionalProperties":false,"required":["status","company","latest_round","latest_stage","total_raised","rounds"],"description":"The standard answer when funding is found (HTTP 200; the only billed answer).","properties":{"status":{"const":"found"},"company":{"$ref":"#/components/schemas/AnswerCompany"},"latest_round":{"oneOf":[{"$ref":"#/components/schemas/AnswerRound"},{"type":"null"}],"description":"The newest dated round of equity in `rounds` (a loan or a grant never is; on a tie, the better-checked round); for a listed company, its IPO; null only when no such round has a date"},"latest_stage":{"type":["string","null"],"description":"The stage the company is at: latest_round's stage; when latest_round names none, the newest stage a round names in the 18 months before it; ipo for a listed company; null when no round names one"},"total_raised":{"oneOf":[{"$ref":"#/components/schemas/TotalRaised"},{"type":"null"}],"description":"The company's total funding raised to date, when Prova has one; null otherwise"},"rounds":{"type":"array","items":{"$ref":"#/components/schemas/AnswerRound"},"description":"Newest first; rounds without a date last. Never empty, except where other_funding lists the company's only funding"},"other_funding":{"type":"array","items":{"$ref":"#/components/schemas/OtherFunding"},"description":"Present only where Prova lists money that is not an equity round apart from rounds: grants, loans, share sales and the like, newest first, each with its type. latest_round and latest_stage never come from them. Where it is absent, those rows are in rounds (the full view's notes say \"A loan, not an equity round.\" or \"A grant, not an equity round.\")."}},"anyOf":[{"properties":{"rounds":{"minItems":1}}},{"required":["other_funding"],"properties":{"other_funding":{"minItems":1}}}]},"TotalRaised":{"type":"object","additionalProperties":false,"required":["amount","currency","basis","as_of"],"description":"The company's total funding raised to date. Never a valuation, and never built from funding-database rows.","properties":{"amount":{"type":"number","exclusiveMinimum":0,"description":"In `currency`"},"currency":{"type":["string","null"],"pattern":"^[A-Z]{3}$","description":"null when the currency is not established"},"basis":{"enum":["stated_total","sum_of_checked_rounds",null],"description":"How Prova has it. stated_total: a total an article states (\"bringing its total funding to $50 million\"), with any checked rounds announced after that article added. sum_of_checked_rounds: the company's checked (verified or confirmed) equity rounds added up, when each states an amount in one currency."},"as_of":{"type":["string","null"],"format":"date","description":"The day the total holds for: the newest article or round it counts. null when not known"}}},"Source":{"type":"object","additionalProperties":false,"required":["type","url","date","quote"],"properties":{"type":{"type":"string","description":"company, press release, filing, investor, news, social post, article, database, database (Wikidata), ..."},"url":{"type":"string"},"date":{"type":["string","null"],"format":"date","description":"When the source was published"},"quote":{"type":["string","null"],"description":"The sentence that states the round, word for word; null when only the link is kept"}}},"FullAnswerRound":{"type":"object","additionalProperties":false,"required":["stage","amount","currency","date","investors","lead_investors","source","sources","notes"],"properties":{"stage":{"type":["string","null"]},"amount":{"type":["number","null"]},"currency":{"type":["string","null"],"pattern":"^[A-Z]{3}$"},"date":{"type":["string","null"],"format":"date"},"investors":{"type":"array","items":{"type":"string"}},"lead_investors":{"type":"array","items":{"type":"string"}},"source":{"enum":["verified","confirmed","database","wikidata"]},"stage_source":{"const":"database"},"sources":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/Source"}},"notes":{"type":"array","items":{"type":"string"}}},"description":"An AnswerRound with its sources (at most four, one per website: the company's own first for a verified round, the article that confirmed it first for a confirmed one) and notes in words"},"FullOtherFunding":{"type":"object","additionalProperties":false,"required":["type","stage","amount","currency","date","investors","lead_investors","source","sources","notes"],"properties":{"type":{"enum":["debt","grant","assistance","secondary","post_ipo","other"],"description":"debt: a loan or other debt. grant: a grant or a prize. assistance: help that takes no shares, such as an accelerator program. secondary: a sale of existing shares (no new money for the company). post_ipo: an offering of a company already listed. other: money of another kind."},"stage":{"type":["string","null"]},"amount":{"type":["number","null"]},"currency":{"type":["string","null"],"pattern":"^[A-Z]{3}$"},"date":{"type":["string","null"],"format":"date"},"investors":{"type":"array","items":{"type":"string"}},"lead_investors":{"type":"array","items":{"type":"string"}},"source":{"enum":["verified","confirmed","database","wikidata"]},"stage_source":{"const":"database"},"sources":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/Source"}},"notes":{"type":"array","items":{"type":"string"}}},"description":"An OtherFunding row with its sources and notes, as a FullAnswerRound"},"FullAnswer":{"type":"object","additionalProperties":false,"required":["status","company","checked_at","latest_round","latest_stage","total_raised","rounds"],"description":"view: \"full\" when funding is found (HTTP 200; billed like the standard answer): the same rounds, with sources and notes.","properties":{"status":{"const":"found"},"company":{"$ref":"#/components/schemas/AnswerCompany"},"checked_at":{"type":["string","null"],"format":"date-time","description":"When this answer was last updated"},"latest_round":{"oneOf":[{"$ref":"#/components/schemas/AnswerRound"},{"type":"null"}],"description":"The newest round, as in the standard answer; its sources are in rounds"},"latest_stage":{"type":["string","null"],"description":"As in the standard answer"},"total_raised":{"oneOf":[{"$ref":"#/components/schemas/TotalRaised"},{"type":"null"}],"description":"As in the standard answer"},"rounds":{"type":"array","items":{"$ref":"#/components/schemas/FullAnswerRound"},"description":"As in the standard answer"},"other_funding":{"type":"array","items":{"$ref":"#/components/schemas/FullOtherFunding"},"description":"As in the standard answer"}},"anyOf":[{"properties":{"rounds":{"minItems":1}}},{"required":["other_funding"],"properties":{"other_funding":{"minItems":1}}}]},"NotFoundAnswer":{"type":"object","additionalProperties":false,"required":["status","message"],"description":"The standard answer when no funding is found (HTTP 200; free).","properties":{"status":{"const":"not_found"},"message":{"type":"string"},"candidates":{"type":"array","description":"When a name fits several companies: send one of their domains instead","items":{"type":"object","properties":{"name":{"type":"string"},"domain":{"type":["string","null"]}}}}}},"PendingAnswer":{"type":"object","additionalProperties":false,"required":["status","message"],"description":"The standard answer while Prova is still looking (HTTP 202; free). Send the same request again in a few seconds.","properties":{"status":{"const":"pending"},"message":{"type":"string"}}},"Ambiguous":{"type":"object","required":["status","candidates"],"properties":{"status":{"const":"ambiguous"},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"domain":{"type":["string","null"]}}}}}},"Unknown":{"type":"object","required":["status","null_reason","checked_at"],"properties":{"status":{"const":"unknown"},"null_reason":{"$ref":"#/components/schemas/NullReason"},"checked_at":{"type":["string","null"],"format":"date-time"},"research":{"$ref":"#/components/schemas/ResearchState"}}},"Pending":{"type":"object","required":["status","job_id"],"properties":{"status":{"const":"pending"},"job_id":{"type":"integer"},"research":{"$ref":"#/components/schemas/ResearchState"}}},"BulkRequest":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/LookupRequest"}}}},"BulkResponse":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"type":"object","required":["index","http_status","body"],"properties":{"index":{"type":"integer","description":"Position in the request"},"http_status":{"type":"integer","enum":[200,202,402,422,429,500],"description":"What the single endpoint would have returned"},"body":{"oneOf":[{"$ref":"#/components/schemas/Answer"},{"$ref":"#/components/schemas/FullAnswer"},{"$ref":"#/components/schemas/NotFoundAnswer"},{"$ref":"#/components/schemas/PendingAnswer"},{"$ref":"#/components/schemas/FundingAnswer"},{"$ref":"#/components/schemas/SimpleFundingAnswer"},{"$ref":"#/components/schemas/Ambiguous"},{"$ref":"#/components/schemas/Unknown"},{"$ref":"#/components/schemas/Pending"},{"$ref":"#/components/schemas/Error"}]}}}}}},"Job":{"type":"object","required":["id","status"],"description":"To read the answer, post the same lookup again with `refresh: \"auto\"` (or `\"never\"`). `\"never\"` never starts work and always answers from storage. `\"auto\"` (the default) answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A `refresh: \"force\"` re-post is answered by the forced run you waited on only within 15 minutes of that run finishing (and within `max_age_seconds`); after that, force starts a new job and spends research quota.","properties":{"id":{"type":"integer"},"status":{"type":"string","enum":["queued","done","unknown","failed"]},"reason":{"type":["string","null"],"description":"Research outcome or failure reason"},"company_id":{"type":["string","null"],"format":"uuid","description":"The company the job ended bound to: its final resolution of the identifier the job was created with (or the company validated when it was queued), or null. Every caller who joined the job gets this same value, so it can be null or differ from what your own request resolves to, and `reason` describes the job's run, not your request. To read your own answer, post your own lookup again."},"country":{"type":["string","null"],"description":"The country hint your own request sent (a tenant key), even when another caller created the job"},"finished_at":{"type":["string","null"],"format":"date-time"},"scope":{"enum":["history","latest"]},"history_since":{"type":["string","null"],"format":"date"},"research_version":{"type":"integer"},"started_at":{"type":["string","null"],"format":"date-time"},"research_outcome":{"enum":["complete","partial","failed",null]},"research_metadata":{"type":"object","description":"A summary every waiter may see: scope, stop reason, whether every planned search ran, counts (queries, pages, documents, remaining links), source families, missing fields, provider availability, and failures and unavailable routes counted by method and outcome. It never includes query text, URLs or any caller's request. Operator keys see the worker's full record."},"next_retry_at":{"type":["string","null"],"format":"date-time"}}},"UsageTotals":{"type":"object","required":["lookups","found","no_funding","free","cost"],"properties":{"lookups":{"type":"integer","description":"Every lookup counted"},"found":{"type":"integer","description":"Lookups answered found"},"no_funding":{"type":"integer","description":"Lookups answered \"No funding found for this company.\""},"free":{"type":"integer","description":"Every other lookup"},"cost":{"type":"number","description":"US dollars: each day's found answers at pricing.found plus its no-funding answers at its hit rate's price"}}},"UsageDay":{"allOf":[{"$ref":"#/components/schemas/UsageTotals"},{"type":"object","required":["day","hit_rate","no_funding_price"],"properties":{"day":{"type":"string","format":"date","description":"A San Francisco day"},"hit_rate":{"type":["number","null"],"description":"found ÷ (found + no_funding), 0 to 1; null without either"},"no_funding_price":{"type":"number","description":"US dollars per no-funding answer that day (today: at the hit rate so far)"}}}]},"UsageHour":{"allOf":[{"$ref":"#/components/schemas/UsageTotals"},{"type":"object","required":["hour","no_funding_price"],"properties":{"hour":{"type":"string","format":"date-time","description":"The start of the hour (UTC)"},"no_funding_price":{"type":"number","description":"US dollars per no-funding answer: today's price (at the hit rate so far)"}}}]},"CreditNeeded":{"type":"object","required":["usd","incoming","needed"],"description":"Why a lookup was refused for credit","properties":{"usd":{"type":"number","description":"Your balance in US dollars; below 0 means owed"},"incoming":{"type":"number","description":"Top-ups still being paid; they count toward a lookup"},"needed":{"type":"number","description":"What one lookup needs: the price of a found answer"}}},"SpendLimit":{"type":"object","required":["monthly","spent","left","reached","resets"],"description":"The monthly spending limit and this month's spend against it (US dollars, San Francisco month)","properties":{"monthly":{"type":"number","description":"The limit"},"spent":{"type":"number","description":"Billed this month so far, including the last few seconds"},"left":{"type":"number","description":"monthly minus spent, never below 0"},"reached":{"type":"boolean","description":"true: lookups get 402 until resets, or until the limit is raised or removed"},"resets":{"type":"string","format":"date","description":"The 1st of the next month (San Francisco), when the count starts over"}}},"Usage":{"type":"object","required":["price_per_lookup","currency","time_zone","pricing","today","this_month","all_time","days","today_hours","balance","credits","limit","credit"],"properties":{"limit":{"oneOf":[{"$ref":"#/components/schemas/SpendLimit"},{"type":"null"}],"description":"Your monthly spending limit, or null when you have none"},"credit":{"type":["object","null"],"required":["required_from","needed","paused"],"description":"On prepaid billing: lookups need credit","properties":{"required_from":{"type":["string","null"],"format":"date-time","description":"From then, a lookup needs credit; null: never"},"needed":{"type":"number","description":"What one lookup needs: the price of a found answer"},"paused":{"type":"boolean","description":"true: lookups get 402 until a top-up"}}},"price_per_lookup":{"type":"number","description":"US dollars per lookup answered found (the same as pricing.found)"},"currency":{"const":"USD"},"time_zone":{"const":"America/Los_Angeles","description":"Days and months are San Francisco days and months"},"pricing":{"type":"object","required":["found","no_funding","prices_from"],"properties":{"found":{"type":"number","description":"US dollars per found answer"},"no_funding":{"type":"array","description":"The price of a no-funding answer by the day's hit rate, highest hit rate first: a day uses the first row whose hit_rate_from it reaches","items":{"type":"object","required":["hit_rate_from","price"],"properties":{"hit_rate_from":{"type":"number"},"price":{"type":"number","description":"US dollars"}}}},"prices_from":{"type":["string","null"],"format":"date","description":"The first day at these prices; earlier days cost found answers only"}}},"balance":{"type":["object","null"],"required":["usd","credits","spent","incoming"],"description":"null without hit-rate pricing","properties":{"usd":{"type":"number","description":"credits minus spent; below 0 means owed"},"credits":{"type":"number","description":"Top-ups and adjustments received, minus refunds"},"spent":{"type":"number","description":"What every day cost, today so far included"},"incoming":{"type":"number","description":"Top-ups still being paid (a bank payment takes a few days)"}}},"credits":{"type":"array","description":"Top-ups, refunds and adjustments, newest first (up to 50)","items":{"type":"object","required":["at","kind","amount","status"],"properties":{"at":{"type":"string","format":"date-time"},"kind":{"enum":["topup","auto_topup","refund","adjustment"]},"amount":{"type":"number","description":"US dollars; a refund is below 0"},"status":{"enum":["pending","succeeded","failed"]},"note":{"type":["string","null"]}}}},"billing":{"type":["object","null"],"description":"On prepaid billing: how you pay","properties":{"payments":{"type":"boolean","description":"Top-ups can be made now"},"payment_method":{"type":["string","null"],"description":"The saved bank account or card, like \"Chase ending 6789\""},"auto":{"type":["object","null"],"properties":{"below":{"type":"number"},"to":{"type":"number"}}},"auto_stopped":{"type":["string","null"],"description":"Why automatic top-ups stopped (a declined payment)"}}},"signed_in":{"type":["string","null"],"description":"The email address a dashboard browser signed in with"},"account":{"type":["object","null"],"description":"The name and logo the dashboard shows","properties":{"name":{"type":["string","null"]},"logo":{"type":["string","null"]}}},"today":{"$ref":"#/components/schemas/UsageDay"},"this_month":{"allOf":[{"$ref":"#/components/schemas/UsageTotals"},{"type":"object","required":["month"],"properties":{"month":{"type":"string","pattern":"^\\d{4}-\\d{2}$"}}}]},"all_time":{"allOf":[{"$ref":"#/components/schemas/UsageTotals"},{"type":"object","required":["since"],"properties":{"since":{"type":["string","null"],"format":"date","description":"The first day counted"}}}]},"days":{"type":"array","description":"The last 30 days, oldest first, including days without lookups","items":{"$ref":"#/components/schemas/UsageDay"}},"today_hours":{"type":["array","null"],"description":"Today's hours, San Francisco midnight to midnight (23 or 25 on a daylight-saving day), oldest first; hours not reached yet count 0. They add up to today. null when they could not be read just now","items":{"$ref":"#/components/schemas/UsageHour"}}}},"WebhookCreate":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","pattern":"^https://","maxLength":2048},"events":{"type":"array","items":{"enum":["round.changed","lookup.completed"]},"default":["round.changed"]},"company_ids":{"oneOf":[{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":1000},{"type":"null"}]}},"description":"company_ids null (default): every company you have looked up."},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"company_ids":{"oneOf":[{"type":"array","items":{"type":"string","format":"uuid"}},{"type":"null"}]},"active":{"type":"boolean","description":"false after 20 consecutive failed deliveries"},"consecutive_failures":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"WebhookCreated":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string","description":"Shown once. Signs every delivery."}}}]},"RoundChangedEvent":{"type":"object","required":["id","event","created_at","company_id","revision","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Delivery id, same as X-Prova-Delivery"},"event":{"const":"round.changed"},"created_at":{"type":"string","format":"date-time"},"company_id":{"type":"string","format":"uuid"},"revision":{"type":"integer"},"checked_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/PublishedAnswer","description":"The new published answer. Its revision is the event's revision; freshness_status and research come only from the lookup endpoint"}}},"LookupCompletedEvent":{"type":"object","required":["id","event","created_at","job_id","status"],"description":"To read the answer, post the same lookup again with `refresh: \"auto\"` (or `\"never\"`). `\"never\"` never starts work and always answers from storage. `\"auto\"` (the default) answers from storage, without a new job, while a completed run is inside `max_age_seconds`, except that it starts new research, even inside `max_age_seconds`, once a run that found nothing, or a partial or failed run, passes its `next_retry_at` (24 hours after a search that found nothing), and when new source material arrives. A `refresh: \"force\"` re-post is answered by the forced run you waited on only within 15 minutes of that run finishing (and within `max_age_seconds`); after that, force starts a new job and spends research quota.","properties":{"id":{"type":"string","format":"uuid"},"event":{"const":"lookup.completed"},"created_at":{"type":"string","format":"date-time"},"job_id":{"type":"integer"},"status":{"type":"string","enum":["done","unknown","failed"]},"company_id":{"type":["string","null"],"format":"uuid","description":"The company the job ended bound to: its final resolution of the identifier the job was created with (or the company validated when it was queued), or null. Every caller who joined the job gets this same value, so it can be null or differ from what your own request (`input`) resolves to, and `reason` describes the job's run, not your request. To read your own answer, post your own lookup again."},"reason":{"oneOf":[{"$ref":"#/components/schemas/JobReason"},{"type":"null"}]},"finished_at":{"type":["string","null"],"format":"date-time"},"scope":{"enum":["history","latest"]},"history_since":{"type":["string","null"],"format":"date"},"research_version":{"type":"integer"},"research_outcome":{"enum":["complete","partial","failed",null]},"research_metadata":{"type":"object","description":"A summary every waiter may see: scope, stop reason, whether every planned search ran, counts (queries, pages, documents, remaining links), source families, missing fields, provider availability, and failures and unavailable routes counted by method and outcome. It never includes query text, URLs or any caller's request."},"next_retry_at":{"type":["string","null"],"format":"date-time"},"input":{"type":"object","description":"The request you sent (kind, value, country), never the input of another caller who joined the same job","properties":{"kind":{"enum":["name","domain","linkedin_slug"]},"value":{"type":"string"},"country":{"type":["string","null"]}}}}},"TestEvent":{"type":"object","required":["id","event","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"event":{"const":"webhook.test"},"created_at":{"type":"string","format":"date-time"},"subscription_id":{"type":"string","format":"uuid"},"data":{"type":"object"}}},"CorrectionRequest":{"type":"object","required":["field","value","evidence_url"],"description":"Exactly one of company_id, domain or name.","properties":{"company_id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"name":{"type":"string"},"field":{"type":"string","enum":["stage","amount","currency","announced_on","lead","financing_type"]},"round_id":{"type":"string","format":"uuid","description":"A round id from the current answer"},"value":{"description":"The correct value, or null if the field should be empty. stage: e.g. series_a; amount: number; currency: ISO 4217; announced_on: YYYY-MM-DD; lead: a name or up to 3 names; financing_type: equity, debt, grant or mixed."},"evidence_url":{"type":"string","format":"uri","pattern":"^https://"},"note":{"type":"string","maxLength":2000}},"oneOf":[{"required":["company_id"]},{"required":["domain"]},{"required":["name"]}]}}}}