Developer Resources
1. Quick Start
This page is the practical companion to the Job API Overview and Job Data Overview. It focuses on working code rather than reference tables. The three steps below get you from zero to a parsed job posting in no time.
1.1 Get an API Key
- Create an account: Sign up at rapidapi.com/auth/sign-up - no credit card required.
- Subscribe to the Basic plan: Open the Job Postings API pricing page and subscribe to the Basic plan. It is free and includes 100 free requests (1000 job postings) per month.
- Copy your API key: Your key appears in the RapidAPI dashboard after subscribing. Pass it as
Authorization: Bearer <your-api-key>in every request header.
1.2 Make Your First Request
Fetch the first page of US software jobs for last month with cURL:
curl -X GET \
"https://daily-international-job-postings.p.rapidapi.com/api/v2/jobs/search?dateCreated=2026-05&countryCode=us&page=1" \
-H "Authorization: Bearer <your-api-key>"The same request in Python:
import requests
URL = "https://daily-international-job-postings.p.rapidapi.com/api/v2/jobs/search"
HEADERS = {"Authorization": "Bearer <your-api-key>"}
resp = requests.get(URL, headers=HEADERS, params={
"dateCreated": "2026-05",
"countryCode": "us",
"page": 1,
})
resp.raise_for_status()
data = resp.json()
print(f"Total matching jobs: {data['totalCount']}")
for job in data["result"]:
print(job["title"], "-", job.get("company", ""), "-", job.get("city", ""))
1.3 Parse the Result
The response has a metadata envelope and a result array. Each element is a job object whose full posting text lives in jsonLD.description as Markdown. The jsonLD object is a valid schema.org JobPosting and can be embedded directly in a webpage for structured data markup.
{
"api": "Techmap.io Job Posting API",
"totalCount": 48231,
"page": 1,
"pageSize": 10,
"result": [
{
"title": "Senior Data Engineer",
"company": "Example Corp",
"city": "Austin",
"countryCode": "us",
"dateCreated": "2026-05-10T09:00:00.000Z",
"language": "en",
"industry": "IT",
"workPlace": ["Hybrid"],
"careerLevel": ["Senior"],
"hasSalary": true,
"minSalary": 140000,
"skills": ["Python", "Spark", "dbt", "Airflow"],
"isDirect": true,
"isRecruiter": false,
"portal": "linkedin",
"source": "linkedin_us",
"jsonLD": {
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Senior Data Engineer",
"description": "## About the Role\n\nWe are looking for ...",
"url": "https://example.com/jobs/456",
"datePosted": "2026-05-10"
}
}
]
}2. API Reference
The Job Postings API is hosted on RapidAPI. The full OpenAPI definition is at api.techmap.io/jobs-api. Every request requires the Authorization: Bearer <your-api-key> header.
2.1 Endpoints
| Path | Description | Plan |
|---|---|---|
/api/v2/jobs/search | Returns up to 10 job postings per page matching the query. | All plans |
/api/v2/jobs/count | Returns the total count for a query without fetching job data. Use this to size a result set before paginating - it does not consume job-fetch quota. | All plans |
/api/v2/meta/jobs/distinct | Returns all distinct values and their job counts for a given field over the last 30 days. Capped at 500 values. Useful for building filter UIs or discovering valid field values. | PRO, ULTRA, MEGA |
/api/v2/meta/jobs/statistics | Returns statistical summaries (total count, coverage, relative and absolute percentages) per distinct value for a given field over the last 30 days. Capped at 100 values. | PRO, ULTRA, MEGA |
Base host for all endpoints: https://daily-international-job-postings.p.rapidapi.com
Distinct and statistics examples
All distinct industry values in the last 30 days:
curl -X GET \
"https://daily-international-job-postings.p.rapidapi.com/api/v2/meta/jobs/distinct?field=industry" \
-H "Authorization: Bearer <your-api-key>"Statistics for workPlace (remote / hybrid / onsite split):
curl -X GET \
"https://daily-international-job-postings.p.rapidapi.com/api/v2/meta/jobs/statistics?field=workPlace" \
-H "Authorization: Bearer <your-api-key>"Valid field values for both endpoints: city, company, contractType, countryCode, department, industry, language, locale, occupation, skills, state, timezone, workPlace, workType, careerLevel.
2.2 Query Parameters
dateCreated is omitted, the API defaults to today minus 2 days - always set it explicitly in production. If page is omitted, the API defaults to 1.Parameters marked search only are not available on /count.
| Parameter | Type | Description | Example |
|---|---|---|---|
dateCreated | String | YYYY-MM for a full month or YYYY-MM-DD for a specific day. Defaults to today-2 if omitted. | dateCreated=2026-05 |
dateCreatedMin | String | Start of a date range (YYYY-MM-DD). Use with dateCreatedMax. Cannot be combined with dateCreated. | dateCreatedMin=2026-05-01 |
dateCreatedMax | String | End of a date range. Use with dateCreatedMin. | dateCreatedMax=2026-06-06 |
page | Integer | Page number starting at 1. Max ~1000 pages (~10000 results). Use cursor pagination for larger sets. (search only) | page=2 |
cursor | String | Pass true to start cursor-based pagination; pass the nextCursor value from the response for subsequent pages. Cannot be combined with page. (search only) | cursor=true |
format | String | Output format. Default: json. Options: json, csv, rss, atom, xml, parquet. (search only) | format=csv |
countryCode | String | ISO 3166-1 alpha-2 country code. See the country list for all supported codes. | countryCode=de |
city | String | City of the job location, as stated in the posting. Use quotes for multi-word cities. | city="New York" |
state | String | State or region. Free text as stated in the posting. Sparsely populated. | state=TX |
postCode | String | Postal or ZIP code. Sparsely populated. | postCode=10001 |
timezone | String | 3-letter IANA timezone code. | timezone=CET |
timezoneMin | Integer | Minimum UTC offset (-12 to 11). Use with timezoneMax to define a range. | timezoneMin=-8 |
timezoneMax | Integer | Maximum UTC offset (-11 to 12). Must be greater than timezoneMin. | timezoneMax=-5 |
geoPointLat | Number | Latitude (WGS84, -90 to +90) for a geo distance search. Use with geoPointLng and geoDistance. | geoPointLat=37.757 |
geoPointLng | Number | Longitude (WGS84, -180 to +180) for a geo distance search. | geoPointLng=-122.449 |
geoDistance | String | Radius around the geo point. Defaults to 10 km. Units: km or mi. | geoDistance=50mi |
geoTopLeftLat | Number | Latitude of the Top-left corner of a bounding box. Cannot be combined with geo distance search. | geoTopLeftLat=52.5 |
geoTopLeftLng | Number | Longitude of the Top-left corner of a bounding box. Cannot be combined with geo distance search. | geoTopLeftLng=5.5 |
geoBottomRightLat | Number | Latitiude of the Bottom-right corner of a bounding box. | geoBottomRightLat=48.0 |
geoBottomRightLng | Number | Longitude of the Bottom-right corner of a bounding box. | geoBottomRightLng=8.0 |
title | String | Free-text search within the job title. Supports boolean operators. | title="data engineer" |
skills | String | Skills, technologies, or tags. Comma-separated for OR logic. | skills=Python,Spark |
company | String | Hiring or recruiting company name. Supports boolean operators. | company=Microsoft |
occupation | String | Normalized occupation stem extracted from the job title. programmer matches all software developer variants; java programmer narrows further. | occupation=programmer |
industry | String | Industry classification. Values include: software, healthcare, finance, automotive, logistics, consulting, education, and more. Use /distinct?field=industry to get all active values. | industry=healthcare |
department | String | Department. Values: it, sales, hr, finance, marketing, legal, tax. Sparsely populated. | department=it |
language | String | ISO 639-1 language code of the posting text. | language=de |
workPlace | String | Work arrangement, only populated when stated in the original posting. Values: remote, hybrid, onsite, field, offshore. | workPlace=remote |
workType | String | Work schedule. Values: fulltime, parttime, flextime, shift, fifo. | workType=fulltime |
contractType | String | Contract type. Values: permanent, temporary, freelance, contract, internship, apprenticeship, seasonal, commission, voluntary. | contractType=permanent |
careerLevel | String | Career level. Values: junior, senior, manager, director, chief, executive. | careerLevel=senior |
hasSalary | Boolean | When true, filters to postings that include salary data. | hasSalary=true |
minSalary | Number | Minimum salary, currency-independent. Only meaningful when combined with hasSalary=true. | minSalary=80000 |
isActive | Boolean | When true, filters to postings where dateActive is in the future. dateActive comes from schema.org validThrough, or defaults to dateCreated + 30 days. | isActive=true |
isDirect | Boolean | When true, only returns postings linked directly to the hiring company (not via a job board). | isDirect=true |
isRecruiter | Boolean | Filter by whether the posting is from a recruiting firm. | isRecruiter=false |
portal | String | Source portal key. See the portal explorer for all values. | portal=linkedin |
source | String | Specific source with country code suffix. | source=linkedin_us |
Example queries
- Jobs within 50 miles of San Francisco:
/api/v2/jobs/search?dateCreated=2026-05&geoPointLat=37.757&geoPointLng=-122.449&geoDistance=50mi - Senior software jobs in Germany posted in English:
/api/v2/jobs/search?dateCreated=2026-05&countryCode=de&language=en&careerLevel=senior&title=software - Remote Python or Spark jobs in core US timezones (UTC-8 to UTC-5):
/api/v2/jobs/search?dateCreated=2026-05&workPlace=remote&skills=Python,Spark&timezoneMin=-8&timezoneMax=-5 - Jobs in southern Netherlands (bounding box below latitude 52.25):
/api/v2/jobs/search?dateCreated=2026-05&countryCode=nl&geoTopLeftLat=52.25&geoTopLeftLng=0&geoBottomRightLat=32.25&geoBottomRightLng=10 - How many Healthcare jobs in the UK this month:
/api/v2/jobs/count?dateCreated=2026-05&countryCode=uk&industry=healthcare
2.3 Pagination
The /search endpoint returns 10 job postings per page. Use totalCount from the first page or run /count first to calculate the number of pages, then decide which pagination strategy fits (i.e., page-based vs. cursor-based).
Page-based pagination (Python)
Suitable for result sets up to ~10000 records. Use for targeted queries where you know the result set is manageable.
import requests
URL = "https://daily-international-job-postings.p.rapidapi.com/api/v2/jobs"
HEADERS = {"Authorization": "Bearer <your-api-key>"}
params = {
"dateCreated": "2026-05",
"countryCode": "de",
"industry": "software",
"careerLevel": "senior",
}
page, all_jobs = 1, []
while True:
resp = requests.get(f"{URL}/search", headers=HEADERS, params={**params, "page": page})
resp.raise_for_status()
data = resp.json()
batch = data.get("result", [])
all_jobs.extend(batch)
if len(all_jobs) >= data["totalCount"] or not batch:
break
page += 1
print(f"Fetched {len(all_jobs)} jobs")
Cursor-based pagination (Python)
Use for large result sets (more than 10000 records). Pass cursor=true on the first request, then pass the nextCursor value from each response. Stop when nextCursor is absent. Cannot be combined with page.
import requests
URL = "https://daily-international-job-postings.p.rapidapi.com/api/v2/jobs"
HEADERS = {"Authorization": "Bearer <your-api-key>"}
params = {"dateCreated": "2026-05", "countryCode": "us"}
cursor, all_jobs = "true", []
while cursor:
resp = requests.get(f"{URL}/search", headers=HEADERS, params={**params, "cursor": cursor})
resp.raise_for_status()
data = resp.json()
all_jobs.extend(data.get("result", []))
cursor = data.get("nextCursor") # absent on the last page
print(f"Fetched {len(all_jobs)} jobs")
For recurring bulk access to all jobs in a country, the Data Feeds are more cost-effective than paginating the API - one daily file contains all postings for that country and date.
Using /count for analytics (Python)
Count postings by country without fetching any job data:
import requests
URL = "https://daily-international-job-postings.p.rapidapi.com/api/v2/jobs/count"
HEADERS = {"Authorization": "Bearer <your-api-key>"}
for country in ["us", "de", "gb", "fr", "in"]:
resp = requests.get(URL, headers=HEADERS, params={
"dateCreated": "2026-05",
"countryCode": country,
"industry": "software",
})
print(f"{country}: {resp.json().get('totalCount', 0)} software jobs in 2026-05")
2.4 Boolean Operators
Text parameters (title, skills, company, industry, occupation) support boolean operators for precise filtering:
| Operator | Syntax | Example |
|---|---|---|
| OR (default) | Comma-separated | skills=Python,Spark - postings mentioning Python or Spark |
| AND | %2B prefix (URL-encoded +) | skills=%2BPython,%2BSpark - must mention both |
| NOT | - prefix | title=engineer,-junior - engineers but not juniors |
| Exact phrase | Double quotes | title="data engineer" - matches the exact phrase |
Combined example - senior data engineers who know both Python and SQL, excluding data scientists:
title="data engineer",-scientist&careerLevel=senior&skills=%2BPython,%2BSQL3. Data Feeds
Data Feeds and Historical Datasets are distributed as gzip-compressed JSON Lines files via AWS Data Exchange. Files follow the naming pattern techmap-jobs_{countryCode}_{date}.json.gz and contain one JSON object per line. For the export field schema and data samples see the Job Data Overview.
3.1 Finding Your Files
After subscribing on AWS Data Exchange, AWS grants read access to an S3 bucket path. To find your BUCKET_ALIAS and key prefix:
- Open the AWS Data Exchange console and go to Entitled Data.
- Select your Techmap dataset and open the Assets tab.
- The
BUCKET_ALIASand key prefix (e.g.,us/) are shown there. Copy both - you will need them in the commands below.
If you have a direct S3 contract with Techmap rather than an ADX subscription, see section 3.2b for the corresponding commands.
To test the workflow before subscribing, the Luxembourg dataset is available for free and covers postings from January 2020 onwards.
3.2 Downloading with the AWS CLI
3.2a AWS Data Exchange subscribers
ADX requires the --request-payer requester flag on all S3 commands. List all files available for the US country prefix:
aws s3api list-objects-v2 \
--request-payer requester \
--bucket BUCKET_ALIAS \
--prefix us/Download a specific daily file:
aws s3api get-object \
--request-payer requester \
--bucket BUCKET_ALIAS \
--key us/techmap-jobs_us_2026-06-06.json.gz \
techmap-jobs_us_2026-06-06.json.gz3.2b Direct S3 access (proprietary contracts)
Techmap provides AWS credentials for direct S3 access. Configure them as a named profile to keep them separate from your default credentials:
# List all available country prefixes
aws s3 ls --profile techmap-data s3://BUCKET_NAME/
# List all files for the US
aws s3 ls --profile techmap-data s3://BUCKET_NAME/us/
# Download a specific daily file
aws s3 cp --profile techmap-data \
s3://BUCKET_NAME/us/techmap-jobs_us_2026-06-06.json.gz .
# Download all US files for a given month
aws s3 sync --profile techmap-data s3://BUCKET_NAME/us/ . \
--exclude "*" --include "techmap-jobs_us_2026-05-*"3.3 Reading .json.gz Files
Each line in the decompressed file is a self-contained JSON object. The examples below decompress on the fly without writing a temporary file.
Python
import gzip
import json
with gzip.open("techmap-jobs_us_2026-06-06.json.gz", "rt", encoding="utf-8") as fh:
for line in fh:
job = json.loads(line)
title = job.get("name", "")
company = (job.get("company") or {}).get("name", "")
country = job.get("sourceCC", "")
date_created = job.get("dateCreated", "")
text = job.get("text", "") # full posting text
print(title, "-", company, "-", country, "-", date_created)
JavaScript / Node.js
const fs = require('fs');
const zlib = require('zlib');
const readline = require('readline');
const stream = fs.createReadStream('techmap-jobs_us_2026-06-06.json.gz')
.pipe(zlib.createGunzip());
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
rl.on('line', (line) => {
try {
const job = JSON.parse(line);
const company = job.company?.name ?? '';
console.log(job.name, '-', company, '-', job.dateCreated);
} catch (err) {
console.error('Parse error:', err.message);
}
});Java (Jackson)
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.util.zip.GZIPInputStream;
ObjectMapper mapper = new ObjectMapper();
try (InputStream fis = new FileInputStream("techmap-jobs_us_2026-06-06.json.gz");
GZIPInputStream gis = new GZIPInputStream(fis);
BufferedReader reader = new BufferedReader(new InputStreamReader(gis, "UTF-8"))) {
String line;
while ((line = reader.readLine()) != null) {
JsonNode job = mapper.readTree(line);
String title = job.path("name").asText();
String company = job.path("company").path("name").asText();
String dateCreated = job.path("dateCreated").asText();
System.out.println(title + " - " + company + " - " + dateCreated);
}
}4. References
- Job API Overview - full parameter table, response schema, data dictionary, error handling
- Job Data Overview - export field schema, Kaggle datasets, data samples
- Job Postings API on RapidAPI - subscribe and manage your API key
- OpenAPI definition (Job Postings API) - machine-readable spec
- RSS API on RapidAPI - for job boards consuming RSS feeds
- Techmap on AWS Marketplace - subscribe to Data Feeds or purchase Historical Datasets
- Portal Explorer - all 127+ source portals with country coverage
- Country Coverage - supported country codes and feed availability
- FAQ - billing, quotas, and common questions
Questions? Contact us if something is unclear or if you want sample data.