StartupSeeker Public API v1
This reference documents the legacy v1 compatibility API. The page and Markdown export are generated from the same v1 endpoint catalog so migrations stay explicit.
Official Surface
The reference covers the legacy compatibility surface: `/api/v1/*` endpoints plus the deprecated `/api/deep-research` route.
Current Behavior
The docs intentionally preserve the current v1 compatibility shapes, including the remaining envelope and access differences between routes.
Generated Markdown
Use the export below when you need to feed the selected API version to an LLM, internal tool, or external consumer.
Company Discovery
Legacy search, enrichment, and competitor endpoints.
/api/v1/searchSearch startups with a natural-language query and return the current legacy v1 result envelope.
/api/v1/enrichLook up a company by website and return the matching StartupSeeker company record, if one exists.
/api/v1/competitorsRun AI-powered competitor analysis from a company website or a sufficiently detailed company description.
VC Screening
Legacy classifier endpoints with lighter access controls.
/api/v1/vc-backable-classifierBatch-classify domains as VC-backable, with full descriptions and raw homepage scrape content.
/api/v1/vc-backable-minimumLow-payload VC-backability classifier that returns only the verdict map, with optional descriptions.
Long-Running Workflows
Legacy async and compatibility routes for deck parsing and deep research.
/api/v1/parse-deckUpload a PDF pitch deck and get per-slide summaries plus a combined markdown representation.
/api/deep-researchRun a multi-step research workflow that combines deep scrape, founders, funding, LinkedIn, scoring, and optional competitors.
Copy Docs for LLMs
Copy the same V1 public API reference that powers this page, formatted as Markdown.
Authentication and Access Modes
The legacy v1 surface is still mixed: most routes require API keys, while the two classifier endpoints remain anonymous and IP-limited.
API-key routes
`/api/v1/search`, `/api/v1/enrich`, `/api/v1/competitors`, `/api/v1/parse-deck`, and `/api/deep-research` require a StartupSeeker API key.
Authorization: Bearer ssk_live_your_api_keyAnonymous IP-limited routes
`/api/v1/vc-backable-classifier` and `/api/v1/vc-backable-minimum` do not currently require API keys and are enforced by IP-based quotas.
v1 compatibility notice
`/api/deep-research` remains documented as a legacy route, but public access is now API-key-only and new integrations should move to `/api/v2/deep-research-jobs`.
/api/v1/searchSearch API
Search startups with a natural-language query and return the current legacy v1 result envelope.
This route currently costs 1 credit per request.
Request Shape
{
"request_id": "search-demo-1",
"query": "AI startups helping ecommerce teams with demand forecasting"
}Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| request_id | string | null | No | Optional client correlation ID. Maximum 128 characters. |
| query | string | Yes | Search query. Must be between 3 and 500 characters. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| request_id | string | null | No | Echoes the provided request ID. |
| query | string | No | Original search query. |
| total_results | number | No | Number of companies returned in `results`. |
| results | array<object> | No | Structured company results from unified search. |
| search_data | object | No | Legacy v1 search metadata including `refined_query`, `version`, and `duration`. |
| rate_limit | object | No | Minute/day quota snapshot mirrored from the response headers. |
Sample Request
curl -X POST https://startup-seeker.com/api/v1/search \
-H "Authorization: Bearer ssk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"request_id": "search-demo-1",
"query": "AI startups helping ecommerce teams with demand forecasting"
}'Sample Response
{
"request_id": "search-demo-1",
"query": "AI startups helping ecommerce teams with demand forecasting",
"total_results": 2,
"results": [
{
"id": "458861125484422704",
"primary_key": "458861125484422704",
"name": "Euphya",
"description": "AI-powered demand forecasting for ecommerce teams.",
"website": "euphya.co",
"founded": "2020",
"location": "San Francisco, CA",
"linkedin_company_url": "https://www.linkedin.com/company/euphyaco",
"score": 0.77,
"quality_score": 0,
"linkedin_followers": 9,
"linkedin_employees": 0,
"funding_range": "",
"major_investors": [],
"query": "AI startups helping ecommerce teams with demand forecasting",
"isRelevant": true
}
],
"search_data": {
"query": "AI startups helping ecommerce teams with demand forecasting",
"refined_query": "AI demand forecasting ecommerce startups",
"final_output": "euphya.co",
"structured_results": [],
"version": "v1",
"duration": 1.42,
"issue": null
},
"rate_limit": {
"minute": {
"limit": 30,
"remaining": 29,
"reset_at": 1712083200000
},
"day": {
"limit": 100,
"remaining": 99,
"reset_at": 1712126400000
}
}
}Important Headers
| Header | Description |
|---|---|
| Authorization | Required. `Bearer ssk_live_...` or `ssk_test_...` API key. |
| X-RateLimit-Limit-Second | Effective per-second limit for the key/account. |
| X-RateLimit-Limit-Minute | Effective per-minute limit for the key/account. |
| X-RateLimit-Limit-Day | Effective per-day limit for the key/account. |
| X-Credits-Remaining | Remaining API credits after the request finalizes. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid JSON or invalid `query` length. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | INSUFFICIENT_CREDITS | API key is valid but the account has no remaining credits. |
| 429 | RATE_LIMITED | Per-key or per-account quota exceeded. |
| 500 | INTERNAL_ERROR | Unexpected search failure. |
Implementation Notes
- This endpoint is fixed to the current v1 response shape and returns at most 25 results.
- There is no separate `filters` object in v1. If you need filter-like constraints, express them in the `query` text; the legacy parser can infer founded year, funding, employee count, follower count, score, and location constraints.
- The `results` objects come from the live unified search pipeline; field presence can vary by company.
/api/v1/enrichEnrich API
Look up a company by website and return the matching StartupSeeker company record, if one exists.
This route currently costs 0 credits per request.
Request Shape
{
"request_id": "enrich-demo-1",
"website": "stripe.com"
}Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| request_id | string | null | No | Optional client correlation ID. Maximum 128 characters. |
| website | string | Yes | Company website or domain to normalize and look up. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| request_id | string | null | No | Echoes the provided request ID. |
| website | object | No | Contains both `submitted` and normalized website values. |
| company | object | null | No | Matching company record, or `null` when no record exists. |
| missing | boolean | No | Convenience flag; `true` when `company` is `null`. |
| rate_limit | object | No | Minute/day quota snapshot mirrored from the response headers. |
Sample Request
curl -X POST https://startup-seeker.com/api/v1/enrich \
-H "Authorization: Bearer ssk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"request_id": "enrich-demo-1",
"website": "stripe.com"
}'Sample Response
{
"request_id": "enrich-demo-1",
"website": {
"submitted": "stripe.com",
"normalized": "stripe.com"
},
"company": {
"id": "458861125612149361",
"name": "Stripe",
"website": "stripe.com",
"description": "Payments infrastructure for internet businesses."
},
"missing": false,
"rate_limit": {
"minute": {
"limit": 30,
"remaining": 29,
"reset_at": 1712083200000
},
"day": {
"limit": 100,
"remaining": 99,
"reset_at": 1712126400000
}
}
}Important Headers
| Header | Description |
|---|---|
| Authorization | Required. `Bearer ssk_live_...` or `ssk_test_...` API key. |
| X-RateLimit-Limit-Minute | Effective per-minute limit for the key/account. |
| X-RateLimit-Limit-Day | Effective per-day limit for the key/account. |
| X-Credits-Remaining | Remaining API credits after the request finalizes. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid JSON or invalid website input. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 429 | RATE_LIMITED | Per-key or per-account quota exceeded. |
| 500 | INTERNAL_ERROR | Website lookup service is not configured or failed. |
Implementation Notes
- The endpoint normalizes the submitted website before lookup.
- A 200 response with `"missing": true` is the expected result when StartupSeeker has no matching company.
/api/v1/competitorsCompetitors API
Run AI-powered competitor analysis from a company website or a sufficiently detailed company description.
This route currently costs 1 credit per request.
Request Shape
{
"company": {
"name": "Acme Analytics",
"website": "acmeanalytics.com"
}
}Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| company.name | string | null | No | Optional company name used to improve the resolved context. |
| company.website | string | null | No | Optional website. Provide this whenever possible for better resolution. |
| company.description | string | null | No | Optional company description. Required when no website is provided and must then be at least 20 characters. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| data | array<object> | No | Competitor matches and AI-generated summaries. |
| company | object | No | Contains the input payload and the resolved company context used by the analysis. |
| rate_limit | object | No | Minute/day quota snapshot mirrored from the response headers. |
Sample Request
curl -X POST https://startup-seeker.com/api/v1/competitors \
-H "Authorization: Bearer ssk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"company": {
"name": "Acme Analytics",
"website": "acmeanalytics.com"
}
}'Sample Response
{
"company": {
"input": {
"name": "Acme Analytics",
"website": "acmeanalytics.com",
"description": null
},
"resolved": {
"name": "Acme Analytics",
"normalized_website": "acmeanalytics.com",
"description": "SaaS analytics platform for B2B companies"
}
},
"data": [
{
"company": {
"name": "DataViz Pro",
"website": "datavizpro.io",
"description": "Business intelligence platform"
},
"similarity_level": "HIGH",
"summary": "DataViz Pro overlaps with Acme Analytics in analytics workflows and target buyers."
}
],
"rate_limit": {
"minute": {
"limit": 30,
"remaining": 29,
"reset_at": 1712083200000
},
"day": {
"limit": 100,
"remaining": 99,
"reset_at": 1712126400000
}
}
}Important Headers
| Header | Description |
|---|---|
| Authorization | Required. `Bearer ssk_live_...` or `ssk_test_...` API key. |
| X-RateLimit-Limit-Minute | Effective per-minute limit for the key/account. |
| X-RateLimit-Limit-Day | Effective per-day limit for the key/account. |
| X-Credits-Remaining | Remaining API credits after the request finalizes. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid JSON, missing both website and description, or description too short. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | INSUFFICIENT_CREDITS | Account has no remaining API credits. |
| 429 | RATE_LIMITED | Per-key or per-account quota exceeded. |
| 500 | INTERNAL_ERROR | Competitor analysis failed. |
Implementation Notes
- Either `company.website` or `company.description` must be present.
- When only a description is provided, make it specific; short descriptions are rejected.
/api/v1/vc-backable-classifierVC Backable Classifier
Batch-classify domains as VC-backable, with full descriptions and raw homepage scrape content.
Anonymous access is allowed and IP-rate-limited.
This route is not credit-metered today.
Request Shape
{
"websites": ["runwayml.com", "genei.io"],
"include_description": true
}Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| websites | array<string> | No | Preferred batch input. Supply one or more websites/domains. |
| website | string | No | Single-site shortcut when not using `websites`. |
| include_description | boolean | No | Optional. Defaults to `true` on this full endpoint. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| count | number | No | Number of entries returned in `data`. |
| data | array<object> | No | Classification results with `website`, `name`, `description`, `vc_investable`, and `homepage_scrape`. |
| rate_limit | object | No | Body copy of the second/minute/day rate-limit state. |
Sample Request
curl -X POST https://startup-seeker.com/api/v1/vc-backable-classifier \
-H "Content-Type: application/json" \
-d '{
"websites": ["runwayml.com", "genei.io"],
"include_description": true
}'Sample Response
{
"count": 2,
"data": [
{
"website": "runwayml.com",
"name": "Runway",
"description": "Runway delivers AI-powered creative tools for video and image generation.",
"vc_investable": "Yes",
"homepage_scrape": "<html>...</html>"
},
{
"website": "genei.io",
"name": "Genei",
"description": "Genei helps knowledge workers summarize research content.",
"vc_investable": "Likely Not",
"homepage_scrape": ""
}
],
"rate_limit": {
"second": {
"limit": 500,
"remaining": 498,
"reset_at": 1736831400000
},
"minute": {
"limit": 10000,
"remaining": 9998,
"reset_at": 1736831460000
},
"day": {
"limit": 50000,
"remaining": 49998,
"reset_at": 1736914200000
}
}
}Important Headers
| Header | Description |
|---|---|
| X-RateLimit-Limit-Second | Per-IP second limit. |
| X-RateLimit-Limit-Minute | Per-IP minute limit. |
| X-RateLimit-Limit-Day | Per-IP day limit. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Request omitted both `website` and `websites`, or a website is invalid. |
| 429 | RATE_LIMITED | Per-IP quota exceeded. |
| 500 | INTERNAL_ERROR | Required scraping configuration is missing or classification failed. |
Implementation Notes
- This endpoint is not credit-metered today.
- Domains are normalized and deduplicated before processing.
/api/v1/vc-backable-minimumVC Backable Minimum
Low-payload VC-backability classifier that returns only the verdict map, with optional descriptions.
Anonymous access is allowed and IP-rate-limited.
This route is not credit-metered today.
Request Shape
{
"websites": ["runwayml.com", "genei.io"],
"include_description": false
}Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| websites | array<string> | No | Preferred batch input. Supply one or more websites/domains. |
| website | string | No | Single-site shortcut when not using `websites`. |
| include_description | boolean | No | Optional. Defaults to `false` on this minimal endpoint. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| data | object | No | Map keyed by normalized website. Each value contains `classification` and optional `description`. |
Sample Request
curl -X POST https://startup-seeker.com/api/v1/vc-backable-minimum \
-H "Content-Type: application/json" \
-d '{
"websites": ["runwayml.com", "genei.io"]
}'Sample Response
{
"data": {
"runwayml.com": {
"classification": "Yes"
},
"genei.io": {
"classification": "Likely Not"
}
}
}Important Headers
| Header | Description |
|---|---|
| X-RateLimit-Limit-Second | Per-IP second limit. |
| X-RateLimit-Limit-Minute | Per-IP minute limit. |
| X-RateLimit-Limit-Day | Per-IP day limit. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Request omitted both `website` and `websites`, or a website is invalid. |
| 429 | RATE_LIMITED | Per-IP quota exceeded. |
| 500 | INTERNAL_ERROR | Required scraping configuration is missing or classification failed. |
Implementation Notes
- This endpoint is not credit-metered today.
- Use `include_description: true` if you want a short description alongside the verdicts.
/api/v1/parse-deckPitch Deck Parser
Upload a PDF pitch deck and get per-slide summaries plus a combined markdown representation.
This route currently costs 5 credits per request.
Request Shape
multipart/form-data
- file: <PDF, required>
- request_id: <string, optional>Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| file | File (PDF) | Yes | Pitch deck PDF. Maximum size is 30 MB. |
| request_id | string | null | No | Optional client correlation ID. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| request_id | string | null | No | Echoes the provided request ID. |
| filename | string | No | Original uploaded filename. |
| total_pages | number | No | Total number of PDF pages in the uploaded file. |
| processed_slides | number | No | Number of slides actually processed. Maximum 30. |
| slides | array<object> | No | Per-slide summaries with `page_number` and `summary`. |
| markdown | string | No | Combined markdown output generated from the processed slides. |
| rate_limit | object | No | Minute/day quota snapshot mirrored from the response headers. |
Sample Request
curl -X POST https://startup-seeker.com/api/v1/parse-deck \
-H "Authorization: Bearer ssk_live_your_api_key" \
-F "file=@pitch-deck.pdf" \
-F "request_id=deck-demo-1"Sample Response
{
"request_id": "deck-demo-1",
"filename": "pitch-deck.pdf",
"total_pages": 12,
"processed_slides": 12,
"slides": [
{
"page_number": 1,
"summary": "Title slide introducing the company and market."
}
],
"markdown": "## Slide 1\n\nTitle slide introducing the company and market.",
"rate_limit": {
"minute": {
"limit": 30,
"remaining": 29,
"reset_at": 1712083200000
},
"day": {
"limit": 100,
"remaining": 99,
"reset_at": 1712126400000
}
}
}Important Headers
| Header | Description |
|---|---|
| Authorization | Required. `Bearer ssk_live_...` or `ssk_test_...` API key. |
| X-RateLimit-Limit-Minute | Effective per-minute limit for the key/account. |
| X-RateLimit-Limit-Day | Effective per-day limit for the key/account. |
| X-Credits-Remaining | Remaining API credits after the request finalizes. |
| X-Credits-Charged | Credits charged for this request. Always `5` on successful or partial-successful processing. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_REQUEST | Body was not multipart/form-data, the file is missing, or the file is not a valid PDF. |
| 400 | INVALID_FILE_TYPE | Uploaded file is not a PDF. |
| 413 | FILE_TOO_LARGE | Uploaded PDF exceeds the 30 MB limit. |
| 207 | MULTI_STATUS | Partial success: one or more slides failed to process, but the request still returned usable output. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | INSUFFICIENT_CREDITS | Account has no remaining API credits. |
Implementation Notes
- Only the first 30 slides are processed; extra pages are ignored but still counted in `total_pages`.
- This endpoint can return HTTP 207 when some slides fail and others succeed.
/api/deep-researchDeep Research API
Run a multi-step research workflow that combines deep scrape, founders, funding, LinkedIn, scoring, and optional competitors.
This route currently costs 10 credits per request.
Request Shape
{
"website": "exa.ai",
"include_competitors": true,
"context": "Optional analyst notes",
"company_name": "Exa"
}Request Fields
| Name | Type | Required | Description |
|---|---|---|---|
| website | string | Yes | Website/domain to research. |
| zilliz_id | string | No | Optional existing StartupSeeker record ID. |
| include_competitors | boolean | No | Optional. Defaults to `true`. Set to `false` to skip competitor analysis. |
| city / country / country_iso | string | No | Optional location overrides used during the workflow. |
| context | string | No | Optional extra context. Public API requests are API-key-owned; signed-in app flows use internal job routes. |
| company_name | string | No | Optional company name override. |
Response Fields
| Name | Type | Required | Description |
|---|---|---|---|
| success | boolean | No | True when at least some of the research workflow succeeded. |
| zilliz_id | string | null | No | Resolved or newly-linked company record ID. |
| timestamp | string | No | ISO timestamp for completion time. |
| used_custom_context / context_truncated / warning | mixed | No | Context-related flags when custom context was provided. |
| data | object | No | Research subsystem results including `deepScrape`, `founders`, `funding`, `linkedin`, `scoring`, `zillizUpdate`, and optional `competitors`. |
| errors | object | No | Per-subsystem error messages for partial failures. |
| summary | object | No | Execution counts and total duration. |
| rate_limit | object | No | Returned for API-key requests. |
Sample Request
curl -X POST https://startup-seeker.com/api/deep-research \
-H "Authorization: Bearer ssk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"website": "exa.ai",
"include_competitors": false,
"company_name": "Exa"
}'Sample Response
{
"success": true,
"zilliz_id": "458861125612149361",
"timestamp": "2026-03-14T11:04:32.102Z",
"data": {
"deepScrape": {
"status": "fulfilled",
"website": "exa.ai",
"concise_description": "AI-native search engine for the web."
},
"founders": {
"status": "fulfilled",
"data": {
"founders": []
}
},
"funding": {
"status": "fulfilled",
"data": {
"total_funding": 107000000
}
},
"linkedin": {
"status": "fulfilled",
"data": {
"followers": 22841,
"employees": 92
}
},
"scoring": {
"status": "fulfilled",
"score": 0.82
},
"zillizUpdate": {
"status": "fulfilled"
}
},
"errors": {},
"summary": {
"total_requests": 5,
"successful": 5,
"failed": 0,
"execution_time_ms": 32450,
"competitors_skipped": true
},
"rate_limit": {
"minute": {
"limit": 30,
"remaining": 29,
"reset_at": 1712083200000
},
"day": {
"limit": 100,
"remaining": 99,
"reset_at": 1712126400000
}
}
}Important Headers
| Header | Description |
|---|---|
| Authorization | Required. `Bearer ssk_live_...` or `ssk_test_...` API key. |
| Retry-After | Returned for API-key rate-limit responses. |
| X-Credits-Remaining | Returned for API-key requests. |
Common Errors
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Missing or invalid `website`, or invalid JSON body. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | INSUFFICIENT_CREDITS | API-key request is valid but the account has no remaining credits. |
| 429 | RATE_LIMITED | API-key quota exceeded. |
| 500 | INTERNAL_ERROR | Workflow failed before producing a usable partial response. |
Implementation Notes
- Public access to `/api/deep-research` is API-key-only.
- Signed-in browser/app flows should use internal deep-research job routes instead of the public API path.
- Typical runtime is much longer than the other public endpoints, especially when `include_competitors` is `true`.
- Response and error envelopes are intentionally documented as-is; they are not fully aligned with the `/api/v1/*` routes.
Rate Limits
v1 still spans two rate-limit families: metered API-key routes and anonymous IP-limited classifier routes.
Header Behavior
- Metered API-key routes return `X-RateLimit-*` headers and `X-Credits-Remaining`.
- `/api/v1/parse-deck` also returns `X-Credits-Charged`.
- IP-limited classifier routes return `X-RateLimit-*` headers but no credit headers.
Errors
Error envelopes are not fully standardized across the v1 compatibility surface. The endpoint sections above show the route-specific status codes and error codes you should expect.
Flat error envelope
Most metered v1 routes use a flat JSON object with `error`, `code`, and optional `meta`.
{
"error": "Invalid request body: Query must be at least 3 characters long.",
"code": "BAD_REQUEST"
}Nested error envelope
The classifier routes and parse-deck route currently return nested error objects.
{
"error": {
"code": "INVALID_REQUEST",
"message": "A PDF file is required. Use the \"file\" field."
}
}Important caveat
Treat each route as its own contract. If you are building an SDK or proxy, branch on the endpoint instead of assuming a single shared error schema across the entire public API.