StartupSeeker Public API v2

This reference documents the v2 public API. The page, the Markdown export, the OpenAPI JSON, and the README overview are generated from the same v2 endpoint catalog.

Official Surface

The reference covers the `/api/v2/*` public endpoints, including async job creation, polling, and result retrieval.

Current Behavior

The docs reflect the current v2 contract: API-key-only public access, unified envelopes, and async jobs for long-running workflows.

Generated Markdown

Use the export below when you need to feed the selected API version to an LLM, internal tool, or external consumer.

Discovery and Analysis

Core synchronous endpoints for search, lookups, founder discovery, competitor analysis, and startup screening.

Pitch Deck Jobs

Create, recover, poll, and fetch results for asynchronous pitch-deck parsing.

Deep Research Jobs

Create, recover, poll, and fetch results for asynchronous deep-research runs.

Webhooks

Manage account-level webhook endpoints for async job completion events.

Copy Docs for LLMs

Copy the same V2 public API reference that powers this page, formatted as Markdown.

OpenAPI JSON

Download the generated machine-readable v2 spec for schema tooling, SDK generation, or external validation.

OpenAPI JSON

Authentication and Access Modes

Public v2 access uses a single auth model: send a StartupSeeker API key in the `Authorization` header. Signed-in browser flows use internal routes and are intentionally not part of the public v2 contract.

Bearer token format

Use the same bearer token header across the full v2 API surface.

Authorization: Bearer ssk_live_your_api_key

Async workflow model

Deep research and pitch-deck parsing use async jobs in v2. Create a job, poll its status, then fetch the final result.

POST/api/v2/searches
1 credit / request

Searches

Use this route when you want StartupSeeker to turn a natural-language sourcing prompt into a ranked list of companies. It is the main discovery endpoint for prospecting, lead generation, market mapping, and investor research workflows.

You can combine a free-text query with structured filters, and the response comes back in the standard v2 envelope with interpreted search metadata. That makes it a good fit for both UI search experiences and backend pipelines that need consistent pagination, filtering, and auditability.

Method
POST
Path
/api/v2/searches
Content-Type
application/json
Credits
1 per request

Search Result Cap

The `limit` field on `/api/v2/searches` is capped at `50`. Requests above `50` are rejected with `400 BAD_REQUEST`.

Request Shape

{
  "request_id": "search-v2-demo-1",
  "query": "AI startups helping ecommerce teams with demand forecasting",
  "limit": 10,
  "filters": {
    "foundedYear": {
      "min": 2020
    },
    "funding": {
      "max": 20000000
    },
    "employees": {
      "min": 10,
      "max": 500
    },
    "score": {
      "min": 7.5
    },
    "countries": {
      "include": ["US", "CA"]
    },
    "industries": {
      "values": ["retail", "logistics"],
      "operator": "OR"
    },
    "websites": {
      "exclude": ["example.com"]
    }
  }
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
querystringYesSearch query. Must be between 3 and 500 characters.
limitnumber | nullNoOptional result cap between 1 and 50. Defaults to 25.
filtersobject | nullNoOptional structured filter object passed into the main search pipeline. Unknown keys are rejected.
filters.foundedYear{ min?: number | null; max?: number | null; includeMissing?: boolean }NoFilter by founded year. Use `includeMissing: true` to also include companies with unknown founded year.
filters.funding{ min?: number | null; max?: number | null }NoFilter by total funding in USD.
filters.employees{ min?: number | null; max?: number | null }NoFilter by LinkedIn employee count.
filters.followers{ min?: number | null; max?: number | null }NoFilter by LinkedIn follower count.
filters.score{ min?: number | null; max?: number | null }NoFilter by StartupSeeker score on the 0-10 scale.
filters.countries{ include?: string[]; exclude?: string[] }NoInclude or exclude ISO-2 country codes such as `US`, `DE`, or `FR`.
filters.citiesstring[]NoRestrict results to one or more city names.
filters.regionsstring[]NoRestrict results to one or more region, state, or province names.
filters.industries{ values: string[]; operator?: "AND" | "OR" }NoMatch one or more normalized industry/category labels. `OR` is the default when omitted.
filters.lists{ include?: uuid[]; exclude?: uuid[] }NoInclude or exclude companies that belong to your saved lists by StartupSeeker list ID.
filters.websites{ include?: string[]; exclude?: string[] }NoInclude or exclude specific company domains. Domains are normalized before matching.

Response Fields

NameTypeRequiredDescription
data.querystringNoEchoes the final query used for the search.
data.total_resultsnumberNoNumber of returned results.
data.resultsarray<object>NoStructured company results.
data.active_filtersobjectNoResolved filters after query interpretation. This can include any supported filter key plus `semanticQuery`.
data.active_filters.semanticQuerystringNoSemantic query text actually used after the refinement stage.
data.requestobjectNoRequest metadata emitted by the search service.
metaobjectNoStandard v2 metadata envelope with request ID, duration, rate-limit state, and credits.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/searches \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "search-v2-demo-1",
    "query": "AI startups helping ecommerce teams with demand forecasting",
    "limit": 10,
    "filters": {
      "foundedYear": { "min": 2020 },
      "funding": { "max": 20000000 },
      "employees": { "min": 10, "max": 500 },
      "score": { "min": 7.5 },
      "countries": { "include": ["US", "CA"] },
      "industries": { "values": ["retail", "logistics"], "operator": "OR" }
    }
  }'

Sample Response

{
  "data": {
    "query": "AI startups helping ecommerce teams with demand forecasting",
    "total_results": 2,
    "results": [
      {
        "primary_key": "458861125484422704",
        "name": "Euphya",
        "website": "euphya.co"
      }
    ],
    "active_filters": {
      "foundedYear": {
        "min": 2020
      },
      "funding": {
        "max": 20000000
      },
      "employees": {
        "min": 10,
        "max": 500
      },
      "score": {
        "min": 7.5
      },
      "countries": {
        "include": ["US", "CA"]
      },
      "industries": {
        "values": ["retail", "logistics"],
        "operator": "OR"
      },
      "semanticQuery": "AI startups helping ecommerce teams with demand forecasting"
    },
    "request": {
      "duration": 1420
    }
  },
  "meta": {
    "request_id": "search-v2-demo-1",
    "api_version": "v2",
    "duration_ms": 1420,
    "rate_limit": {
      "second": { "limit": 5, "remaining": 4, "reset_at": 1712083200000 },
      "minute": { "limit": 30, "remaining": 29, "reset_at": 1712083200000 },
      "day": { "limit": 100, "remaining": 99, "reset_at": 1712126400000 }
    },
    "credits": {
      "charged": 1,
      "remaining": 99
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-RateLimit-Limit-SecondEffective per-second limit for the key/account.
X-RateLimit-Limit-MinuteEffective per-minute limit for the key/account.
X-RateLimit-Limit-DayEffective per-day limit for the key/account.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTInvalid JSON, invalid `query`, or invalid filter structure.
401UNAUTHORIZEDMissing or invalid API key.
402INSUFFICIENT_CREDITSAPI key is valid but the account has no remaining credits.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected search failure.

Implementation Notes

  • Use this route instead of `/api/v1/search` and `/api/assistant/search` for new integrations.
  • The request `limit` is capped at `50`; values above `50` are rejected with `400 BAD_REQUEST`.
  • Structured filters currently support founded year, funding, employee count, follower count, score, countries, cities, regions, industries, saved lists, and explicit websites.
  • Use ISO-2 country codes in `filters.countries.include` / `exclude`, for example `US`, `DE`, or `FR`.
  • Successful responses always use the v2 `data` + `meta` envelope.
POST/api/v2/company-lookups
Free

Company Lookups

Use this route to check a batch of company websites against the StartupSeeker dataset in a single call. It is the fastest way to power CRM syncs, imports, enrichment queues, and deduplication workflows when you already know the domains you care about.

The API normalizes each submitted website, preserves input order in the response, and returns a per-item match or miss record in `data.companies`. That makes it straightforward to merge the results back into your own systems without losing positional context.

Method
POST
Path
/api/v2/company-lookups
Content-Type
application/json
Credits
0 per request

Request Shape

{
  "request_id": "lookup-batch-demo-1",
  "websites": ["stripe.com", "exa.ai"]
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
websitesarray<string>YesBatch-only input. Supply 1 to 100 company websites or domains.

Response Fields

NameTypeRequiredDescription
data.companiesarray<object>NoOrdered lookup results in the same order as the submitted `websites` array.
data.companies[].submittedstringNoOriginal submitted website string.
data.companies[].normalizedstringNoNormalized domain used for matching.
data.companies[].companyobject | nullNoMatching company record, or `null` when no match exists.
data.companies[].missingbooleanNoConvenience flag indicating whether the company record was missing.
metaobjectNoStandard v2 metadata envelope with rate-limit and credit state.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/company-lookups \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "lookup-batch-demo-1",
    "websites": ["stripe.com", "exa.ai"]
  }'

Sample Response

{
  "data": {
    "companies": [
      {
        "submitted": "stripe.com",
        "normalized": "stripe.com",
        "company": {
          "id": "458861125612149361",
          "name": "Stripe",
          "website": "stripe.com"
        },
        "missing": false
      },
      {
        "submitted": "exa.ai",
        "normalized": "exa.ai",
        "company": null,
        "missing": true
      }
    ]
  },
  "meta": {
    "request_id": "lookup-batch-demo-1",
    "api_version": "v2",
    "duration_ms": 180,
    "credits": { "charged": 0, "remaining": 99 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-RateLimit-Limit-MinuteEffective per-minute limit for the key/account.
X-RateLimit-Limit-DayEffective per-day limit for the key/account.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTInvalid JSON, missing `websites`, empty arrays, arrays longer than 100, or invalid website input.
401UNAUTHORIZEDMissing or invalid API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORWebsite lookup service is not configured or failed.

Implementation Notes

  • Use this route instead of `/api/v1/enrich` for new integrations.
  • This v2 route is batch-only; use `/api/v1/enrich` if you need the legacy single-company response shape.
  • Results preserve input order and duplicates from the submitted `websites` array.
  • A 200 response with `data.companies[].missing: true` is the expected result when StartupSeeker has no matching company.
POST/api/v2/founders
5 credits / request

Founders

Use this route when you want StartupSeeker to identify founders and the current CEO for a company using only its website. It is designed for workflows that want a simpler public contract than the legacy founder route while still benefiting from the existing founder discovery pipeline.

StartupSeeker opportunistically reuses company lookup data to improve the founder run, but a lookup miss does not block execution. The response includes normalized website metadata, optional resolved company context, founding details, and the discovered founder profiles in the standard v2 envelope.

Method
POST
Path
/api/v2/founders
Content-Type
application/json
Credits
5 per request

Request Shape

{
  "request_id": "founders-v2-demo-1",
  "website": "stripe.com"
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
websitestringYesWebsite or domain to analyze for founder discovery.

Response Fields

NameTypeRequiredDescription
data.website.submittedstringNoOriginal submitted website string.
data.website.normalizedstringNoNormalized website used for lookup and pipeline execution.
data.companyobject | nullNoBest-effort company context resolved from existing StartupSeeker lookup data, or `null` when no match exists.
data.company.namestring | nullNoResolved company name when lookup enrichment was available.
data.company.descriptionstring | nullNoResolved company description when available from lookup enrichment.
data.company.resolved_from_lookupbooleanNoAlways `true` when `data.company` is present.
data.founding_detailsobjectNoStructured founding details returned by the founder pipeline.
data.foundersarray<object>NoFounder and CEO records discovered by the pipeline.
metaobjectNoStandard v2 metadata envelope with rate-limit and credit state.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/founders \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "founders-v2-demo-1",
    "website": "stripe.com"
  }'

Sample Response

{
  "data": {
    "website": {
      "submitted": "stripe.com",
      "normalized": "stripe.com"
    },
    "company": {
      "name": "Stripe",
      "description": "Payments infrastructure for internet businesses.",
      "resolved_from_lookup": true
    },
    "founding_details": {
      "year_founded": "2010",
      "location": "San Francisco, United States"
    },
    "founders": [
      {
        "name": "Patrick Collison",
        "role": "Co-founder & CEO",
        "status": "active",
        "linkedin_profile_url": "https://linkedin.com/in/patrickcollison",
        "location": {
          "city": "San Francisco",
          "country": "United States"
        },
        "experience_summary": "- **Stripe**, Co-founder & CEO",
        "education": [],
        "sources": ["https://stripe.com/about"]
      }
    ]
  },
  "meta": {
    "request_id": "founders-v2-demo-1",
    "api_version": "v2",
    "duration_ms": 1520,
    "credits": { "charged": 5, "remaining": 95 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-RateLimit-Limit-MinuteEffective per-minute limit for the key/account.
X-RateLimit-Limit-DayEffective per-day limit for the key/account.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTInvalid JSON or invalid `website` input.
401UNAUTHORIZEDMissing or invalid API key.
402INSUFFICIENT_CREDITSAccount has no remaining API credits.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORFounder discovery failed or insufficient context was available.

Implementation Notes

  • This route accepts only a website in the public v2 contract.
  • StartupSeeker reuses existing company data when available, but still attempts founder discovery when no match exists.
  • Successful responses always use the v2 `data` + `meta` envelope.
POST/api/v2/competitor-analyses
1 credit / request

Competitor Analyses

Use this route when you already know the target company and want StartupSeeker to generate a focused competitor set. Providing a website gives the resolver the strongest signal, while a description can be used as a fallback when no domain is available.

The response includes the resolved company context, the generated search query, and the returned competitors with similarity information. It is designed for product experiences that need explainable comps rather than a generic company search result list.

Method
POST
Path
/api/v2/competitor-analyses
Content-Type
application/json
Credits
1 per request

Request Shape

{
  "request_id": "competitor-v2-demo-1",
  "company": {
    "name": "Acme Analytics",
    "website": "acmeanalytics.com"
  }
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
company.namestring | nullNoOptional company name used to improve resolution.
company.websitestring | nullNoOptional website. Provide this whenever possible.
company.descriptionstring | nullNoOptional description. Required when no website is provided.

Response Fields

NameTypeRequiredDescription
data.companyobjectNoContains the input payload and resolved company context.
data.competitorsarray<object>NoCompetitor matches and AI-generated summaries.
data.total_analyzednumberNoNumber of competitor records returned.
data.search_querystring | nullNoSearch query generated by the competitor analysis service.
metaobjectNoStandard v2 metadata envelope with rate-limit and credit state.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/competitor-analyses \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "company": {
      "name": "Acme Analytics",
      "website": "acmeanalytics.com"
    }
  }'

Sample Response

{
  "data": {
    "company": {
      "input": {
        "name": "Acme Analytics",
        "website": "acmeanalytics.com",
        "description": null
      },
      "resolved": {
        "name": "Acme Analytics",
        "normalized_website": "acmeanalytics.com"
      }
    },
    "competitors": [
      {
        "company": {
          "name": "DataViz Pro",
          "website": "datavizpro.io"
        },
        "similarity_level": "HIGH"
      }
    ],
    "total_analyzed": 1,
    "search_query": "analytics workflow competitors"
  },
  "meta": {
    "request_id": "competitor-v2-demo-1",
    "api_version": "v2",
    "duration_ms": 920,
    "credits": { "charged": 0, "remaining": 99 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-RateLimit-Limit-MinuteEffective per-minute limit for the key/account.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTInvalid JSON or missing both `company.website` and `company.description`.
401UNAUTHORIZEDMissing or invalid API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORCompetitor analysis failed.

Implementation Notes

  • Use this route instead of `/api/v1/competitors` for new integrations.
  • Provide `company.website` whenever possible for the most stable resolution path.
POST/api/v2/vc-backability-checks
Free

VC Backability Checks

Use this route to quickly screen one or more startups for venture-backability. It is intended for fast triage when you want a classification before deciding whether a company deserves deeper manual review or a full research run.

Batch input is supported through `websites`, and `response_detail` lets you choose between a compact verdict-only payload and a fuller response with more supporting output. That makes the same route usable for both high-volume scoring and analyst-facing tooling.

Method
POST
Path
/api/v2/vc-backability-checks
Content-Type
application/json
Credits
0 per request

Request Shape

{
  "request_id": "vc-v2-demo-1",
  "websites": ["runwayml.com", "genei.io"],
  "response_detail": "minimal"
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
websitesarray<string> | nullNoPreferred batch input. Supply one or more websites/domains.
websitestring | nullNoSingle-site shortcut when not using `websites`.
response_detail"minimal" | "full" | nullNoControls whether the response contains full scrape/detail output or a compact verdict set.

Response Fields

NameTypeRequiredDescription
data.countnumberNoNumber of entries returned in `data.results`.
data.resultsarray<object> | objectNoFull or minimal classification payload depending on `response_detail`.
data.results[website].classification"Yes" | "Likely Not"NoMinimal-mode VC backability verdict.
data.results[website].namestring | nullNoMinimal-mode company name when available.
data.results[website].descriptionstring | nullNoMinimal-mode short description (cached) or generated AI description (fresh scrape).
metaobjectNoStandard v2 metadata envelope with rate-limit and credit state.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/vc-backability-checks \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "websites": ["runwayml.com", "genei.io"],
    "response_detail": "minimal"
  }'

Sample Response

{
  "data": {
    "count": 2,
    "results": {
      "runwayml.com": {
        "classification": "Yes",
        "name": "Runway",
        "description": "AI-powered creative tools for generating and editing video and image content."
      },
      "genei.io": {
        "classification": "Likely Not",
        "name": "Genei",
        "description": "Research and note-taking assistant focused on summarization and productivity workflows."
      }
    }
  },
  "meta": {
    "request_id": "vc-v2-demo-1",
    "api_version": "v2",
    "duration_ms": 2140,
    "credits": { "charged": 0, "remaining": 99 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-RateLimit-Limit-MinuteEffective per-minute limit for the key/account.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTRequest omitted both `website` and `websites`, or validation failed.
401UNAUTHORIZEDMissing or invalid API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORRequired scraping configuration is missing or classification failed.

Implementation Notes

  • Use this route instead of `/api/v1/vc-backable-classifier` and `/api/v1/vc-backable-minimum` for new integrations.
  • Choose `response_detail: "minimal"` for a compact verdict payload that still includes `name` and `description`.
GET/api/v2/pitch-deck-jobs
Free

List Pitch Deck Jobs

Use this listing endpoint to recover, inspect, or paginate through pitch-deck jobs created by the current API key. It is mainly operational and helps when a client lost local job state, a webhook was missed, or you need to rebuild a queue view.

The response is intentionally lightweight: each item includes status, timestamps, and relative poll/result URLs. You can resume tracking existing jobs without re-uploading the original deck.

Method
GET
Path
/api/v2/pitch-deck-jobs
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/pitch-deck-jobs?status=running&limit=10&request_id=pitch-deck-demo-1

Request Fields

NameTypeRequiredDescription
statusqueued | running | succeeded | failedNoOptional status filter.
limitintegerNoOptional page size from 1 to 100. Defaults to `20`.
afterstringNoOptional cursor returned as `data.next_cursor` for pagination.
request_idstringNoOptional exact-match filter on the original request ID.
idempotency_keystringNoOptional exact-match filter on the original idempotency key.

Response Fields

NameTypeRequiredDescription
data.jobs[].job_idstringNoJob identifier.
data.jobs[].request_idstring | nullNoOriginal client request ID, when supplied.
data.jobs[].statusstringNoCurrent job lifecycle state.
data.jobs[].created_at / updated_at / completed_atstring | nullNoLifecycle timestamps for the job.
data.jobs[].poll_urlstringNoRelative path for polling job status. Prefix it with your API base URL.
data.jobs[].result_urlstringNoRelative path for retrieving the completed result. Prefix it with your API base URL.
data.next_cursorstring | nullNoOpaque cursor for the next page, or `null` when exhausted.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl "https://startup-seeker.com/api/v2/pitch-deck-jobs?status=running&limit=10&request_id=pitch-deck-demo-1" \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "jobs": [
      {
        "job_id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
        "request_id": "pitch-deck-demo-1",
        "status": "running",
        "created_at": "2026-03-14T12:00:00.000Z",
        "updated_at": "2026-03-14T12:00:03.000Z",
        "completed_at": null,
        "poll_url": "/api/v2/pitch-deck-jobs/3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
        "result_url": "/api/v2/pitch-deck-jobs/3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4/result"
      }
    ],
    "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wMy0xNFQxMjowMDowMy4wMDBaIiwiaWQiOiIzYzZhNjE3Ni0xZjhkLTRlOGQtYjFhMC05YmY5ZDRiNmU3ZDQifQ"
  },
  "meta": {
    "request_id": "8bc6b4b1-0b41-4c1b-b1d8-f1cb11bd1af7",
    "api_version": "v2",
    "duration_ms": 5,
    "credits": { "charged": 0, "remaining": 95 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTQuery parameter validation failed.
401UNAUTHORIZEDMissing or invalid API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected job listing failure.

Implementation Notes

  • Use this route to recover job IDs if the original create response was not persisted client-side.
  • Only jobs owned by the authenticated API key are returned.
  • Use `data.next_cursor` as the `after` parameter to fetch the next page.
  • `poll_url` and `result_url` are relative paths, not absolute URLs.
POST/api/v2/pitch-deck-jobs
5 credits / request

Create Pitch Deck Job

Use this route to upload a PDF pitch deck for asynchronous parsing. StartupSeeker accepts the file, creates a job immediately, and processes the deck in the background instead of holding the request open until extraction is finished.

This is the right entry point when you need structured deck output in production systems. Create the job once, then either poll the paired status/result endpoints or attach a managed webhook endpoint to receive completion events.

Method
POST
Path
/api/v2/pitch-deck-jobs
Content-Type
multipart/form-data
Credits
5 per request

Request Shape

multipart/form-data
- file: <PDF, required>
- request_id: <string, optional>
- webhook_endpoint_id: <uuid, optional>

Request Fields

NameTypeRequiredDescription
fileFileYesPitch deck PDF. Maximum 30 MB.
request_idstring | nullNoOptional client correlation ID.
webhook_endpoint_iduuid | nullNoOptional managed webhook endpoint that receives job completion events.
Idempotency-KeyheaderNoOptional idempotency key. Reusing the same key for the same API key with the same payload returns the existing job instead of charging again.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoCreated or reused job identifier.
data.statusstringNoInitial job status, typically `queued`.
data.poll_urlstringNoRelative path for polling job status. Prefix it with your API base URL.
data.result_urlstringNoRelative path for retrieving the completed result. Prefix it with your API base URL.
meta.jobobjectNoJob metadata mirrored into the standard v2 meta envelope.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/pitch-deck-jobs \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Idempotency-Key: pitch-deck-demo-1" \
  -F "file=@deck.pdf" \
  -F "request_id=pitch-deck-demo-1" \
  -F "webhook_endpoint_id=7c0d1e8b-302d-4d03-b38f-1ce85fa7999d"

Sample Response

{
  "data": {
    "job_id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
    "status": "queued",
    "poll_url": "/api/v2/pitch-deck-jobs/3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
    "result_url": "/api/v2/pitch-deck-jobs/3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4/result"
  },
  "meta": {
    "request_id": "pitch-deck-demo-1",
    "api_version": "v2",
    "duration_ms": 45,
    "credits": { "charged": 5, "remaining": 95 },
    "job": {
      "id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
      "status": "queued"
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
Idempotency-KeyOptional retry-deduplication key. Replays only succeed when the payload matches the original request.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTRequest was not multipart/form-data or no PDF was supplied.
401UNAUTHORIZEDMissing or invalid API key.
402INSUFFICIENT_CREDITSAccount has no remaining API credits.
409IDEMPOTENCY_MISMATCHThe same idempotency key was reused with a different payload.
413FILE_TOO_LARGEUploaded PDF exceeds the 30 MB limit.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected job creation failure.

Implementation Notes

  • Use this route instead of `/api/v1/parse-deck` for new integrations.
  • The upload returns `202 Accepted`; fetch the final deck output from the result endpoint.
  • If the same `Idempotency-Key` is replayed for the same API key with the same payload, StartupSeeker returns the existing job without charging credits again.
  • If the same idempotency key is reused with a different payload, the API returns `409 IDEMPOTENCY_MISMATCH`.
  • If `webhook_endpoint_id` is supplied, StartupSeeker posts signed `api.job.succeeded` or `api.job.failed` events to that endpoint.
GET/api/v2/pitch-deck-jobs/{job_id}
Free

Pitch Deck Job Status

Use this route to monitor a pitch-deck job after creation. It reports lifecycle state, coarse progress, and timing information, but it does not return the parsed deck payload itself.

Poll this endpoint while the job is `queued` or `running`, then switch to the result endpoint once the job reaches `succeeded`. That keeps status checks cheap and keeps the final payload fetch separate from progress monitoring.

Method
GET
Path
/api/v2/pitch-deck-jobs/{job_id}
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/pitch-deck-jobs/{job_id}

Request Fields

NameTypeRequiredDescription
job_idstringYesJob identifier returned by the job creation endpoint.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoJob identifier.
data.job_typestringNoJob type, currently `pitch_deck`.
data.statusstringNoJob lifecycle state: `queued`, `running`, `succeeded`, or `failed`.
data.progressnumberNoCoarse job progress percentage.
data.created_at / updated_at / completed_atstring | nullNoLifecycle timestamps for the job.
meta.jobobjectNoJob metadata mirrored into the standard v2 meta envelope.

Sample Request

curl https://startup-seeker.com/api/v2/pitch-deck-jobs/3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4 \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "job_id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
    "job_type": "pitch_deck",
    "status": "running",
    "progress": 10,
    "created_at": "2026-03-14T12:00:00.000Z",
    "updated_at": "2026-03-14T12:00:03.000Z",
    "completed_at": null
  },
  "meta": {
    "request_id": "2db6b347-f88c-4bb7-92c9-09f0b8d8d74b",
    "api_version": "v2",
    "duration_ms": 9,
    "credits": { "charged": 0, "remaining": 95 },
    "job": {
      "id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
      "status": "running"
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key.
404NOT_FOUNDJob does not exist or is not owned by the requesting API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected job lookup failure.

Implementation Notes

  • Status polling is rate-limited but not credit-charged.
  • Ownership is enforced per API key; one key cannot inspect another key’s jobs.
GET/api/v2/pitch-deck-jobs/{job_id}/result
Free

Pitch Deck Job Result

Use this route only after a pitch-deck job has completed successfully. It returns the final parsed output for the uploaded deck in the standard v2 response envelope.

Clients should treat this as the terminal fetch step in the workflow: `409 JOB_NOT_READY` means the job is still processing, while `422 JOB_FAILED` means the job finished unsuccessfully and should be handled as a terminal error rather than retried blindly.

Method
GET
Path
/api/v2/pitch-deck-jobs/{job_id}/result
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/pitch-deck-jobs/{job_id}/result

Request Fields

NameTypeRequiredDescription
job_idstringYesJob identifier returned by the job creation endpoint.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoJob identifier.
data.statusstringNoFinal job state, typically `succeeded`.
data.resultobjectNoPitch-deck parsing result with slide summaries and markdown.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl https://startup-seeker.com/api/v2/pitch-deck-jobs/3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4/result \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "job_id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
    "status": "succeeded",
    "result": {
      "request_id": "pitch-deck-demo-1",
      "filename": "deck.pdf",
      "total_pages": 12,
      "processed_slides": 12,
      "slides": [],
      "markdown": "## Slide 1..."
    }
  },
  "meta": {
    "request_id": "34db6728-f1af-4f9a-bc78-1d3a0b4e5d44",
    "api_version": "v2",
    "duration_ms": 7,
    "credits": { "charged": 0, "remaining": 95 },
    "job": {
      "id": "3c6a6176-1f8d-4e8d-b1a0-9bf9d4b6e7d4",
      "status": "succeeded"
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key.
404NOT_FOUNDJob does not exist or is not owned by the requesting API key.
409JOB_NOT_READYJob exists but has not completed yet.
422JOB_FAILEDJob reached a failed terminal state; inspect `error.details`.
429RATE_LIMITEDPer-key or per-account quota exceeded.

Implementation Notes

  • The final result endpoint is rate-limited but not credit-charged.
  • Failed jobs return the standard v2 error envelope instead of a success body.
GET/api/v2/deep-research-jobs
Free

List Deep Research Jobs

Use this listing endpoint to recover, inspect, or paginate through deep-research jobs created by the current API key. It is useful for dashboards, webhook reconciliation, support tooling, and any workflow that needs to resume work after losing a job ID.

Each item includes status, timestamps, and relative poll/result URLs rather than the full research payload. That keeps the list endpoint fast while still giving clients everything they need to continue tracking or fetching completed runs.

Method
GET
Path
/api/v2/deep-research-jobs
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/deep-research-jobs?status=succeeded&limit=10&request_id=deep-research-v2-demo-1

Request Fields

NameTypeRequiredDescription
statusqueued | running | succeeded | failedNoOptional status filter.
limitintegerNoOptional page size from 1 to 100. Defaults to `20`.
afterstringNoOptional cursor returned as `data.next_cursor` for pagination.
request_idstringNoOptional exact-match filter on the original request ID.
idempotency_keystringNoOptional exact-match filter on the original idempotency key.

Response Fields

NameTypeRequiredDescription
data.jobs[].job_idstringNoJob identifier.
data.jobs[].request_idstring | nullNoOriginal client request ID, when supplied.
data.jobs[].statusstringNoCurrent job lifecycle state.
data.jobs[].created_at / updated_at / completed_atstring | nullNoLifecycle timestamps for the job.
data.jobs[].poll_urlstringNoRelative path for polling job status. Prefix it with your API base URL.
data.jobs[].result_urlstringNoRelative path for retrieving the completed result. Prefix it with your API base URL.
data.next_cursorstring | nullNoOpaque cursor for the next page, or `null` when exhausted.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl "https://startup-seeker.com/api/v2/deep-research-jobs?status=succeeded&limit=10&request_id=deep-research-v2-demo-1" \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "jobs": [
      {
        "job_id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
        "request_id": "deep-research-v2-demo-1",
        "status": "succeeded",
        "created_at": "2026-03-14T12:10:00.000Z",
        "updated_at": "2026-03-14T12:10:34.000Z",
        "completed_at": "2026-03-14T12:10:34.000Z",
        "poll_url": "/api/v2/deep-research-jobs/d61d9b95-06f8-47a8-a409-77d9ee5756d1",
        "result_url": "/api/v2/deep-research-jobs/d61d9b95-06f8-47a8-a409-77d9ee5756d1/result"
      }
    ],
    "next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wMy0xNFQxMjoxMDozNC4wMDBaIiwiaWQiOiJkNjFkOWI5NS0wNmY4LTQ3YTgtYTQwOS03N2Q5ZWU1NzU2ZDEifQ"
  },
  "meta": {
    "request_id": "ab34fd45-c9fc-4f47-b1de-8db71b3d3ff6",
    "api_version": "v2",
    "duration_ms": 4,
    "credits": { "charged": 0, "remaining": 90 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTQuery parameter validation failed.
401UNAUTHORIZEDMissing or invalid API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected job listing failure.

Implementation Notes

  • Use this route to recover job IDs if the original create response was not persisted client-side.
  • Only jobs owned by the authenticated API key are returned.
  • Use `data.next_cursor` as the `after` parameter to fetch the next page.
  • `poll_url` and `result_url` are relative paths, not absolute URLs.
POST/api/v2/deep-research-jobs
10 credits / request

Create Deep Research Job

Use this route to start StartupSeeker's full deep-research workflow for a company website. The job runs asynchronously because it can combine company resolution, web research, and optional competitor analysis into a heavier report.

You can steer the run with company, location, and analyst context fields, disable competitor analysis when you only need the core company report, and attach a managed webhook for completion events. It is the recommended v2 replacement for the older synchronous deep-research flow.

Method
POST
Path
/api/v2/deep-research-jobs
Content-Type
application/json
Credits
10 per request

Request Shape

{
  "request_id": "deep-research-v2-demo-1",
  "website": "exa.ai",
  "include_competitors": false,
  "company_name": "Exa"
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
websitestringYesWebsite/domain to research.
zilliz_idstring | nullNoOptional existing StartupSeeker record ID.
include_competitorsboolean | nullNoOptional. Defaults to `true`. Set to `false` to skip competitor analysis.
city / country / country_isostring | nullNoOptional location overrides used during the workflow. Use ISO-2 codes such as `US` or `DE` for `country_iso`.
contextstring | nullNoOptional analyst context merged into the deep research workflow.
company_namestring | nullNoOptional company name override.
webhook_endpoint_iduuid | nullNoOptional managed webhook endpoint that receives job completion events.
Idempotency-KeyheaderNoOptional idempotency key. Reusing the same key for the same API key with the same payload returns the existing job instead of charging again.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoCreated or reused job identifier.
data.statusstringNoInitial job status, typically `queued`.
data.poll_urlstringNoRelative path for polling job status. Prefix it with your API base URL.
data.result_urlstringNoRelative path for retrieving the completed result. Prefix it with your API base URL.
meta.jobobjectNoJob metadata mirrored into the standard v2 meta envelope.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/deep-research-jobs \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: deep-research-demo-1" \
  -d '{
    "request_id": "deep-research-v2-demo-1",
    "website": "exa.ai",
    "include_competitors": false,
    "company_name": "Exa",
    "webhook_endpoint_id": "7c0d1e8b-302d-4d03-b38f-1ce85fa7999d"
  }'

Sample Response

{
  "data": {
    "job_id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
    "status": "queued",
    "poll_url": "/api/v2/deep-research-jobs/d61d9b95-06f8-47a8-a409-77d9ee5756d1",
    "result_url": "/api/v2/deep-research-jobs/d61d9b95-06f8-47a8-a409-77d9ee5756d1/result"
  },
  "meta": {
    "request_id": "deep-research-v2-demo-1",
    "api_version": "v2",
    "duration_ms": 38,
    "credits": { "charged": 10, "remaining": 90 },
    "job": {
      "id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
      "status": "queued"
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
Idempotency-KeyOptional retry-deduplication key. Replays only succeed when the payload matches the original request.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTInvalid JSON, missing `website`, or schema validation failed.
401UNAUTHORIZEDMissing or invalid API key.
402INSUFFICIENT_CREDITSAccount has no remaining API credits.
409IDEMPOTENCY_MISMATCHThe same idempotency key was reused with a different payload.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected job creation failure.

Implementation Notes

  • Public API access is API-key-only in v2.
  • The legacy synchronous `/api/deep-research` route remains available as a compatibility layer during migration.
  • If the same `Idempotency-Key` is replayed for the same API key with the same payload, StartupSeeker returns the existing job without charging credits again.
  • If the same idempotency key is reused with a different payload, the API returns `409 IDEMPOTENCY_MISMATCH`.
  • If `webhook_endpoint_id` is supplied, StartupSeeker posts signed `api.job.succeeded` or `api.job.failed` events to that endpoint.
GET/api/v2/webhook-endpoints
Free

List Webhook Endpoints

Use this route to inspect the managed webhook destinations configured for the authenticated account. It is primarily a settings and operations endpoint for building admin screens, selecting a webhook to attach to new jobs, or auditing which URLs are active.

Webhook endpoints are account-scoped resources shared across API keys on the same account. Listing them here gives clients a stable source of truth before creating or deleting endpoints elsewhere in the API.

Method
GET
Path
/api/v2/webhook-endpoints
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/webhook-endpoints

Request Fields

NameTypeRequiredDescription

Response Fields

NameTypeRequiredDescription
data.webhook_endpoints[].webhook_idstringNoWebhook endpoint identifier.
data.webhook_endpoints[].urlstringNoDelivery URL.
data.webhook_endpoints[].labelstring | nullNoOptional human-readable label.
data.webhook_endpoints[].created_at / updated_atstringNoLifecycle timestamps for the webhook endpoint.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl https://startup-seeker.com/api/v2/webhook-endpoints \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "webhook_endpoints": [
      {
        "webhook_id": "7c0d1e8b-302d-4d03-b38f-1ce85fa7999d",
        "url": "https://example.com/startupseeker/webhooks",
        "label": "Production jobs",
        "created_at": "2026-03-14T12:00:00.000Z",
        "updated_at": "2026-03-14T12:00:00.000Z"
      }
    ]
  },
  "meta": {
    "request_id": "b15df4f1-fbd3-4a5f-8249-a22294353106",
    "api_version": "v2",
    "duration_ms": 4,
    "credits": { "charged": 0, "remaining": 90 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected webhook endpoint listing failure.

Implementation Notes

  • Webhook endpoints are account-managed resources shared across API keys on the same account.
  • The signing secret is returned only on creation and is not listed again later.
POST/api/v2/webhook-endpoints
Free

Create Webhook Endpoint

Use this route to register an HTTPS endpoint that should receive signed async job events from StartupSeeker. Once created, the returned `webhook_endpoint_id` can be attached to pitch-deck and deep-research job creation requests.

The signing secret is returned only once when the endpoint is created. Persist it immediately and use it to verify `X-StartupSeeker-Signature` on incoming deliveries before accepting webhook payloads.

Method
POST
Path
/api/v2/webhook-endpoints
Content-Type
application/json
Credits
0 per request

Request Shape

{
  "url": "https://example.com/startupseeker/webhooks",
  "label": "Production jobs"
}

Request Fields

NameTypeRequiredDescription
urlstringYesHTTPS URL that receives job event deliveries.
labelstring | nullNoOptional human-readable label for the endpoint.

Response Fields

NameTypeRequiredDescription
data.webhook_idstringNoWebhook endpoint identifier.
data.urlstringNoDelivery URL.
data.labelstring | nullNoOptional human-readable label.
data.signing_secretstringNoSecret used to verify `X-StartupSeeker-Signature`; returned only once.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl -X POST https://startup-seeker.com/api/v2/webhook-endpoints \
  -H "Authorization: Bearer ssk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/startupseeker/webhooks",
    "label": "Production jobs"
  }'

Sample Response

{
  "data": {
    "webhook_id": "7c0d1e8b-302d-4d03-b38f-1ce85fa7999d",
    "url": "https://example.com/startupseeker/webhooks",
    "label": "Production jobs",
    "signing_secret": "sskwhsec_11d6e95dcbcd19611e59191db79e2bb12309ad6b299f2717",
    "created_at": "2026-03-14T12:00:00.000Z",
    "updated_at": "2026-03-14T12:00:00.000Z"
  },
  "meta": {
    "request_id": "3c6d983e-74e7-4e1f-845c-362cebb41c35",
    "api_version": "v2",
    "duration_ms": 6,
    "credits": { "charged": 0, "remaining": 90 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
400BAD_REQUESTInvalid JSON or invalid webhook URL.
401UNAUTHORIZEDMissing or invalid API key.
409CONFLICTA webhook endpoint with the same URL already exists on the account.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected webhook endpoint creation failure.

Implementation Notes

  • StartupSeeker signs deliveries using `X-StartupSeeker-Signature` and `X-StartupSeeker-Timestamp`.
  • Webhook deliveries are retried with bounded exponential backoff and persisted in the delivery queue.
DELETE/api/v2/webhook-endpoints/{webhook_id}
Free

Delete Webhook Endpoint

Use this route to remove a managed webhook destination that should no longer receive StartupSeeker events. This is the cleanup path for rotated URLs, decommissioned environments, or endpoints that were created by mistake.

Deleting the endpoint stops future deliveries to that URL and removes queued deliveries tied to it. Use the `webhook_id` from the list or create response to target the correct destination.

Method
DELETE
Path
/api/v2/webhook-endpoints/{webhook_id}
Content-Type
application/json
Credits
0 per request

Request Shape

DELETE /api/v2/webhook-endpoints/{webhook_id}

Request Fields

NameTypeRequiredDescription
webhook_idstringYesWebhook endpoint identifier.

Response Fields

NameTypeRequiredDescription
data.webhook_idstringNoDeleted webhook endpoint identifier.
data.deletedbooleanNoAlways `true` on success.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl -X DELETE https://startup-seeker.com/api/v2/webhook-endpoints/7c0d1e8b-302d-4d03-b38f-1ce85fa7999d \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "webhook_id": "7c0d1e8b-302d-4d03-b38f-1ce85fa7999d",
    "deleted": true
  },
  "meta": {
    "request_id": "f3dd0c13-9d18-48db-a06f-f5f8115f8599",
    "api_version": "v2",
    "duration_ms": 4,
    "credits": { "charged": 0, "remaining": 90 }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key.
404NOT_FOUNDWebhook endpoint does not exist or is not owned by the requesting account.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected webhook endpoint deletion failure.

Implementation Notes

  • Deleting a webhook endpoint stops future job deliveries to that URL.
  • Queued deliveries for the deleted endpoint are removed via cascade delete.
GET/api/v2/deep-research-jobs/{job_id}
Free

Deep Research Job Status

Use this route to monitor a deep-research job after creation. It returns lifecycle state, coarse progress, and timestamps so clients can show job progress without downloading the full report body on every poll.

Poll this endpoint while the job is `queued` or `running`, then fetch the final research payload from the result endpoint after the job reaches `succeeded`. Ownership is enforced per API key, so a key can only inspect its own jobs.

Method
GET
Path
/api/v2/deep-research-jobs/{job_id}
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/deep-research-jobs/{job_id}

Request Fields

NameTypeRequiredDescription
job_idstringYesJob identifier returned by the job creation endpoint.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoJob identifier.
data.job_typestringNoJob type, currently `deep_research`.
data.statusstringNoJob lifecycle state: `queued`, `running`, `succeeded`, or `failed`.
data.progressnumberNoCoarse job progress percentage.
data.created_at / updated_at / completed_atstring | nullNoLifecycle timestamps for the job.
meta.jobobjectNoJob metadata mirrored into the standard v2 meta envelope.

Sample Request

curl https://startup-seeker.com/api/v2/deep-research-jobs/d61d9b95-06f8-47a8-a409-77d9ee5756d1 \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "job_id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
    "job_type": "deep_research",
    "status": "running",
    "progress": 10,
    "created_at": "2026-03-14T12:10:00.000Z",
    "updated_at": "2026-03-14T12:10:03.000Z",
    "completed_at": null
  },
  "meta": {
    "request_id": "a924f980-9d20-4b14-b168-d624e6dfb430",
    "api_version": "v2",
    "duration_ms": 6,
    "credits": { "charged": 0, "remaining": 90 },
    "job": {
      "id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
      "status": "running"
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key.
404NOT_FOUNDJob does not exist or is not owned by the requesting API key.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORUnexpected job lookup failure.

Implementation Notes

  • Status polling is rate-limited but not credit-charged.
  • Ownership is enforced per API key; one key cannot inspect another key’s jobs.
GET/api/v2/deep-research-jobs/{job_id}/result
Free

Deep Research Job Result

Use this route to fetch the final output of a completed deep-research job. It returns the assembled research payload once StartupSeeker has finished the workflow.

Treat it as the final step in the async flow: `409 JOB_NOT_READY` means the report is still being generated, while `422 JOB_FAILED` indicates a terminal failure and points clients toward error handling rather than continued polling.

Method
GET
Path
/api/v2/deep-research-jobs/{job_id}/result
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/deep-research-jobs/{job_id}/result

Request Fields

NameTypeRequiredDescription
job_idstringYesJob identifier returned by the job creation endpoint.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoJob identifier.
data.statusstringNoFinal job state, typically `succeeded`.
data.resultobjectNoDeep research workflow result payload.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl https://startup-seeker.com/api/v2/deep-research-jobs/d61d9b95-06f8-47a8-a409-77d9ee5756d1/result \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "job_id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
    "status": "succeeded",
    "result": {
      "success": true,
      "zilliz_id": "458861125612149361",
      "timestamp": "2026-03-14T12:10:34.102Z",
      "data": {
        "deepScrape": {
          "status": "fulfilled",
          "website": "exa.ai"
        }
      }
    }
  },
  "meta": {
    "request_id": "0867f1dc-70b9-4d4a-9b01-0efc8f4d6720",
    "api_version": "v2",
    "duration_ms": 6,
    "credits": { "charged": 0, "remaining": 90 },
    "job": {
      "id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
      "status": "succeeded"
    }
  }
}

Important Headers

HeaderDescription
AuthorizationRequired. `Bearer ssk_live_...` or `ssk_test_...` API key.
X-Credits-RemainingRemaining API credits after the request finalizes.

Common Errors

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid API key.
404NOT_FOUNDJob does not exist or is not owned by the requesting API key.
409JOB_NOT_READYJob exists but has not completed yet.
422JOB_FAILEDJob reached a failed terminal state; inspect `error.details`.
429RATE_LIMITEDPer-key or per-account quota exceeded.

Implementation Notes

  • The final result endpoint is rate-limited but not credit-charged.
  • The embedded `data.result` payload reflects the current deep-research workflow output from the shared processor.

Rate Limits

All public v2 routes use the metered API-key quota model. Long-running workflows differ by transport, not by rate-limit family.

Default API key quota
5/sec
30/min
100/day

Header Behavior

  • Metered API-key routes return `X-RateLimit-*` headers and `X-Credits-Remaining`.
  • Job creation endpoints charge credits; job polling and job result endpoints are rate-limited but use `0` credits.
  • All successful public v2 responses use the `data` + `meta` envelope.

Errors

v2 standardizes public errors around the `error` + `meta` envelope, but you should still branch on route-specific status codes like `JOB_NOT_READY` and `JOB_FAILED`.

Canonical v2 envelope

Public v2 routes return a structured `error` object plus a `meta` object carrying the request ID and API version.

{
  "error": {
    "code": "BAD_REQUEST",
    "message": "Request validation failed.",
    "details": [
      {
        "path": "query",
        "message": "String must contain at least 3 character(s)"
      }
    ]
  },
  "meta": {
    "request_id": "search-v2-demo-1",
    "api_version": "v2"
  }
}

Job-state specific errors

Async job result endpoints use the same envelope, but add route-specific codes like `JOB_NOT_READY` and `JOB_FAILED`.

{
  "error": {
    "code": "JOB_NOT_READY",
    "message": "Job has not completed yet.",
    "details": {
      "job_id": "d61d9b95-06f8-47a8-a409-77d9ee5756d1",
      "status": "running"
    }
  },
  "meta": {
    "request_id": "0867f1dc-70b9-4d4a-9b01-0efc8f4d6720",
    "api_version": "v2"
  }
}

Important caveat

Treat job creation, job polling, and job result endpoints as distinct contracts even though they share the same envelope shape.

StartupSeeker - Startup Search Engine