Co APIposindonesia.co.id ↗
Fetch job vacancies from the Pos Indonesia career page. Get title, employment type, department, posting date, and URL via 2 structured endpoints.
What is the Co API?
The Pos Indonesia Careers API exposes 2 endpoints that return structured job vacancy data from the Pos Indonesia career page (posindonesia.co.id/id/karir). The list_jobs endpoint delivers paginated vacancy rows — each including job title, employment type, department, posting date, location, and a direct URL to the listing. The list_departments endpoint returns the department vocabulary needed to filter jobs by department.
curl -X GET 'https://api.parse.bot/scraper/0007bfdb-3372-45f0-bbb7-adf0898b9e1e/list_jobs?page=1&limit=10&search=engineer&department=65a8f7159ea4cfd5043d5e84&employment_type=permanent' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace posindonesia-co-id-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Pos Indonesia Careers API — browse departments and vacancies."""
from parse_apis.posindonesia_co_id_api import PosIndonesia, EmploymentType, InputFormatInvalid
client = PosIndonesia()
# List all departments to discover filter values.
for dept in client.departments.list(limit=10):
print(dept.department_id, dept.name)
# Pick the first department and use its id to filter job listings.
dept = client.departments.list(limit=1).first()
if dept is not None:
for job in client.jobs.list(department=dept.department_id, limit=5):
print(job.job_title, job.employment_type, job.posting_date)
# Filter by employment type using the enum.
try:
for job in client.jobs.list(employment_type=EmploymentType.INTERNSHIP, limit=5):
print(job.job_title, job.location, job.url)
except InputFormatInvalid as e:
# Raised when the API rejects a filter value.
print("invalid filter:", e.message)
print("exercised: departments.list / jobs.list (by department, by employment_type)")
Returns one page of job vacancies currently published on the Pos Indonesia career page, newest first. Each row is one vacancy with job_title, employment_type (permanent, internship or contract), department, posting_date (ISO 8601 UTC timestamp of publication), and url (the career page pre-filtered to that vacancy; the site has no per-vacancy detail pages). location is null unless the site attaches a location to the vacancy — at build time the career page listed zero vacancies, so this field, and the filter effects, could not be observed on real rows. A valid empty page is returned as jobs=[] with total=0, exactly as the site shows when no vacancy is open. Pagination: page (1-based, default 1) and limit (default 20, max 100); has_more reports whether a further page exists. One upstream request per call.
| Param | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Vacancies per page; values above 100 are clamped to 100. |
| search | string | Free-text filter matched against the job title (substring). Omitted = all titles. |
| department | string | Department filter: department_id from list_departments.departments[*].department_id. Omitted = all departments. |
| employment_type | string | Employment type filter from the career page's 'Kategori' dropdown. Omitted = all types. |
{
"type": "object",
"fields": {
"jobs": "array of vacancy rows: job_id, job_title, location (string or null), employment_type, department_id, department (name), posting_date (ISO 8601), updated_at (ISO 8601), url",
"page": "integer current page",
"total": "integer total number of vacancies matching the filters across all pages",
"has_more": "boolean, true when a following page exists",
"total_pages": "integer number of pages"
},
"sample": {
"data": {
"jobs": [],
"page": 1,
"total": 0,
"has_more": false,
"total_pages": 1
},
"status": "success"
}
}About the Co API
Endpoints and Response Shape
The list_jobs endpoint returns vacancies sorted newest-first, with each row containing job_id, job_title, location (string or null), employment_type (permanent, internship, or contract), department_id, department (human-readable name), and posting_date as an ISO 8601 UTC timestamp. The response also includes page, total, total_pages, and has_more for pagination. The limit parameter accepts up to 100 vacancies per page; higher values are clamped to 100.
Filtering and Search
list_jobs supports three independent filters. search matches a substring against the job title — useful for targeting specific roles. department accepts a department_id from list_departments, which mirrors the 'Departemen' dropdown on the career page. employment_type mirrors the 'Kategori' dropdown and accepts values such as permanent, internship, or contract. Filters can be combined freely; omitting any filter returns all matching vacancies.
Department Vocabulary
The list_departments endpoint returns the complete department list used on the career page, with each entry containing a department_id (the opaque identifier to pass to list_jobs) and a name in Indonesian. At build time the set contained 2 departments. This endpoint takes no parameters and is designed as a single lookup call to populate filter options before querying list_jobs.
The Co API is a managed, monitored endpoint for posindonesia.co.id — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when posindonesia.co.id changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official posindonesia.co.id API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Monitor new Pos Indonesia job postings automatically by checking posting_date on a schedule
- Filter internship or contract vacancies using the employment_type parameter to surface short-term roles
- Build a department-specific job alert by combining department_id from list_departments with list_jobs filters
- Aggregate job listing counts across departments to track hiring volume trends over time
- Extract direct vacancy URLs from the url field to deep-link users straight to application pages
- Search for specific roles by passing a job title substring to the search parameter
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Pos Indonesia provide an official developer API for its career page?+
What does list_jobs return and how does pagination work?+
jobs key, each with job_id, job_title, location, employment_type, department_id, department name, posting_date (ISO 8601 UTC), and a url. The response also includes page, total, total_pages, and has_more. Use the page parameter (1-based) to step through results; limit controls rows per page up to a maximum of 100.