Jobs
Public job listings plus employer-only create, update, visibility, and apply flows.
List public jobs
Lists published, non-deleted jobs. Supports search, filtering, and pagination query parameters.
/api/jobsAuth: No auth required.
Response body
{
"data": [
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}
],
"page": 1,
"pageSize": 20,
"totalPages": 1,
"nextPage": false,
"prevPage": false
}Status codes
- 200 OK
- 400 Bad Request — Returned when a query value fails schema validation.
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Create job
Creates a job for a company owned by the authenticated user.
/api/jobsAuth: Bearer token or Clerk session.
Request body
{
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
]
}Response body
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}Status codes
- 201 Created
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
List employer jobs
Lists jobs for the authenticated employer company, including unpublished or deleted rows when present.
/api/jobs/privateAuth: Bearer token or Clerk session.
Response body
{
"data": [
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}
],
"page": 1,
"pageSize": 20,
"totalPages": 1,
"nextPage": false,
"prevPage": false
}Status codes
- 200 OK
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Get job
Returns a published job publicly. Owners can also fetch their own unpublished or deleted job.
/api/jobs/{id}Auth: Public for published jobs. Owner auth is optional for private or deleted jobs.
Response body
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}Status codes
- 200 OK
- 400 Bad Request
- 404 Not Found
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Update job
Updates a non-deleted job owned by the authenticated company.
/api/jobs/{id}Auth: Bearer token or Clerk session.
Request body
{
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
]
}Response body
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}Status codes
- 200 OK
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Delete job
Soft-deletes a job by default. Add `?hard=true` to permanently delete it.
/api/jobs/{id}Auth: Bearer token or Clerk session.
Response body
No response body.
Status codes
- 204 No Content
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Publish job
Sets `published_at` for a company-owned job. Publishing can fail if the subscription limit is reached.
/api/jobs/{id}/publishAuth: Bearer token or Clerk session.
Response body
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}Status codes
- 200 OK
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Unpublish job
Clears `published_at` for a company-owned job.
/api/jobs/{id}/unpublishAuth: Bearer token or Clerk session.
Response body
{
"id": "22222222-2222-2222-2222-222222222222",
"company_id": "11111111-1111-1111-1111-111111111111",
"title": "Frontend student developer",
"description": "Help build user-facing product features.",
"location": "Ljubljana",
"work_type": "hybrid",
"required_title": "What we are looking for",
"pay_from": 12,
"pay_to": 18,
"pay_type": "hourly",
"pay_category": "gross",
"job_type_id": "66666666-6666-6666-6666-666666666666",
"region_id": "55555555-5555-5555-5555-555555555555",
"education_level_id": "77777777-7777-7777-7777-777777777777",
"required_skills": [
"TypeScript",
"React"
],
"sections": [
{
"type": "markdown",
"title": "About the role",
"content": "Build and ship product improvements."
},
{
"type": "required_skills",
"title": "Required skills",
"content": null
}
],
"published_at": "2026-03-28T18:00:00.000Z",
"deleted_at": null
}Status codes
- 200 OK
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 500 Internal Server Error
Error format
{
"error": "Unauthorized",
"code": "unauthorized"
}Routes use the shared JSON error envelope; exact `code` values depend on the endpoint.
Apply for job (form flow)
Submits a form-based application attempt and redirects back to the job page. This route does not return JSON.
/api/jobs/{id}/applyAuth: Bearer token or Clerk session for a student account.
Request body
Content-Type: multipart/form-data
jobId: "22222222-2222-2222-2222-222222222222"The route reads multipart form data and requires the `jobId` field to match the path.
Response body
Redirect target examples:
/sl/app/jobs/22222222-2222-2222-2222-222222222222?success=true
/sl/app/jobs/22222222-2222-2222-2222-222222222222?error=validation
/sl/app/jobs/22222222-2222-2222-2222-222222222222?error=application_failedThe route redirects to the default locale job page instead of returning JSON.
Status codes
- 307 Temporary Redirect — The route calls `NextResponse.redirect()` without an explicit status.
Error format
No JSON error body. Failures are represented by redirect query parameters.