{"version":1,"resources":["https://stablejobs.dev/api/coresignal/job-search","https://stablejobs.dev/api/coresignal/job-collect"],"mppResources":["https://stablejobs.dev/api/coresignal/job-search","https://stablejobs.dev/api/coresignal/job-collect"],"description":"Job search APIs powered by Coresignal, protected by x402 micropayments.","instructions":"# StableJobs API\n> Job search via Coresignal. x402/MPP micropayments (USDC on Base/Solana/Tempo).\n\n## Base URL\nhttps://stablejobs.dev\n\n## Happy path (always follow this order)\n1. POST /api/coresignal/job-search — ALWAYS call this first with filters.\n   Returns up to 20 preview records per page (id, title, location, company_name, created, _score).\n   Check pagination.has_more; if true, repeat the SAME filters with pagination.next_page ($0.10/page).\n   Use preview fields to decide which postings matter. Charged even when jobs is empty. No description/salary/URLs here.\n   When jobs are returned, response includes next.collect — use it for step 2 after picking interesting ids.\n2. POST next.collect (or /api/coresignal/job-collect) — ONLY after job-search, with ids from step 1.\n   Pass { \"ids\": [122854839] } (1–10 ids). $0.20 per id quoted upfront. Returns full records\n   (description, url, salary, seniority, employment_type, etc.).\n\nNever call job-collect without ids from a prior job-search response in the same task.\nDo not guess or invent job ids.\n\n## When to collect\n- Need description, apply URL, salary, or seniority → collect those ids.\n- Only need titles/companies/locations to rank or shortlist → stop after job-search.\n\n## Endpoints\n- POST /api/coresignal/job-search $0.10/page — preview search (call first)\n- POST /api/coresignal/job-collect $0.20/id — full record collect (call second, only for ids you need)\n\n## Pagination (job-search only)\n- page 1–5 (default 1), 20 preview jobs per page, $0.10 per page request.\n- Check pagination.has_more; if true, repeat the SAME filters with pagination.next_page.\n- pagination.total_results is total matches; preview caps at 100 jobs (5 pages).\n- offset/limit/per_page/size are ignored — use page only.\n\n## Job Search Request\nCanonical filters: title, keyword_description, employment_type, location, company_id, company_name, company_domain, company_exact_website, company_professional_network_url, deleted, application_active, country, industry, created_at_gte, created_at_lte, last_updated_gte, last_updated_lte.\n\nAliases are accepted and echoed in normalized: job_title -> title, keywords -> keyword_description, company -> company_name. employment_type values are normalized where possible: full_time/fulltime/Full time -> Full-time; part_time -> Part-time; contract -> Contract; intern -> Internship.\n\nDefaults (schema): application_active=true, deleted=false. Pass application_active:false or deleted:true to include inactive or historical postings.\n\nUnsupported meaningful filters such as remote, salary, salary_min, salary_max, seniority, and experience_level return a free 400 before payment.\n\nDate filters (created_at_*, last_updated_*) use Coresignal format YYYY-MM-DD HH:mm:ss. Date-only strings such as 2026-05-25 are auto-normalized (gte -> 00:00:00, lte -> 23:59:59).\n\nLocation matching is literal to Coresignal data. Prefer broader strings such as \"San Francisco Bay Area\" over \"San Francisco\" when a city-only filter returns no jobs.\n\nExample two-step compose:\nStep 1: { \"job_title\": \"Software Engineer\", \"country\": \"United States\", \"employment_type\": \"full_time\" }\n→ jobs[0].id = 122854839, next.collect = \"/api/coresignal/job-collect\", pagination.has_more may be true\nStep 1b (optional): same filters + { \"page\": 2 } for next 20 previews\nStep 2 (only if full description/URL needed): POST next.collect with { \"ids\": [122854839] }\n"}