Jobs API
The Jobs resource is the heart of the Qudra Partner API. Every job you create flows through the embedding pipeline and becomes matchable against the Qudra seeker graph within ~30 seconds.
The job object
{
"id": "job_01HXY8N1K9PZ3R…",
"title": "Senior Backend Engineer",
"description": "Build the Qudra matching pipeline…",
"city": "Riyadh",
"employment_type": "full_time",
"salary_min": 18000,
"salary_max": 30000,
"currency": "SAR",
"status": "active",
"embedding_status": "ready",
"match_ready": true,
"qudra_url": "https://qudrah.io/jobs/senior-backend-engineer-01hxy…",
"created_at": "2026-05-21T08:14:22.123Z",
"updated_at": "2026-05-21T08:14:54.802Z"
}| Field | Type | Description |
|---|---|---|
id | stringjob_<ulid> | Stable Qudra-issued id. |
title | string | 3–200 chars. Used in matching — be specific. |
description | string | Up to 20,000 chars. Markdown is rendered on the public page. |
city | string | KSA city in English (Riyadh, Jeddah, Dammam, NEOM, …). |
employment_type | enum | Employment type. Enum full_timepart_timecontractinternship |
salary_min | integerSAR | Monthly SAR. Required for full_time and contract. |
salary_max | integerSAR | Monthly SAR. Must be ≥ salary_min. |
currency | string | Reserved for future expansion. Default SAR |
status | enum | Lifecycle state. Default activeEnumactivepausedclosed |
embedding_status | enum | Async pipeline state — wait for `ready` before relying on matching. Enum processingreadyfailed |
match_ready | boolean | `true` once embedding is ready and the job is in the match graph. Default false |
qudra_url | stringURL | Public canonical URL on qudrah.io. |
created_at | stringISO-8601 | Server creation time. |
updated_at | stringISO-8601 | Last mutation time. |
Create
/v1/partner/jobsv1BearerCreate a single job. Counts against your monthly quota and per-minute rate limit. Returns 201 with the new job.
The embedding runs asynchronously — listen for job.created and job.matched webhooks rather than polling.
Request body
| Field | Type | Description |
|---|---|---|
title | string | 3–200 chars. Be specific — used for matching. |
description | string | Up to 20,000 chars. Markdown is rendered on the public page. |
city | string | KSA city in English. |
employment_type | enum | Employment type. Enum full_timepart_timecontractinternship |
salary_min | integerSAR | Monthly SAR. |
salary_max | integerSAR | Monthly SAR. Must be ≥ salary_min. |
currency | string | Reserved. Default SAR |
Request
curl -X POST https://api.qudrah.io/v1/partner/jobs \
-H "Authorization: Bearer $QUDRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Senior Backend Engineer",
"description": "Build the Qudra matching pipeline. Stack: NestJS, Postgres, pgvector, Redis.",
"city": "Riyadh",
"employment_type": "full_time",
"salary_min": 18000,
"salary_max": 30000,
"currency": "SAR"
}'Response — 201 Created
{
"id": "job_01HXY8N1K9PZ3R…",
"status": "active",
"embedding_status": "processing",
"match_ready": false,
"qudra_url": "https://qudrah.io/jobs/senior-backend-engineer-01hxy…",
"created_at": "2026-05-21T08:14:22.123Z"
}Idempotency
Pass Idempotency-Key: <uuid> to safely retry a create. We deduplicate by hash of (partnerId, idempotencyKey) for 24 hours.
List
/v1/partner/jobsv1BearerList your partner's jobs in reverse-chronological order with cursor pagination.
Query params
| Field | Type | Description |
|---|---|---|
limit | integer | Page size. Min 1, max 100. Default 20 |
cursor | string | Opaque cursor from the `next_cursor` of the previous response. |
status | enum | Filter by job status. Enum activepausedclosed |
city | string | Filter by KSA city (English). |
Response
{
"data": [
{ "id": "job_01HXY…", "title": "…", "status": "active", "match_ready": true, "…": "…" }
],
"next_cursor": "eyJpZCI6Imp…",
"has_more": true
}Retrieve
/v1/partner/jobs/:idv1BearerReturns the full job object. 404 partner.not_found if the job isn't owned by your partner.
Update
/v1/partner/jobs/:idv1BearerPartial update — send only the fields you want to change. Mutating title/description re-runs the embedding pipeline.
curl -X PATCH https://api.qudrah.io/v1/partner/jobs/job_01HXY… \
-H "Authorization: Bearer $QUDRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "paused" }'Delete
/v1/partner/jobs/:idv1BearerSoft-delete. The job disappears from the seeker feed immediately; we retain it for 30 days for audit. Returns 204 No Content.
Bulk
/v1/partner/jobs/bulkv1BearerGrowth and Scale only. Create up to 100 jobs in a single call. One request against rate limit, N against monthly quota.
Request
curl -X POST https://api.qudrah.io/v1/partner/jobs/bulk \
-H "Authorization: Bearer $QUDRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobs": [
{ "title": "Backend Engineer", "city": "Riyadh", "employment_type": "full_time", "salary_min": 15000, "salary_max": 22000 },
{ "title": "Frontend Engineer", "city": "Jeddah", "employment_type": "full_time", "salary_min": 14000, "salary_max": 20000 }
]
}'Response — 207 Multi-Status
{
"created": [
{ "index": 0, "id": "job_01HXY…", "status": "active" },
{ "index": 1, "id": "job_01HXZ…", "status": "active" }
],
"errors": []
}Per-item failures are reported in errors with the same shape as a top-level validation error — the rest of the batch still succeeds.