startup APIstartup.jobs ↗
Search startup job listings on startup.jobs by keyword, location, workplace type, and employment type. Returns roles, facets, and geo-resolved place data.
What is the startup API?
The startup.jobs API exposes a single search_jobs endpoint that returns up to 25 job listings per page from startup.jobs, along with a total result count, facet breakdowns by employment type and workplace arrangement, and a geo-resolved location object. Each role record includes the job ID, title, company name, company slug, logo URL, location string, country, and more — giving developers structured access to startup-focused job data with keyword and geographic filtering.
curl -X GET 'https://api.parse.bot/scraper/f28a8cab-fc8e-475d-b453-09db63ed6517/search_jobs?query=engineer&location=Netherlands' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace startup-jobs-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: startup_jobs_api SDK — search startup job listings with filters."""
from parse_apis.startup_jobs_api import StartupJobs, WorkplaceType, Since, InputFormatInvalid
client = StartupJobs()
# Paginated search: find remote engineering jobs posted in the last 30 days.
for job in client.jobs.search(
query="engineer",
location="Netherlands",
workplace_type=WorkplaceType.REMOTE,
since=Since.LAST_30_DAYS,
limit=5,
):
print(job.title, "-", job.company_name, f"({job.location})")
print(f" type: {job.employment_type} tags: {job.tags}")
# Scalar wrapper: inspect facets and resolved location for the same search.
overview = client.job_searches.search(query="engineer", location="Netherlands")
print(f"\nTotal results: {overview.total_results} Pages: {overview.total_pages}")
if overview.location_resolved is not None:
loc = overview.location_resolved
print(f"Resolved to: {loc.name} ({loc.latitude}, {loc.longitude})")
print("Workplace facets:", overview.facets.workplace_type)
print("Employment facets:", overview.facets.employment_type)
# Drill into a single result from the paginated search.
first_job = client.jobs.search(query="data", location="Amsterdam", limit=1).first()
if first_job is not None:
print(f"\nFirst hit: {first_job.title} at {first_job.company_name}")
print(f" Published: {first_job.published_at} URL: {first_job.url}")
# Typed error: invalid filter values produce InputFormatInvalid (422).
try:
client.job_searches.search(query="engineer", workplace_type="bogus")
except InputFormatInvalid as e:
print(f"\nExpected error: {e.message}")
print("\nexercised: jobs.search / job_searches.search / InputFormatInvalid")
Searches job listings by keyword and/or location and returns one page of 25 matching roles ordered by relevance, plus the total match count, facet counts, and the resolved place. At least one of query or location must be given. A location is free text (country, region or city); it is resolved to the site's best-matching place and the search is limited to roles within 100 km of that place's centre, exactly as the site does — location_resolved reports what was matched (name, context, coordinates, radius_km). An unrecognised location yields an empty result set with location_resolved null rather than an unfiltered search. Pagination is page-based: page defaults to 1, total_pages and has_more describe the continuation, and the site exposes at most 20 pages (500 roles) per search, so narrow the search when total_results exceeds that. Filters workplace_type, employment_type and since are optional and combine. facets contains the per-value role counts for the current search. Each role carries job_id, title, company, location, country, workplace_type, employment_type, tags, published_at (ISO 8601 UTC) and the listing url. Invalid filter values or a non-positive page return a 422.
| Param | Type | Description |
|---|---|---|
| page | integer | 1-based result page of 25 roles; pages beyond total_pages return an empty results array. |
| query | string | Free-text search over job titles, skills and company names. Required when location is omitted. |
| since | string | Only roles published within this rolling window ending now. Omitted = any time. |
| location | string | Free-text place name (country, region or city) resolved to the site's best-matching place; roles within 100 km of its centre are returned. Required when query is omitted. |
| workplace_type | string | Restrict to one workplace arrangement. Omitted = all. |
| employment_type | string | Restrict to one employment type. Omitted = all. |
{
"type": "object",
"fields": {
"page": "integer, the 1-based page returned",
"query": "echo of the keyword searched (empty string when omitted)",
"facets": "object with employment_type and workplace_type maps of value -> role count for the current search",
"results": "array of role records: job_id, title, company_name, company_slug, company_logo_url, location, country (null when the listing has no location), workplace_type, employment_type, tags (array of strings), published_at, url",
"has_more": "boolean, true when a further page exists",
"location": "echo of the location text searched (empty string when omitted)",
"total_pages": "integer, number of pages the site exposes for this search (max 20)",
"total_results": "integer, total matching roles reported by the site",
"location_resolved": "object with the matched place's id, name, context (parent place or null), latitude, longitude and radius_km; null when no location was given or it could not be resolved"
},
"sample": {
"data": {
"page": 1,
"query": "engineer",
"facets": {
"workplace_type": {
"hybrid": 262,
"remote": 108,
"on-site": 487
},
"employment_type": {
"full-time": 836,
"contractor": 11,
"internship": 10
}
},
"results": [
{
"url": "https://startup.jobs/sales-engineer-eu-onlogic-8768699",
"tags": [
"Engineer",
"Sales"
],
"title": "Sales Engineer - EU",
"job_id": "8768699",
"country": "Netherlands",
"location": "Oosterhout, Netherlands",
"company_name": "OnLogic",
"company_slug": "onlogic",
"published_at": "2026-07-17T00:00:00Z",
"workplace_type": "on-site",
"employment_type": "full-time",
"company_logo_url": "https://startup.jobs/logos/19303"
}
],
"has_more": true,
"location": "Netherlands",
"total_pages": 20,
"total_results": 857,
"location_resolved": {
"id": "NLD",
"name": "Netherlands",
"context": null,
"latitude": 51.66720947847681,
"longitude": 4.876495757450328,
"radius_km": 100
}
},
"status": "success"
}
}About the startup API
What the API Returns
The search_jobs endpoint accepts a free-text query (searching over job titles, skills, and company names) and/or a location string (country, region, or city). At least one of the two must be provided. Each response page contains up to 25 role records, each carrying fields including job_id, title, company_name, company_slug, company_logo_url, location, and country (which may be null when the listing omits country data). The response also includes total_results, total_pages (capped at 20), has_more, and echoed query and location fields.
Filtering and Facets
Results can be narrowed using workplace_type (e.g., remote, on-site, hybrid) and employment_type (e.g., full-time, contract) parameters. Omitting either returns all arrangements. The since parameter restricts results to roles published within a rolling time window ending at request time — useful for monitoring fresh listings. The facets object in every response provides counts of matching roles broken down by employment_type and workplace_type for the active search, which is useful for building filter UIs or aggregating market data.
Location Resolution
When a location is supplied, the API resolves it to the site's best-matching geographic place and returns a location_resolved object containing the matched place's id, name, context (parent region or null), latitude, longitude, and radius_km. Roles within 100 km of that resolved point are included. When no location can be resolved, location_resolved is null. Pagination uses a 1-based page parameter; requesting a page beyond total_pages returns an empty results array.
Pagination Behavior
The API uses page-based pagination with 25 results per page. The maximum number of pages the source exposes for any search is 20, meaning up to 500 role records are reachable per query. The has_more boolean tells you whether an additional page exists, and total_results reflects the full match count as reported by the site — which may exceed the 500 reachable records.
The startup API is a managed, monitored endpoint for startup.jobs — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when startup.jobs changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official startup.jobs API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Aggregate Netherlands or other region-specific startup job listings using the
locationparameter for geo-targeted job boards. - Track newly posted remote roles by combining
workplace_typewith thesincefilter to surface fresh listings. - Build employer research tools using
company_name,company_slug, andcompany_logo_urlfields returned per role. - Analyze supply of contract vs. full-time startup roles using
facets.employment_typecounts across searches. - Monitor keyword-based job trends (e.g., 'machine learning' or 'Series A') by querying the
queryparameter and recordingtotal_resultsover time. - Power a job alert system by polling
search_jobswith asincewindow and comparing newjob_idvalues against previously seen ones. - Enrich a startup database with open role counts per company by querying
company_nameas the keyword and readingtotal_results.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does startup.jobs have an official developer API?+
What does the search_jobs endpoint return for each role?+
job_id, title, company_name, company_slug, company_logo_url, location, and country (null when the listing omits it). The response also carries total_results, total_pages, has_more, a facets object with employment and workplace type breakdowns, and a location_resolved object with the matched place's coordinates and radius when a location was searched.How far back can the `since` filter look for job postings?+
since parameter defines a rolling window ending at the current request time, so it filters by recency relative to when you call the endpoint. The API documentation does not specify an absolute oldest supported date; very long windows may return the same results as omitting the parameter entirely.Can I retrieve the full job description or application URL for a listing?+
search_jobs endpoint returns summary-level role data — title, company, location, and identifiers — but not the full job description text, application link, or salary information. You can fork this API on Parse and revise it to add a job detail endpoint that fetches those fields.Is pagination limited to 500 results per search?+
total_results field may report a larger match count than that, reflecting the full set on the site. To cover more roles, you can narrow searches using query, location, or filter parameters to bring the result set within the 500-record window. You can also fork this API on Parse and revise pagination behavior if your use case requires deeper access.