Upwork
Live freelance job postings with the full brief, fixed or hourly budget, required skills and experience level.
/upwork/v1/search1 creditSearch live Upwork jobs by keyword and Upwork's own filters — contract type, experience level, project length, weekly workload, client location, how many people the client has hired, client timezone — plus a posted-within-N-hours cut. Returns title, full description, budget, skills, posting timestamp and coarse client signals for each job, with the total match count.
| Parameter | Allowed / range | Description | |
|---|---|---|---|
| query | optional | — | Keyword to search job titles and descriptions. Omit it to browse the whole open board (109k+ jobs) newest-first. |
| limit = 20 | optional | 1–200 | How many jobs to return (1–200). Upwork serves 50 per page, so anything over 50 costs extra page fetches. |
| offset = 0 | optional | 0–5000 | Skip this many results before returning `limit` (0–5000). |
| job_type | optional | hourly · fixed | Contract type. Accepts both, comma-separated. |
| experience_level | optional | entry · intermediate · expert | Experience level the buyer asked for. Comma-separated for several. |
| duration | optional | week · month · semester · ongoing | Project length: week = less than a month, month = 1–3 months, semester = 3–6 months, ongoing = more than 6 months. The spelled-out labels ('1_to_3_months', 'more_than_6_months') are accepted too. |
| workload | optional | as_needed · full_time | Hours per week: as_needed (under 30) or full_time (30+). |
| client_location | optional | — | Where the CLIENT is: a country ('Germany'), a region ('Europe') or a sub-region ('Northern Europe'). Comma-separated for several. Call `filters` for the exact 263 accepted values. |
| client_hires | optional | 0 · 1-9 · 10- | How many freelancers this client has ever hired: 0 (never hired), 1-9, or 10- (ten or more). |
| timezone | optional | — | Client timezone, as an IANA name. Call `filters` for the 72 values Upwork accepts. |
| skill_uid | optional | — | Require a specific Upwork SKILL, by its numeric uid. Take the uid from any job's `skills_detail[].uid` in a previous response — Upwork publishes no skill directory to a logged-out visitor, so that is where the values come from. Comma-separated for several. |
| sort = relevance | optional | relevance · newest | Result order. `newest` sorts by posting time. |
| posted_within_hours | optional | 1–2160 | Only jobs posted in the last N hours. Upwork gives a logged-out visitor no posted-date filter, so this one is applied by us: the search is forced to newest-first and paging stops at the first job older than the window. `filtered_out` in the response says how many rows the cut removed. |
/upwork/v1/job1 creditEverything Upwork publishes about one job: the full brief, budget (fixed amount or hourly range), category and occupation, skills with mandatory/nice-to-have weighting, experience level, project length in weeks, freelancer requirements (countries, languages, minimum job-success score and hours), how many people have applied, been interviewed and been hired, and the client's history — country, city, timezone, total spend, jobs posted, hires, hours billed, review count, rating and member-since date. Plus Upwork's own list of similar jobs. Note that Upwork withholds a minority of listed jobs from anyone who is not signed in; those return NOT_FOUND. `search` already carries the full brief, budget, skills and posting time for every job, so this endpoint is for the ones you shortlist.
| Parameter | Allowed / range | Description | |
|---|---|---|---|
| id | required | — | The job: its cipher id ('~02…' as `search` returns in `cipher_id`), a full Upwork job URL, or the bare numeric id. |
/upwork/v1/filtersfreeThe exact filter vocabulary Upwork's own job search ships — every accepted client location (263 countries, regions and sub-regions), timezone (72), contract type, experience level, project length, workload and client-hire band. Read straight off the live search page, so it cannot drift from what `search` accepts.
Try in playground →curl -X POST https://api.reefapi.com/upwork/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"python","limit":10}'{
"ok": true,
"data": { /* the result */ },
"meta": {
"latency_ms": 240,
"record_count": 12,
"completeness_pct": 100
},
"error": null
}