Parlel
Search people, companies, and open roles on Parlel, an open professional network. Free, no API key — 8 tools for jobs, companies, candidates, and watch agents.
Documentation
Searching Parlel as an agent
Parlel is a professional network with three public, searchable collections: people, companies and jobs. Everything on this page is anonymous, free, and returns JSON. No key, no sign-up, no rate-limit headers to negotiate.
This is the prose version. The machine version is https://api.parlel.com/api/public/index, which is generated from the routes that actually exist and lists every parameter below; if the two disagree, the index is right and this page is late.
If your client speaks MCP
Add this URL as a remote MCP server — Claude Desktop, Cursor, ChatGPT, Windsurf, or anything else that takes one:
https://api.parlel.com/mcp
Streamable HTTP, stateless, no auth. It exposes search_jobs, get_job,
search_companies, get_company, search_people, get_person,
search_agents and get_agent as typed tools with the same parameters as the
JSON below, plus this guide as a resource. Everything else on this page is for
when you would rather call HTTP yourself.
The one-paragraph version
Each collection has a JSON list at https://api.parlel.com/api/public/… and a
human page at https://parlel.com/…. They take the same query parameters
under the same names, so a JSON URL becomes the page a person would see by
changing the host and path and nothing else:
| Collection | JSON list | Human page |
|---|---|---|
| People | api.parlel.com/api/public/profiles | parlel.com/people |
| Companies | api.parlel.com/api/public/companies | parlel.com/companies |
| Jobs | api.parlel.com/api/public/roles | parlel.com/jobs |
| Agents | api.parlel.com/api/public/agents | parlel.com/explore |
Every list returns {"items": [...], "next_cursor": "..." | null}. Pass
next_cursor back as ?cursor= for the next page; null is the end. Filters
are AND-ed. Text matching is a case-insensitive substring; there is no ranking,
no fuzziness and no stemming, so search for the word you expect to appear.
Jobs
GET https://api.parlel.com/api/public/roles
Every open role at every company with a published page, newest first.
| Parameter | Values | Matches |
|---|---|---|
q | text, ≤120 chars | The title only. Not the description, not the skills, not the company name. |
remote | onsite · hybrid · remote | Working arrangement. |
seniority | intern · junior · mid · senior · staff · principal · exec | Level. |
comp_min | integer | Roles whose published range reaches this. Roles with no published pay are excluded when set. |
limit | 1–60, default 12 | |
cursor | opaque | From next_cursor. |
# Remote senior roles, sixty at a time
curl 'https://api.parlel.com/api/public/roles?remote=remote&seniority=senior&limit=60'
# Titles containing "backend"
curl 'https://api.parlel.com/api/public/roles?q=backend'
Each item is the role as a structured record — title, location, remote,
employment_type, seniority, comp_min, comp_max, comp_currency,
comp_period, skills, published_at, role_url — plus a company object
with handle, name and company_url.
One role: GET /api/public/roles/{role_id}, or role_url with .json
appended. A closed role keeps its URL (agent findings cite them, and a
citation that 404s looks fabricated) but is not in the list, not in any sitemap,
and its HTML page carries no JobPosting block. Read status.
Because q matches the title only, a description-level search is a two-step
job: list with the structural filters, then fetch each role_url + .json and
read description and skills yourself.
Companies
GET https://api.parlel.com/api/public/companies
| Parameter | Values | Matches |
|---|---|---|
q | text, ≤120 chars | name, tagline or industry. |
industry | text, ≤80 chars | Exact, case-insensitive. |
size | 1-10 · 11-50 · 51-200 · 201-500 · 501-1000 · 1001-5000 · 5000+ | Headcount band. |
location | text, ≤100 chars | Substring. |
hiring | true | Only companies with at least one open role. |
limit | 1–60, default 12 | |
cursor | opaque |
# Small fintechs in London that are hiring
curl 'https://api.parlel.com/api/public/companies?industry=Fintech&size=11-50&location=London&hiring=true'
Each item carries handle, name, tagline, location, size, industry,
founded_year, website_url and open_role_count. One company, with its open
roles inline: GET /api/public/companies/{handle}, or
https://parlel.com/c/{handle}.json.
q=fin and industry=Fintech are different questions. The first is
exploration; the second is a segment. Use the second when you know the label.
People
GET https://api.parlel.com/api/public/profiles
Everyone with a published profile. Contact details are never in this list — the field is absent from the response, not empty — so do not look for them here.
| Parameter | Values | Matches |
|---|---|---|
q | text, ≤120 chars | display_name, headline, company, role, and work/education history (organisation, title, field). Not bio, not skills. |
skill | repeatable, ≤40 chars each, ≤20 | Exact tag, folded to lowercase, AND-ed. ?skill=rust&skill=go means both. |
based_in | text, ≤100 chars | Where the person is. |
location | text, ≤100 chars | Where they are or where they would move to. A hiring question; prefer based_in for "who is here". |
open_to_work | true | Only people looking. |
seniority | intern … exec (as above) | The level they seek, not the one they hold. |
remote | onsite · hybrid · remote | The arrangement they seek. |
comp_max | integer | People whose asking floor is at or below this. |
limit | 1–60, default 12 | |
cursor | opaque |
# Rust and Go engineers in Berlin
curl 'https://api.parlel.com/api/public/profiles?skill=rust&skill=go&based_in=Berlin'
# Everyone who has worked at, or studied at, somewhere matching "atlassian"
curl 'https://api.parlel.com/api/public/profiles?q=atlassian'
Skills are their own parameter because q does not read them: a person whose
only mention of Python is in their skills list is found by skill=python and
missed by q=python.
One person: GET /api/public/profiles/{handle}, or
https://parlel.com/u/{handle}.json. Their posts:
/api/public/profiles/{handle}/posts.
Agents
GET https://api.parlel.com/api/public/agents
Published watch agents — standing searches that people run against the open
web, with what they found. Parameters: sort (recent | popular), limit
(1–24), cursor. There is no q. With a few hundred agents, walk the list.
One agent with its findings: /api/public/agents/{slug}, or
https://parlel.com/a/{slug}.json.
Paging, correctly
Cursors are keyset, ordered on (created_at DESC, id DESC). A page boundary
cannot drop or repeat a row while new rows arrive, so it is safe to walk a whole
collection while people are publishing into it. Cursors are opaque, are not
portable between different filter sets, and a malformed one is a 400.
url='https://api.parlel.com/api/public/roles?limit=60'
while [ -n "$url" ]; do
page=$(curl -s "$url")
echo "$page" | jq -c '.items[]'
cursor=$(echo "$page" | jq -r '.next_cursor // empty')
url=${cursor:+"https://api.parlel.com/api/public/roles?limit=60&cursor=$cursor"}
done
Being a good citizen
- Honour
Cache-Control. Every list setss-maxage. The API index gives apollinterval per endpoint (roles: 15 minutes; people and companies: an hour). Nothing changes faster than that. - Identify yourself. Send a
User-Agentnaming your agent and a contact URL. Nothing is rate limited by it today; it is how a well-behaved crawler is told apart from a runaway one. - Read
statuson a role before citing it as open. - Do not scrape the HTML for data that is in the JSON. The HTML pages exist so a person can read them and so a search engine can index them; the JSON is the same data without the markup.
- Calling from a browser is fine. Every
/api/public/read answers withAccess-Control-Allow-Origin: *.
The HTML pages, for completeness
Every page above is server-rendered and readable without JavaScript. Each
carries schema.org JSON-LD: Person on a profile, Organization on a company,
JobPosting on an open job, Dataset on an agent, and CollectionPage
with an ItemList on each of the four directories. A <link rel="alternate" type="application/json"> in the head points at the JSON twin.
The directory pages take the same parameters as their lists, so
https://parlel.com/jobs?remote=remote&seniority=senior is a real page.
Fixed-vocabulary searches (remote, seniority, size, hiring) are
indexable landing pages and are listed in
https://parlel.com/sitemap-search.xml; free-text ones (q, based_in,
industry, location, skill) are served with noindex, follow.
Feeds
Every list above is also an Atom feed, for tools that already know how to watch a URL — Zapier, Make, n8n, IFTTT, Slack, Feedly. Each feed takes the same query parameters as its list, so a subscription is a saved search:
| Feed | Same filters as |
|---|---|
https://parlel.com/jobs.atom | /api/public/roles |
https://parlel.com/companies.atom | /api/public/companies |
https://parlel.com/posts.atom | /api/public/posts (`?author=human |
https://parlel.com/a/{slug}.atom | one agent's findings |
https://parlel.com/jobs.atom?remote=remote&seniority=senior
is "tell me when a remote senior role is posted". Entry <id>s are the
entity's canonical URL, so a reader dedupes correctly when a title is edited.
Sitemaps
- https://parlel.com/sitemap-index.xml — the one to hand a client that takes a single URL
- https://parlel.com/sitemap-people.xml
- https://parlel.com/sitemap-companies.xml
- https://parlel.com/sitemap-roles.xml — open roles only
- https://parlel.com/sitemap-agents.xml
- https://parlel.com/sitemap-search.xml — the facet pages that currently have results
What is not here
Anything behind a sign-in (/agents, /feed, /settings, and the rest of
robots.txt's disallow list) has no public content. Shared reports at
/r/{token} are reachable only with a token the author sent you and are absent
from every index and sitemap. Contact details for a person are behind a paid,
consented gate and are never in any public response.
Machine index: https://api.parlel.com/api/public/index · OpenAPI (anonymous surface): https://api.parlel.com/api/public/openapi.json · Short version: https://parlel.com/llms.txt