Workflows
Six sequences this corpus is for. Each names the calls in order, what to carry from one step to the next, and what it costs — so you can propose the right sequence before writing any code.
One rule runs through all of them: the per-posting tools are feed-scoped. get_job, get_buyer, get_buyer_quality and get_job_score answer only for postings this corpus has already shown you — your own search results and your saved-search matches. Every sequence below therefore starts with a search or a saved search.
Find work worth answering today
Turn a filter into a short list you would actually spend connects on.
| call | carry forward |
|---|---|
1. check_prefilter(prefilter) | matched — if it is 0 or 40,000, fix the filter before spending a search |
2. search_jobs(phrase | filters, limit: 50) | jobs[].upwork_id, and matched to know how much you did not see |
3. get_job_score(upwork_id) per candidate | score plus the breakdown that produced it |
4. get_buyer_quality(upwork_id, ask) on the top few | the verdict AND coverage — read coverage first |
Cost: 1 + 1 + n + m calls. check_prefilter is free of the corpus-question cap; the rest are not.
Score before you qualify. get_job_score is about the posting; get_buyer_quality is about whether the client pays, and it is the expensive judgement.
Survey a market exhaustively
Answer 'show me everything matching X', and know when you are done.
| call | carry forward |
|---|---|
1. search_jobs(phrase: "…", limit: 50) | matched — this is the size of the job; next_cursor |
2. search_jobs(same search, cursor: next_cursor) | the next page; repeat |
3. …until next_cursor is absent | its absence is the only proof the survey is complete |
Cost: ceil(matched / 50) calls. Read matched first: 900 matches is 18 calls against your daily cap.
Do NOT narrow the filter to work around the page size. Narrowing answers a different question, and sub-searches you invent overlap and double-count without telling you.
Qualify one client before spending connects
Decide whether this buyer is worth a proposal, and how much to ask.
| call | carry forward |
|---|---|
1. get_buyer(upwork_id) | company and confidence — below 'high' is a lead, not a fact |
2. get_buyer_quality(upwork_id, ask: 65) | coverage FIRST, then the verdict and ask_vs_record |
Cost: 2 calls.
Both are feed-scoped: they answer for a posting a search or a saved match has already shown you. An id from elsewhere is refused.
Be told instead of asking
Stop polling. Have new matches pushed as they appear.
| call | carry forward |
|---|---|
1. check_prefilter(prefilter) | matched — a filter that catches nothing looks exactly like a quiet market |
2. save_search(name, prefilter, webhook_url) | the slug, and the signing secret — shown ONCE |
3. verify each delivery | X-Moxlade-Signature; see the webhooks page |
Cost: 2 calls, then nothing. Deliveries are not calls and do not touch your caps.
Saving back-fills recent matches, so deliveries start immediately rather than at the next posting.
Decide whether a skill is worth positioning around
Is there demand, and what does it pay?
| call | carry forward |
|---|---|
1. skill_demand(skill, window: "quarter") | trend and per_day — never the raw bucket counts |
2. rate_benchmark(skill, country?) | p25 / median / p75 / p90 of LISTED rates |
Cost: 2 calls.
The newest weekly bucket is always short. Compare per_day, or read trend, which excludes partial weeks. And these are rates freelancers ASK — what buyers paid is get_buyer_quality.
Audit your own agent
Find out what it actually did, and why it stopped.
| call | carry forward |
|---|---|
1. get_plan() | usage — today's calls and distinct questions against their caps |
2. get_activity(limit: 50) | every call with its arguments, and the refusal text when there was one |
Cost: Free. Neither counts against the corpus-question cap.
Refusals are the useful half: a cap being hit looks identical to a broken tool without them.