AI Integration
Integrate with the Jooble ATS API faster using an AI coding assistant (Claude Code, Cursor, ChatGPT, GitHub Copilot…). Paste the prompt below into your assistant and it will write accurate, working integration code for you. You can also download the full specification as a single Markdown file.
↓ Download the full spec (Markdown)
Use as a prompt
Copy the prompt below (copy button, top-right) and paste it as the first message — then describe your task, e.g. “Write a Python script that authenticates, creates a job, and fetches its candidates.”
The prompt is self-contained — you don’t need to paste any other documentation.
You are an expert backend engineer helping me integrate with the Jooble ATS
Integration API. Use ONLY the specification below. When you write code, prefer
the language/framework I specify; otherwise default to clean, production-ready
examples with error handling. Never invent endpoints, fields, or enum values
that are not listed here.
# Jooble ATS Integration API — Specification
## Base URL
https://{countryCode}.jooble.org/employer/api/v2
Replace {countryCode} with the country subdomain (e.g. ua, hu, ro).
## Authentication
- POST /AtsJob/login Body: { "email": string, "password": string } (both required)
Response 200: { "access_token": string } // JWT, expires after 24 hours
- Send on every authenticated request:
Authorization: Bearer {access_token}
Content-Type: application/json
- 401 Unauthorized means the token is missing or invalid -> re-authenticate.
## Endpoints
1) POST /AtsJob/create — create a job listing.
Body: title (string, REQUIRED, max 20), region (string, REQUIRED),
description (string, REQUIRED, min 100 chars), address (string, optional),
salaryValue1 (int >=0, optional), salaryValue2 (int >=0, optional, >= salaryValue1),
salaryRateId (sbyte, optional, REQUIRED if salaryValue1 set),
jobType1 (int, optional), jobType2 (int, optional).
Rules: salaryValue2 needs salaryValue1; salaryRateId needed if salaryValue1 set;
jobType2 needs jobType1. Response 200: { id: long, dateCreated: datetime }.
Errors: 400, 403.
2) PUT /AtsJob/update — same as create plus jobId (long, REQUIRED, >0). Response 204.
3) POST /AtsJob/changeStatus — Body { jobId: long, jobStatus: int }.
jobStatus 0=Activated, 1=Stopped, 2=Deleted. Response 200: { status: string }.
4) GET /AtsJob/{id} — returns the job object (see fields below). Errors 403, 404.
5) GET /AtsJob/allJobs?jobStatus=... — array of job objects. Errors 403.
6) GET /AtsJob/appliesByJob/{jobId} — array of candidate objects (see below). Errors 403.
7) POST /AtsJob/{applyId}/markViewed — mark apply as viewed. Idempotent. Response 200.
Job object: id, status, title, region, address, jobType1?, jobType2?,
salaryValue1? (null if 0), salaryValue2? (null if 0), salaryRateId?,
description (HTML), appliesCount, viewsCount, email.
Candidate object: id (apply id), jobId, date, dateStatusChanged, status, isNew,
isViewed, isSuggested, isPremium, withoutCv, hasProfileCV, hasProfile, fileName?,
hasMessages, messagesCount, newMessagesCount, lastMessageDate?, appliesCount,
cvFile? (only if ATS integration enabled, else null);
applicant { name, age?, salary?, currency?, region?, gender?, photoUrl?, isReadyForRelocate?,
contacts { phone?, email? (may be masked), isOpened, openDate? } };
additionalQuestions { total, passed };
cvFile { name, data (base64), type "CV", contentType }.
## Webhooks (Jooble calls YOUR endpoint on each new application)
Headers: Content-Type: application/json; X-Webhook-Signature: HMAC-SHA256
"t={timestamp},v1={signature}" (verify it).
Body: {
candidate { first_name (req), last_name (req), email_address?, phone_number?,
gender? (MALE|FEMALE), location { city?, country (req, ISO uppercase) } },
application { job_id (req), source? },
attachments [ { name, data (base64), type "CV", content_type } ]
}
## Enums
Job Status (string): Activated, Stopped, Deactivated, Deleted, PreActivated.
Job Status (int): 0=Activated, 1=Stopped, 2=Deleted.
Job Type: 0=Full-time, 1=Part-time, 2=Contract, 3=Temporary, 4=Remote, 5=Internship.
Salary Rate: 0=hour, 1=day, 2=week, 3=month, 5=year (4 unused).
Gender: MALE, FEMALE, null.
Candidate Status: Received, Processing, Invited, Offer, Rejected, Deleted.
## Errors
Format: { "code": string, "message": string }.
Codes: JobsOverLimit (active limit exceeded), SubscriptionOnApproving (publishing blocked).
HTTP: 200, 204, 400, 401, 403, 404, 500.
## Best practices
- Cache the JWT, refresh before 24h expiry, handle 401 by re-login.
- Validate salary/job-type rules before create/update.
- Verify the webhook HMAC signature before trusting the payload.
- Never log the access_token or candidate personal data.What you can ask
- “Write a Node.js client that logs in and caches the JWT until it expires.”
- “Generate an Express webhook receiver that verifies the
X-Webhook-Signature.” - “Create a TypeScript type for the candidate object returned by
appliesByJob.” - “Show me how to publish a job with a salary range and validate it before sending.”