Coding agent documentation index Fetch the complete documentation index at: https://docs.worklittle.com/docs-agent-manifest.json Use this file to discover all available pages before exploring further.

Search jobs

Search Worklittle's open-role index, paginate results, and fetch enriched job details for agents and job boards.

Overview

Worklittle maintains a market-wide index of millions of open roles, enriched with location, salary, and company data, alongside jobs employers publish on Worklittle. GET /jobs returns discovery rows; GET /jobs/:id returns the full posting. MCP mirrors the same flows with search_jobs and get_job_details.

When to use

If you are building:

A job board or search UI List matching roles with GET /jobs or MCP search_jobs Open detail pages with GET /jobs/:id or get_job_details A career copilot or matching agent Rank listings, then pull keywords with get_job_keywords before resume tailoring A market analytics dashboard * Use GET /jobs/stats or get_market_overview for aggregate counts (not row-level search)

Basic usage

> Tip: Job search is included in the monthly free Jobs API quota (not billed per job returned). Default limit is 20, max 50. Always follow list rows with a detail fetch for full descriptions.

curl -s "https://api.worklittle.com/jobs?q=product+designer&workplace_type=remote&limit=10" \
  -H "Authorization: Bearer $WORKLITTLE_API_KEY"
curl -s "https://api.worklittle.com/jobs/JOB_ID" \
  -H "Authorization: Bearer $WORKLITTLE_API_KEY"

Default detail is raw description_text plus already-cached AI. Pass ?summary=true (MCP get_job_details with summary: true) only when you want a first-time generate.

MCP equivalent: search_jobs then get_job_details with the job_id from results.

Search jobs reference

> Self-contained reference for coding agents using Worklittle job search.

Overview

| Route | Method | Scope | Billing |
| --- | --- | --- | --- |
| `/jobs` | GET | `jobs:read` | Free within monthly quota - [Pricing](/jobs/get-started/pricing) |
| `/jobs/:id` | GET | `jobs:read` | Free within monthly quota |
| `/stats` | GET | `jobs:read` | Free |
| `/jobs/map` | GET | `jobs:read` | Free within monthly company/map quota - see [Search companies](/jobs/api/search-companies) |
| `/jobs/salary-average` | GET | `jobs:read` | **$0.05** per request |

MCP: search_jobs, get_job_details, get_job_keywords, get_market_overview.

List response shape

{
  "data": [
    {
      "id": "…",
      "title": "Senior Product Designer",
      "company": { "name": "Example Co" },
      "apply_url": "https://…",
      "can_apply": true,
      "closed_at": null
    }
  ],
  "meta": { "next_cursor": "…" }
}

List rows are snippets. They do not include the full job_description. Use meta.next_cursor as cursor on the next request.

List rows include closed_at (always null on this endpoint). Search never returns closed jobs and has no closes_at filter. Read closes_at on GET /jobs/:id / get_job_details when you need the ATS deadline. See Closed jobs and eligibility.

Apply: use can_apply (boolean) to decide whether POST /jobs/apply can run for that job. Do not infer from source_name or apply_url. See Apply for jobs.

GET /jobs/:id description_text is plain text, never HTML. ATS headings and <b> become bold, lists become - bullets (nested lists indent with two spaces), and safe <a href> links become [label](url). Bold is display only. Do not treat bold spans as Create Resume keywords. Use keywords / get_job_keywords for that.

Salary average

Aggregate annual compensation for jobs matching a search query. Uses the same filters and negative title tokens as GET /jobs (-Senior in q or title).

curl -s "https://api.worklittle.com/jobs/salary-average?title=Product+Manager,+-Senior,+-Principal,+-Lead,+-Staff,+-Director,+-Group&workplace_type=remote&country=US" \
  -H "Authorization: Bearer $WORKLITTLE_API_KEY"
| Parameter | What it does |
| --- | --- |
| `q` or `title` | **Required.** Role query; comma-separated OR phrases; `-token` exclusions (`-Senior` also matches Sr./Sr titles) |
| `currency` | ISO 4217 code for salary rows included in the average (default `USD`) |
| `location`, `company`, `workplace_type`, etc. | Same filters as [Common filters](#common-filters) |

Response data includes matching_jobs, jobs_with_salary, jobs_in_average, average_salary, salary_min, and salary_max (annual amounts in currency). Only jobs with annualized pay between $30k and $1M are included in the average (mis-parsed or extreme outliers are excluded). Hourly and monthly postings are annualized before averaging. $0.05 per request - see Pricing.

Common filters

| Parameter | What it does |
| --- | --- |
| `q` | Title or company text match |
| `title` | Title-only match (comma-separated). Prefix `-` to exclude title substrings - `-Senior` also excludes **Sr.** / **Sr** titles; same for `-Principal`, `-Lead`, `-Staff`, `-Director`, `-Executive`, `-VP`, `-Head`, `-Chief`, `-Group` |
| `location`, `location_or` | Location filters |
| `company` | Company slug(s). Bare = include OR (`stripe` or `meta,google`). Prefix `-` to exclude (`-lucid-motors,-tesla`). Same leading-dash rule as title negatives, but employers stay in `company` |
| `employment_type`, `workplace_type`, `seniority_level` | Structured filters. `employment_type` and `seniority_level` accept comma-separated values (OR / SQL `IN`), e.g. `full_time,part_time` or `internship,entry,new_grad` |
| `posted_within_days` | Optional rolling lookback in days. `0` = no cutoff. Omit = no cutoff on REST (including `company=`). Chat/MCP tools default to **14** when the model omits it. |
| `since` | Unix timestamp lower bound (wins over `posted_within_days` when both set) |
| `limit`, `cursor` | Pagination (max 50) |

Agent REST tools

| Method | Path | Purpose |
| --- | --- | --- |
| GET | `/v1/agent/tools` | List REST agent tools and JSON schemas |
| POST | `/v1/agent/tool` | Run `search_jobs`, `get_job_details`, `create_resume`, or `create_cover_letter` (legacy wrapper) |

Requires agent:tools scope. Prefer POST /jobs/resumes and POST /jobs/cover-letters for documents. Full ATS is on MCP.

Common mistakes

| Wrong | Correct |
| --- | --- |
| Using list `job_summary` as the full JD | Call `GET /jobs/:id` or `get_job_details` |
| Ignoring pagination | Pass `cursor` until `meta.next_cursor` is null |
| Expecting hosted apply on every `job_id` | Some indexed roles use an employer `apply_url`; hosted apply is [Apply for jobs](/jobs/api/apply-for-jobs) |

Patterns and gotchas

MCP/chat recency - posted_within_days: today > 1, this week > 7, vague new/recent > 14; omit defaults to 14 in tools; 0 = any age. Never put those words in query. Company lists - GET /jobs?company= returns all open roles when recency is omitted. Pass posted_within_days or since only when you want a lookback window. First detail fetch may enrich - AI enrichment runs once; later reads are cached. Keywords for tailoring - get_job_keywords strips prose; better input for create_resume / create_cover_letter. * Pair with apply - After get_job_details, use submit_job_application for Worklittle-hosted roles.