For developers API v1
Put remote opportunities into your job board, community, or internal tool. One free endpoint, useful filters, and structured JSON.
No signup. No API key. Just a GET request.
/api/v1/jobs?category=programming&limit=1{
"data": [
{
"title": "Senior Frontend Engineer",
"company": {
"name": "Acme Corp"
},
"location": "Remote (Worldwide)",
"type": "Full-time",
"employment_types": [
"FULL_TIME"
],
"employer_job_id": null,
"direct_apply": null
}
],
"pagination": {
"limit": 1,
"offset": 0,
"has_more": true
}
}Choose a category and job type to bring relevant opportunities to your audience.
Find roles by keyword and link members to the full listing and application page.
Work with structured job, company, location, and salary fields in your app or dashboard.
01 / Quickstart
Choose the jobs you want, update the request, then copy an example into your project.
https://remotejobs.org/api/v1/jobscurl --fail 'https://remotejobs.org/api/v1/jobs?category=programming&limit=20&offset=0'JavaScript and Python examples run on your server. Cross-origin browser requests aren’t currently supported.
Open JSON response02 / Query parameters
All parameters are optional. Combine them to narrow your results; active jobs are returned newest first.
| Parameter | Default | How it works |
|---|---|---|
categorystring | All categories | A category slug, such as programming or design. Unknown slugs return an empty page. See available values below. |
typestring | All types | full-time, part-time, contract, or freelance. |
qstring | No search | English full-text search across job titles and descriptions. URL-encode your search terms. |
limitinteger | 20 | Jobs per request, from 1 to 50. |
offsetinteger | 0 | Number of jobs to skip. Use it with limit to fetch the next page. |
generalprogrammingdesignmarketingsalescustomer-supportwritingdata-sciencedevopsproduct-managementhuman-resourcesfinancelegaldentalhealthcarecurriculum-developmenteducationai-machine-learningai-trainingcybersecurityfinancial-crimesehsquality-assurancegraphic-designmedical-recordscomplianceenvironmental-safetycyber-securityfitness-wellnessaccountingpersonal-training03 / Response reference
Each response contains a data array of jobs, a pagination object, and meta with attribution and documentation links.
| Job fields | What to expect |
|---|---|
id, title | A job identifier and the listing title. |
url, apply_url | Both point to the job’s RemoteJobs.org page. Use these links to let readers view the listing and apply. |
company, category | Company name, logo_url, website, and profile url; category name and slug. Logo and website may be null. |
location | The listing’s location text, or null. Remote roles can still have country or region restrictions. |
location_normalization | Versioned geography with ISO country and subdivision codes, allowed and excluded areas, IANA timezone identifiers, original raw wording, and known, partial, unknown, or conflicting status. Bare Remote does not establish worldwide eligibility; working hours and legal eligibility require separate evidence. |
salary_min, salary_max, salary_text | Native pay bounds and formatted pay text. Each bound may independently be null. Amounts are not annualized or converted between currencies. |
salary_currency, salary_period | Recorded currency code and pay period: hour, day, week, month, or year. Either may be null. Compare amounts only when both currency and period are known and match. |
salary_source_text | Retained source pay wording, or null. Missing currency or period stays unknown. |
type, employment_types | type is a summary display label or null when unavailable. employment_types is the complete set of Google JobPosting classifications, or null; full-time and contractor can coexist. Type filters match this set. |
employer_job_id, direct_apply | Employer-issued identifier and verified direct-application classification, or null. A working application URL alone does not establish direct_apply. |
description | Sanitized HTML preserving supported description content, with a RemoteJobs.org application link appended. Apply your own HTML policy when displaying it in your application. |
posted_at | The posting timestamp, returned as an ISO 8601 string. |
is_translated, original_language | Whether the listing was translated, and its original language when recorded. The language may be null. |
{
"data": [
{
"id": "a1b2c3d4-5678-4abc-9012-3456789abcde",
"title": "Senior Frontend Engineer",
"url": "https://remotejobs.org/remote-jobs/senior-frontend-engineer-acme",
"apply_url": "https://remotejobs.org/remote-jobs/senior-frontend-engineer-acme",
"company": {
"name": "Acme Corp",
"logo_url": null,
"website": "https://example.com",
"url": "https://remotejobs.org/companies/acme-corp"
},
"category": {
"name": "Programming",
"slug": "programming"
},
"location": "Remote (Worldwide)",
"salary_min": 120000,
"location_normalization": {
"version": "job-location/1",
"reference_version": "iso-3166@4.4.0",
"raw": "Remote (Worldwide)",
"input": {},
"status": "known",
"scope": "worldwide",
"work_arrangement": "remote",
"allowed_countries": [],
"allowed_subdivisions": [],
"excluded_countries": [],
"excluded_subdivisions": [],
"timezones": [],
"regions": [],
"unresolved": []
},
"salary_max": 160000,
"salary_text": "USD 120,000–160,000/year",
"salary_source_text": "$120,000–$160,000 USD per year",
"salary_currency": "USD",
"salary_period": "year",
"type": "Full-time",
"employment_types": [
"FULL_TIME"
],
"employer_job_id": null,
"direct_apply": null,
"description": "<p>Help us build our next product.</p>\n<p>Apply directly on <a href=\"https://remotejobs.org\">RemoteJobs.org</a>: https://remotejobs.org/remote-jobs/senior-frontend-engineer-acme</p>",
"posted_at": "2026-10-01T09:00:00Z",
"is_translated": false,
"original_language": null
}
],
"pagination": {
"total": 42,
"limit": 1,
"offset": 0,
"has_more": true
},
"meta": {
"powered_by": "RemoteJobs.org",
"url": "https://remotejobs.org",
"docs": "https://remotejobs.org/developers/api"
}
}04 / Pagination
Start with offset=0. Increase it by your page size for each request, keeping the same filters.
?limit=20&offset=0?limit=20&offset=20?limit=20&offset=40Know when to stop. Check pagination.has_more before continuing, and stop if data is empty. pagination.total counts matching listings at request time. If a count cannot be retrieved, the request returns an error. Listings can change between requests; pagination isn’t a fixed snapshot.
05 / Limits & caching
Keep usage below 200 requests per hour per IP address. Rate limiting is best-effort; this is not a guaranteed quota. API and MCP requests are limited separately. Up to 50 jobs can be returned in each request. Cache results in your application and avoid polling on every page view.
Responses are not cached by the endpoint. Listings can change between requests, including while you page through results. Cache a response in your application when repeated requests do not need fresh results.
| Status | Next step |
|---|---|
200 OK | Read data and pagination. An empty data array means there are no jobs on this page. |
400 Invalid request | Send whole numbers for limit and offset. |
429 Rate limited | Wait for the number of seconds in Retry-After before trying again. |
500, 503 Server unavailable | The API couldn’t fetch jobs. Retry later rather than treating the failure as an empty result. |
Rate-limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (a Unix timestamp in seconds).
06 / Attribution
If you display listings from the API, please include a visible link back to RemoteJobs.org and keep the job’s application link intact. Here’s a simple attribution you can use.
<a href="https://remotejobs.org">
Powered by RemoteJobs.org
</a>Use of the API and third-party content is covered by our terms of service.
From an idea to an integration
Start with a request. Get in touch if you need help with a larger integration.