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.

v1 API removed

The legacy /api/v1/* API has been removed. Existing v1 API keys were deleted as part of the cutover. Create a new API key and use the v2 endpoints documented here.

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.

VC Backability Jobs

Recover, poll, and fetch results for VC backability batches above 50 websites.

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 `query_mode` lets you force company-name lookup or semantic discovery when you need predictable routing. The response comes back in the standard v2 envelope with interpreted search metadata, making 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",
  "query_mode": "auto",
  "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.
query_mode"auto" | "name" | "discovery" | nullNoOptional routing hint for lexical company-name lookup versus semantic discovery.
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.lastRaisedAge{ operator?: "<" | ">" | "=" | "<=" | ">=" | "between"; value?: number | null; endValue?: number | null; unit?: "months" | "years"; includeMissing?: boolean }NoFilter by relative time since the latest funding round.
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.cityGeonameIdsnumber[] | { include?: number[]; exclude?: number[] }NoRestrict results to canonical GeoNames city IDs, with optional include/exclude semantics.
filters.admin1Codesstring[] | { include?: string[]; exclude?: string[] }NoRestrict results to canonical admin1 codes such as `US-CA`, with optional include/exclude semantics.
filters.regionSlugsstring[] | { include?: string[]; exclude?: string[] }NoRestrict results to canonical metro region slugs such as `sf_bay_area`, with optional include/exclude semantics.
filters.industries{ values: string[]; operator?: "AND" | "OR" }NoMatch one or more normalized industry/category labels. `OR` is the default when omitted.
filters.includedInvestorsDatabaseInvestorFilterOption[]NoRestrict results to startups backed by one or more selected investors.
filters.excludedInvestorsDatabaseInvestorFilterOption[]NoExclude startups backed by one or more selected investors.
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.
data.request.query_mode_requestedstring | nullNoRequested query routing mode, when provided.
data.request.query_mode_resolvedstringNoResolved routing mode used by the search service.
data.request.used_lexical_lookupbooleanNoWhether lexical company-name lookup ran for this request.
data.request.name_match_confidencestring | nullNoPresent when lexical company-name lookup produced a ranked match.
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",
    "query_mode": "auto",
    "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,
      "query_mode_requested": "auto",
      "query_mode_resolved": "discovery",
      "used_lexical_lookup": false,
      "name_match_confidence": null
    }
  },
  "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

  • Legacy v1 search has been removed. Use this v2 route for all public search integrations.
  • The request `limit` is capped at `50`; values above `50` are rejected with `400 BAD_REQUEST`.
  • Use `query_mode: "name"` for exact company-name lookup and `query_mode: "discovery"` to skip lexical name routing.
  • 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 or company names against the StartupSeeker dataset in a single call. It is the fastest way to power CRM syncs, imports, enrichment queues, deduplication workflows, and exact brand-resolution flows without calling separate public endpoints.

The API preserves input order in `data.companies`, normalizes each submitted website or company name, and returns either a direct website hit or ranked lexical name matches. 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",
  "names": ["Stripe", "OpenAI"],
  "limit_per_name": 3
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
websitesarray<string> | nullNoSupply 1 to 100 company websites or domains for direct website/domain lookup.
namesarray<string> | nullNoSupply 1 to 50 company names for lexical company-name lookup.
limit_per_namenumber | nullNoOptional for `names` lookups only. Defaults to 5 and cannot exceed 10.

Response Fields

NameTypeRequiredDescription
data.companiesarray<object>NoOrdered lookup results in the same order as the submitted `websites` or `names` array.
data.companies[].lookup_kind"website" | "name"NoIndicates whether the item came from a website lookup or name lookup branch.
data.companies[].submittedstringNoOriginal submitted website or company name string.
data.companies[].normalizedstringNoNormalized website/domain or normalized company name used for matching.
data.companies[].companyobject | nullNoMatching company record, or `null` when no match exists. For name lookups this mirrors the best match when present.
data.companies[].best_matchobject | nullNoPresent on name lookups. Contains `matched_alias`, `match_type`, `confidence`, `score`, and `company`.
data.companies[].matchesarray<object>NoPresent on name lookups. Ranked lexical candidates for the submitted name.
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",
    "names": ["Stripe", "OpenAI"],
    "limit_per_name": 3
  }'

Sample Response

{
  "data": {
    "companies": [
      {
        "lookup_kind": "name",
        "submitted": "Stripe",
        "normalized": "stripe",
        "company": {
          "id": "458861125612149361",
          "name": "Stripe",
          "website": "stripe.com"
        },
        "best_match": {
          "matched_alias": "Stripe",
          "match_type": "exact",
          "confidence": "high",
          "score": 1000,
          "company": {
            "id": "458861125612149361",
            "name": "Stripe",
            "website": "stripe.com"
          }
        },
        "matches": [
          {
            "matched_alias": "Stripe",
            "match_type": "exact",
            "confidence": "high",
            "score": 1000,
            "company": {
              "id": "458861125612149361",
              "name": "Stripe",
              "website": "stripe.com"
            }
          }
        ],
        "missing": false
      },
      {
        "lookup_kind": "name",
        "submitted": "OpenAI",
        "normalized": "openai",
        "company": null,
        "best_match": null,
        "matches": [],
        "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, providing both `websites` and `names`, providing neither, invalid array sizes, 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

  • Legacy v1 enrich has been removed. Use this v2 batch route for website or company-name lookups.
  • Provide exactly one of `websites` or `names` per request.
  • Results preserve input order and duplicates from the submitted 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.
company_namestring | nullNoOptional company name hint used when canonical lookup metadata is missing.
descriptionstring | nullNoOptional description hint used when canonical lookup metadata is missing.
existing_founding_detailsobject | nullNoOptional founding year/location hints to preserve when evidence is weak.
seed_foundersarray<object> | nullNoOptional structured founder seed inputs.
options.enrich_linkedinbooleanNoOptional. Defaults to `true` so LinkedIn-based person linking stays enabled.
options.debugbooleanNoOptional. Defaults to `false`. When `true`, the response includes founder decision debug data.

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": [
          {
            "company": "Stripe",
            "title": "Co-founder & CEO",
            "duration": ""
          }
        ],
        "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/funding
5 credits / request

Funding

Use this route when you want StartupSeeker to assemble a company funding profile from the funding extraction pipeline while receiving a stable public API contract. It runs the same core funding workflow used internally, then returns the canonicalized funding profile, execution counters, and optional supporting trace in the standard v2 envelope.

The response includes normalized website metadata, total funding summary fields, canonical rounds, linked investors, and source references after persistence. This makes it suitable for CRM enrichment, analyst tooling, and downstream pipelines that need funding data without relying on the legacy `/api/funding` response shape.

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

Request Shape

{
  "request_id": "funding-v2-demo-1",
  "website": "stripe.com",
  "options": {
    "mode": "standard",
    "max_sources": 10
  }
}

Request Fields

NameTypeRequiredDescription
request_idstring | nullNoOptional client correlation ID. Maximum 128 characters.
websitestringYesWebsite or domain to analyze for funding history.
entity_idstring | nullNoOptional canonical startup entity UUID used to improve company-name resolution before the funding run.
options.mode"standard" | "deep" | nullNoOptional execution mode kept for compatibility with the simplified funding pipeline.
options.max_sourcesnumber | nullNoAccepted for compatibility with the simplified funding pipeline.
options.allow_database_onlyboolean | nullNoAccepted for compatibility; ignored by the simplified funding pipeline.
options.include_leadsboolean | nullNoAccepted for compatibility; ignored by the simplified funding pipeline.
options.cost_optimizedboolean | nullNoOptional toggle that switches OpenRouter routing to the price-prioritized provider order (`deepinfra`, `novita`).
options.debugboolean | nullNoOptional flag that includes the internal funding trace in the response.

Response Fields

NameTypeRequiredDescription
data.website.submittedstringNoOriginal submitted website string.
data.website.normalizedstringNoNormalized absolute website URL used by the funding pipeline.
data.profileobjectNoCanonical funding profile loaded after persistence.
data.profile.total_funding_amountnumber | nullNoBest available total funding amount in the profile currency.
data.profile.total_funding_currencystring | nullNoCurrency code for `total_funding_amount`.
data.profile.total_funding_usdnumber | nullNoBest available total funding amount normalized to USD.
data.profile.total_roundsnumber | nullNoBest available count of canonical funding rounds.
data.profile.roundsarray<object>NoCanonical funding rounds with amounts, dates, valuations, investors, linked investors, and sources.
data.profile.rounds[].investors[].role"lead" | "co_lead" | "participant" | "unknown" | nullNoOptional investor role per round. Lead and co-lead roles are present only when explicitly supported by source evidence.
data.profile.linked_investorsarray<object>NoUnique linked investors that could be resolved from the canonical investor graph, including canonical logo URLs when available.
data.profile.total_funding_sourcesarray<object>NoSources supporting the total-funding assertion when available.
data.sourcesarray<object>NoFunding sources cited by the simplified SERP-to-LLM pipeline.
data.countersobjectNoSimplified funding pipeline execution counters.
data.used_custom_contextbooleanNoAlways `false` on the simplified funding route.
data.context_truncatedbooleanNoAlways `false` on the simplified funding route.
data.traceobject | nullNoOnly present when `options.debug` is `true`.
metaobjectNoStandard v2 metadata envelope with rate-limit and credit state.

Sample Request

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

Sample Response

{
  "data": {
    "website": {
      "submitted": "stripe.com",
      "normalized": "https://stripe.com/"
    },
    "profile": {
      "entity_id": "entity-stripe",
      "startup_id": "startup-stripe",
      "canonical_domain": "stripe.com",
      "total_funding_amount": 2200000000,
      "total_funding_currency": "USD",
      "total_funding_usd": 2200000000,
      "total_rounds": 8,
      "latest_round_type": "Series I",
      "latest_round_date": "2023-03-15",
      "total_funding_sources": [
        {
          "url": "https://stripe.com/newsroom",
          "snippet": "Stripe has raised more than $2.2 billion to date."
        }
      ],
      "rounds": [
        {
          "round_id": "round-stripe-series-i",
          "round_type": "Series I",
          "round_variant": null,
          "announced_at": "2023-03-15",
          "date_source": "explicit",
          "closed_at": null,
          "amount_original": 694000000,
          "currency_original": "USD",
          "amount_usd": 694000000,
          "valuation_pre_money_amount_original": null,
          "valuation_pre_money_currency_original": null,
          "valuation_pre_money_usd": null,
          "valuation_post_money_amount_original": 50000000000,
          "valuation_post_money_currency_original": "USD",
          "valuation_post_money_usd": 50000000000,
          "valuation_amount_original": null,
          "valuation_currency_original": null,
          "valuation_usd": null,
          "edited_by_actor_type": null,
          "status": "confirmed",
          "investors": [
            {
              "name": "Thrive Capital",
              "website": null,
              "role": "lead"
            },
            {
              "name": "Founders Fund",
              "website": null,
              "role": "participant"
            }
          ],
          "linked_investors": [],
          "sources": [
            {
              "url": "https://stripe.com/newsroom",
              "snippet": "Thrive Capital led Stripe's latest financing round."
            }
          ]
        }
      ],
      "linked_investors": []
    },
    "sources": [
      {
        "url": "https://stripe.com/newsroom",
        "doc_type": "press_release",
        "about_score": 0.99,
        "scraped": false,
        "windows": 0
      }
    ],
    "counters": {
      "serp_requests": 1,
      "serp_candidates": 12,
      "model_rounds": 6,
      "persisted_events": 3,
      "events": 3,
      "leads": 0
    },
    "used_custom_context": false,
    "context_truncated": false
  },
  "meta": {
    "request_id": "funding-v2-demo-1",
    "api_version": "v2",
    "duration_ms": 2840,
    "credits": { "charged": 5, "remaining": 94 }
  }
}

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, invalid `website`, or invalid funding options.
401UNAUTHORIZEDMissing or invalid API key.
402INSUFFICIENT_CREDITSAccount has no remaining API credits.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORFunding processing or canonical persistence failed unexpectedly.
502BAD_GATEWAYAn upstream funding provider failed.

Implementation Notes

  • This is the preferred public funding endpoint for new integrations.
  • The legacy `/api/funding` route remains available for internal/browser flows and compatibility, but it does not use the standard v2 metadata envelope.
  • Set `options.debug: true` only when you explicitly need the internal funding trace in the response.
  • 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

  • Legacy v1 competitors has been removed. Use this v2 route for public competitor analysis 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, a descriptive payload with short company descriptions, and a fuller response with more supporting output. Requests with 51 to 500 websites return an async job with `poll_url` and `result_url`, while requests with 1 to 50 websites return results synchronously.

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 1-50 websites for a sync response, or 51-500 to create an async job.
websitestring | nullNoSingle-site shortcut when not using `websites`.
response_detail"minimal" | "descriptive" | "full" | nullNoDefaults to `minimal`. Minimal responses omit company descriptions. `descriptive` adds the short company description. `full` adds name, cache metadata, and queue/existing flags. Raw homepage scrape content is never exposed.

Response Fields

NameTypeRequiredDescription
data.countnumberNoNumber of entries returned in `data.results`.
data.resultsarray<object>NoOne item per submitted website, preserving order. Row failures are returned inline with `status: "error"`.
data.summaryobjectNoCounters for row errors, canonical hits, active queue hits, cache hits, and live classifications.
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": [
      {
        "input": "runwayml.com",
        "website": "runwayml.com",
        "status": "classified",
        "classification": "Yes",
        "source": "canonical_startup",
        "error": null
      },
      {
        "input": "genei.io",
        "website": "genei.io",
        "status": "classified",
        "classification": "Likely Not",
        "source": "live_classifier",
        "error": null
      }
    ],
    "summary": {
      "classified": 2,
      "errors": 0,
      "canonical_hits": 1,
      "active_queue_hits": 0,
      "cache_hits": 0,
      "live_classifications": 1
    }
  },
  "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.
Idempotency-KeyOptional for async requests. Reusing the same key with the same payload returns the existing job.
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`, exceeded 500 websites, or validation failed.
401UNAUTHORIZEDMissing or invalid API key.
409IDEMPOTENCY_MISMATCHThe async idempotency key was reused with a different payload.
429RATE_LIMITEDPer-key or per-account quota exceeded.
500INTERNAL_ERRORSystemic API/job failure. Provider failures for individual websites are returned as row errors.

Implementation Notes

  • Legacy v1 VC backability classifier routes have been removed. Use this v2 route for public VC backability checks.
  • Canonical StartupSeeker matches always return `Yes` without scraping. Active post-gate startup enrichment queue matches also return `Yes` and can be reused by upload flows.
  • For 51-500 websites, the POST returns `202` with `poll_url` and `result_url`. Poll `GET /api/v2/vc-backability-checks/{job_id}` and fetch `GET /api/v2/vc-backability-checks/{job_id}/result` when complete.
GET/api/v2/vc-backability-checks
Free

List VC Backability Jobs

Use this listing endpoint to recover VC backability jobs created by the current API key. It is useful when a client did not persist the original `202` response or needs to rebuild a queue view.

Each returned job includes relative `poll_url` and `result_url` values. Prefix those paths with your API base URL, poll while the job is queued or running, and fetch the result once it succeeds.

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

Request Shape

GET /api/v2/vc-backability-checks?status=running&limit=10&request_id=vc-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[].progressnumberNoCoarse job progress percentage.
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/vc-backability-checks?status=running&limit=10&request_id=vc-v2-demo-1" \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "jobs": [
      {
        "job_id": "58466a0d-4a9a-41b2-8753-5d30749c5d4d",
        "request_id": "vc-v2-demo-1",
        "status": "running",
        "progress": 45,
        "created_at": "2026-04-26T01:27:58.625Z",
        "updated_at": "2026-04-26T01:28:03.081Z",
        "completed_at": null,
        "poll_url": "/api/v2/vc-backability-checks/58466a0d-4a9a-41b2-8753-5d30749c5d4d",
        "result_url": "/api/v2/vc-backability-checks/58466a0d-4a9a-41b2-8753-5d30749c5d4d/result"
      }
    ],
    "next_cursor": null
  },
  "meta": {
    "request_id": "4a89ad5a-5d85-4fb6-8cb5-2c8df3b7a4df",
    "api_version": "v2",
    "duration_ms": 8,
    "credits": { "charged": 0, "remaining": 99 }
  }
}

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 202 response was not persisted client-side.
  • Only VC backability jobs owned by the authenticated API key are returned.
  • `poll_url` and `result_url` are relative paths, not absolute URLs.
GET/api/v2/vc-backability-checks/{job_id}
Free

VC Backability Job Status

Use this route to monitor a VC backability batch after a 51 to 500 website request returned `202`. It reports lifecycle state, coarse progress, timestamps, and response metadata without returning the full result body.

Poll this endpoint while the job is `queued` or `running`, then fetch `GET /api/v2/vc-backability-checks/{job_id}/result` after the job reaches `succeeded`.

Method
GET
Path
/api/v2/vc-backability-checks/{job_id}
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/vc-backability-checks/{job_id}

Request Fields

NameTypeRequiredDescription
job_idstringYesJob identifier returned by the async 202 response or list endpoint.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoJob identifier.
data.job_typestringNoJob type, currently `vc_backability_check`.
data.statusstringNoJob lifecycle state: `queued`, `running`, `succeeded`, or `failed`.
data.progressnumberNoCoarse job progress percentage.
data.response_metaobjectNoCounters such as website count, row errors, cache hits, and live classifications.
meta.jobobjectNoJob metadata mirrored into the standard v2 meta envelope.

Sample Request

curl https://startup-seeker.com/api/v2/vc-backability-checks/58466a0d-4a9a-41b2-8753-5d30749c5d4d \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "job_id": "58466a0d-4a9a-41b2-8753-5d30749c5d4d",
    "job_type": "vc_backability_check",
    "status": "running",
    "progress": 45,
    "created_at": "2026-04-26T01:27:58.625Z",
    "updated_at": "2026-04-26T01:28:03.081Z",
    "completed_at": null,
    "response_meta": {
      "endpoint": "/api/v2/vc-backability-checks",
      "website_count": 125,
      "status": "running"
    }
  },
  "meta": {
    "request_id": "2db6b347-f88c-4bb7-92c9-09f0b8d8d74b",
    "api_version": "v2",
    "duration_ms": 9,
    "credits": { "charged": 0, "remaining": 99 },
    "job": {
      "id": "58466a0d-4a9a-41b2-8753-5d30749c5d4d",
      "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.
  • When `data.status` becomes `succeeded`, call `GET /api/v2/vc-backability-checks/{job_id}/result` for the same job ID.
GET/api/v2/vc-backability-checks/{job_id}/result
Free

VC Backability Job Result

Use this route to fetch the final output for an async VC backability batch. The completed result is nested under `data.result` and uses the same `count`, `results`, and `summary` fields as the synchronous response.

`409 JOB_NOT_READY` means the job is still processing. `422 JOB_FAILED` means the batch hit a systemic failure; row-level scrape/classification failures are still returned inside `data.result.results` when the job itself succeeds.

Method
GET
Path
/api/v2/vc-backability-checks/{job_id}/result
Content-Type
application/json
Credits
0 per request

Request Shape

GET /api/v2/vc-backability-checks/{job_id}/result

Request Fields

NameTypeRequiredDescription
job_idstringYesJob identifier returned by the async 202 response or list endpoint.

Response Fields

NameTypeRequiredDescription
data.job_idstringNoJob identifier.
data.statusstringNoFinal job state, typically `succeeded`.
data.result.countnumberNoNumber of submitted entries.
data.result.resultsarray<object>NoOne VC backability row per submitted website, preserving order.
data.result.summaryobjectNoCounters for classified rows, row errors, canonical hits, active queue hits, cache hits, and live classifications.
metaobjectNoStandard v2 metadata envelope.

Sample Request

curl https://startup-seeker.com/api/v2/vc-backability-checks/58466a0d-4a9a-41b2-8753-5d30749c5d4d/result \
  -H "Authorization: Bearer ssk_live_your_api_key"

Sample Response

{
  "data": {
    "job_id": "58466a0d-4a9a-41b2-8753-5d30749c5d4d",
    "status": "succeeded",
    "result": {
      "count": 1,
      "results": [
        {
          "input": "runwayml.com",
          "website": "runwayml.com",
          "status": "classified",
          "classification": "Yes",
          "source": "canonical_startup",
          "error": null
        }
      ],
      "summary": {
        "classified": 1,
        "errors": 0,
        "canonical_hits": 1,
        "active_queue_hits": 0,
        "cache_hits": 0,
        "live_classifications": 0
      }
    }
  },
  "meta": {
    "request_id": "34db6728-f1af-4f9a-bc78-1d3a0b4e5d44",
    "api_version": "v2",
    "duration_ms": 7,
    "credits": { "charged": 0, "remaining": 99 },
    "job": {
      "id": "58466a0d-4a9a-41b2-8753-5d30749c5d4d",
      "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 completed result uses the same `data.count`, `data.results`, and `data.summary` shape as the synchronous 200 response, nested under `data.result`.
  • Raw homepage scrape content is never exposed in async results.
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

  • Legacy v1 parse-deck has been removed. Use this v2 async job route for public pitch-deck parsing 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",
  "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.
city / country / country_isostring | nullNoOptional location overrides used during the workflow. Use ISO-2 codes such as `US` or `DE` for `country_iso`.
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",
    "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 has been removed and now returns `410 Gone` with `/api/v2/deep-research-jobs` as the replacement.
  • 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.