Documentation API CVReaderPro
Automatisez l'analyse, l'appariement et la génération de CV pour un recrutement efficace et conforme au RGPD.
Fonctionnalités clés
| Fonctionnalité | Description | Méthode de livraison |
|---|---|---|
| Analyse de CV (Parsing) | Extraire des données structurées (compétences, expérience, éducation, etc.) à partir d'un CV. | Synchrone (Réponse API) |
| Appariement CV/Offre d'Emploi | Comparez les CVs avec vos offres d'emploi pour trouver les meilleurs candidats. | API ou Webhook |
| Génération de CV | Générez des CVs standard ou anonymisés selon le modèle de votre entreprise. | Webhook ou Email |
1. Analyse de CV (Parsing)
Extraire des données structurées à partir de fichiers CV (PDF, DOCX, etc.).
https://cvreader.fr/api/v1/parserHeaders
Authorization: ApiKey YOUR_API_KEY
Accept: application/json (default) | application/xmlBody (multipart/form-data)
file : Fichier CV (PDF, DOCX, TXT, etc.)parserType : "ADVANCED" (56 champs) ou "PREMIUM" (96 champs, recommandé)
Exemple cURL
curl -X POST https://cvreader.fr/api/v1/parser \
-H "Authorization: ApiKey YOUR_API_KEY" \
-F "file=@/path/to/cv.pdf" \
-F "parserType=PREMIUM"Réponse (extrait)
{
"resumeId": "c8cd44a0-d765-4d47-ba04-67903ef650e5",
"documentType": "CV",
"documentLanguage": "FR",
"candidate": { "firstName": "Jean", "lastName": "Dupont" },
"experiences": [],
"educations": [],
"skills": [],
...
}Mise à jour et suppression d'un CV analysé
/api/v1/parser/{resumeId}Met à jour les données d'un CV existant.
/api/v1/parser/{resumeId}Supprime un CV analysé.
Async Parser (Parsing asynchrone)
Soumettez un CV pour traitement asynchrone. Les résultats sont envoyés à votre webhook.
/api/v1/parser/asyncPrérequisConfigurez l'URL de votre webhook dans l'application.
Exemple
curl -X POST https://cvreader.fr/api/v1/parser/async \
-H "Authorization: ApiKey YOUR_API_KEY" \
-F "file=@cv.pdf" \
-F "parserType=PREMIUM"Réponse immédiate :
{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08" }Webhook (implémentation client)
Votre endpoint doit recevoir une requête POST avec le résultat. Vérifiez la signature HMAC-SHA256 avec votre secret.
POST /webhook/parser-results
Headers: X-Webhook-Signature: <hmac-sha256>
Body: { "id": "...", "status": "SUCCESS", "resumeData": { ... } }2. API Offres d'Emploi (Jobs)
Fournissez une API qui retourne vos offres au format JobItem.
/api/jobs(implémenté par le client)
Doit retourner un tableau d'objets :
[
{
"title": "Senior Software Engineer",
"reference": "JOB-2023-456",
"description": "...",
"company": "TechCorp",
"country": "FR",
"city": "Paris"
}
]Enregistrez l'URL de votre endpoint dans CVReaderPro (Paramètres → Intégrations API).
Parse job from file
/api/job/parse/api-keyUploads a job description file (PDF, DOCX, etc.) and returns a structured Job object. The file is parsed server-side and the result is persisted and linked to the authenticated user.
Headers
Authorization: ApiKey YOUR_API_KEY
Content-Type: multipart/form-dataRequest body multipart/form-data
| Field | Type | Description |
|---|---|---|
| file* | File | The job description file to parse (PDF, DOCX, TXT…) |
Request example
curl -X POST "https://cvreader.fr/api/job/parse/api-key" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-F "file=@/path/to/job_description.pdf"Response 200 OK
| Field | Type | Description |
|---|---|---|
| id* | UUID | Unique job identifier |
| title | string | Parsed job title |
| description | string | Full job description text |
| profile | string | Required candidate profile |
| experience | string | Required experience level |
| education | string | Required education level |
| skills | string (JSON) | JSON-encoded array of required skills |
| company | string | Company name (if detected) |
| country | string | Country code (e.g. "FR") |
| city | string | City name (if detected) |
{
"id": "d4c7a1e2-0f3b-4c8d-9e1f-000000000001",
"title": "Senior Software Engineer",
"description": "We are looking for...",
"profile": "Experienced developer with leadership skills",
"experience": "5+ years",
"education": "Bachelor's degree",
"skills": "[\"Java\",\"Spring Boot\",\"Docker\"]",
"company": "TechCorp",
"country": "FR",
"city": "Paris"
}Error responses
| Status | Description |
|---|---|
| 401 | Invalid or missing ApiKey |
| 400 | No file provided or unsupported file format |
| 500 | Failed to parse job file |
Parse job from text
/api/job/parse/text/api-keyParses a raw job description string and returns a structured DTO without creating a file upload. The body can be a plain JSON string, a quoted string, or a JSON object with a description, job_description, or text field — the API extracts the value automatically.
Headers
Authorization: ApiKey YOUR_API_KEY
Content-Type: application/jsonRequest body application/json
Send the job description as a JSON string, a raw string, or an object with a recognized field:
// Option A — plain JSON string
"We are looking for a Senior React Developer with 5+ years..."
// Option B — object with recognized field
{ "description": "We are looking for a Senior React Developer..." }Request example
curl -X POST "https://cvreader.fr/api/job/parse/text/api-key" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '"We are looking for a Senior React Developer with 5+ years of experience..."'Response 200 OK
| Field | Type | Description |
|---|---|---|
| jobTitle | string | Parsed job title |
| jobDescription | string | Full job description |
| profileRecherche | string | Required candidate profile |
| experienceRequired | string | Required experience level |
| educationLevel | string | Required education level |
| skills | string[] | Array of required skills |
{
"jobTitle": "Senior React Developer",
"jobDescription": "We are looking for a Senior React Developer...",
"profileRecherche": "Experienced frontend engineer",
"experienceRequired": "5+ years",
"educationLevel": "Bachelor's degree",
"skills": ["React", "TypeScript", "Node.js", "GraphQL"]
}Error responses
| Status | Description |
|---|---|
| 400 | Job description is required (empty or missing body) |
| 401 | Invalid or missing ApiKey |
| 500 | Failed to parse job description text |
Create a job
/api/jobs/api-keyCreates a new job record linked to the API key owner. The payload shape is the same as the authenticated frontend endpoint. Use this to push jobs from your own ATS or data pipeline.
Request body application/json
| Field | Type | Description |
|---|---|---|
| title* | string | Job title |
| reference | string | Internal job reference code (e.g. "JOB-2026-001") |
| description | string | Full job description text |
| profile | string | Required candidate profile narrative |
| experience | string | Required experience level (e.g. "5+ years") |
| education | string | Required education level (e.g. "Bachelor's degree") |
| skills | string (JSON) | JSON-encoded array of required skills |
| company | string | Company name |
| country | string | Country code (e.g. "FR") |
| city | string | City name |
| status | string | "ACTIVE" | "CLOSED" | "DRAFT" |
Request example
curl -X POST "https://cvreader.fr/api/jobs/api-key" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Senior Java Developer",
"reference": "JOB-2026-001",
"description": "We are looking for a Senior Java Developer...",
"profile": "Experienced backend engineer",
"experience": "5+ years",
"education": "Bachelor'"'"'s degree",
"skills": "[\"Java\",\"Spring Boot\",\"Docker\"]",
"company": "TechCorp",
"country": "FR",
"city": "Paris",
"status": "ACTIVE"
}'Response 200 OK
Returns the created Job object (same shape as the parse file response).
{
"id": "d4c7a1e2-0f3b-4c8d-9e1f-000000000001",
"title": "Senior Java Developer",
"reference": "JOB-2026-001",
"status": "ACTIVE",
"company": "TechCorp",
"country": "FR",
"city": "Paris"
}Error responses
| Status | Description |
|---|---|
| 400 | Invalid or missing required fields |
| 401 | Invalid or missing ApiKey |
List my jobs
/api/jobs/api-key/myReturns a paginated list of jobs belonging to the API key owner. Supports the same filtering options as the authenticated frontend list endpoint.
Query parameters
| Field | Type | Description |
|---|---|---|
| page | integer | Zero-based page index (default: 0) |
| size | integer | Items per page (default: 10) |
| status | string | Filter by job status: "ACTIVE" | "CLOSED" | "DRAFT" |
| source | string | Filter by source (e.g. "api_key", "manual") |
| reference | string | Filter by reference code (partial match) |
| title | string | Filter by title (partial match) |
| postedFrom | ISO date-time | Filter jobs posted on or after this date |
| postedTo | ISO date-time | Filter jobs posted on or before this date |
Request example
# All active jobs, page 0, 10 per page
curl "https://cvreader.fr/api/jobs/api-key/my?page=0&size=10&status=ACTIVE" \
-H "Authorization: ApiKey YOUR_API_KEY"Response 200 OK
Paginated response — standard Spring Page structure:
{
"content": [
{ "id": "d4c7a1e2-...", "title": "Senior Java Developer", "status": "ACTIVE", ... }
],
"totalElements": 42,
"totalPages": 5,
"number": 0,
"size": 10
}Error responses
| Status | Description |
|---|---|
| 401 | Invalid or missing ApiKey |
Get one job
/api/jobs/api-key/my/{jobId}Retrieves a single job by ID. Ownership is enforced — only jobs belonging to the authenticated API key owner are returned.
Path parameters
| Field | Type | Description |
|---|---|---|
| jobId* | UUID | UUID of the job to retrieve. |
Request example
JOB_ID="d4c7a1e2-0f3b-4c8d-9e1f-000000000001"
curl "https://cvreader.fr/api/jobs/api-key/my/${JOB_ID}" \
-H "Authorization: ApiKey YOUR_API_KEY"Response 200 OK
Returns the full Job object.
Error responses
| Status | Description |
|---|---|
| 401 | Invalid or missing ApiKey |
| 403 | Job does not belong to the API key owner |
| 404 | Job not found |
Update a job
/api/jobs/api-key/my/{jobId}Replaces an existing job's data. The payload shape is the same as POST /api/jobs/api-key. Only fields present in the body are applied — omit fields you do not wish to change. Ownership is enforced.
Path parameters
| Field | Type | Description |
|---|---|---|
| jobId* | UUID | UUID of the job to update. |
Request body application/json
| Field | Type | Description |
|---|---|---|
| title* | string | Job title |
| reference | string | Internal job reference code (e.g. "JOB-2026-001") |
| description | string | Full job description text |
| profile | string | Required candidate profile narrative |
| experience | string | Required experience level (e.g. "5+ years") |
| education | string | Required education level (e.g. "Bachelor's degree") |
| skills | string (JSON) | JSON-encoded array of required skills |
| company | string | Company name |
| country | string | Country code (e.g. "FR") |
| city | string | City name |
| status | string | "ACTIVE" | "CLOSED" | "DRAFT" |
Request example
JOB_ID="d4c7a1e2-0f3b-4c8d-9e1f-000000000001"
curl -X PUT "https://cvreader.fr/api/jobs/api-key/my/${JOB_ID}" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Lead Java Developer",
"status": "ACTIVE",
"city": "Lyon"
}'Response 200 OK
Returns the updated Job object.
Error responses
| Status | Description |
|---|---|
| 400 | Invalid payload |
| 401 | Invalid or missing ApiKey |
| 403 | Job does not belong to the API key owner |
| 404 | Job not found |
3. API Score (Appariement)
Obtenir les scores d'un CV avec les offres
/api/scores/jobs-for-resume/{resumeId}Retourne une liste de scores pour un CV donné.
[
{
"jobId": "e918ab2f-d2f8-4890-b2d6-b049a76207a9",
"totalScore": 88.79
}
]Obtenir les CV correspondant à une offre
/api/scores/resumes-for-job/{jobReference}Match direct (job vs CV)
/api/scores/match-job-resume/{resumeId}Corps JSON avec les détails de l'offre.
File d'attente asynchrone
/api/jobs/queueSoumettez une liste de références d'offres pour traitement. Résultats envoyés par webhook.
["offre-123", "offre-456"]4. Génération de CV (standard ou anonymisé)
Générez des CVs au format PDF avec anonymisation optionnelle.
Authentication required
All endpoints below require an Authorization: ApiKey <YOUR_API_KEY> header. Missing or invalid keys return 401 Invalid Api Key.
/api/resume-settingsUpdate settings + regenerate canvas
/api/resume-settings/api-key/update-with-canvasReplaces the authenticated user's resume settings and immediately regenerates canvas preview images. Returns the updated settings payload including refreshed canvas pages — ideal for updating the preview UI instantly after a settings change.
Request body application/json
| Field | Type | Description |
|---|---|---|
| layout | string | Template layout name (e.g. "modern", "classic") |
| fontStyle | string | Font family (e.g. "Calibri", "Arial") |
| fontSize | number | Base font size in pt (e.g. 11) |
| lineHeight | number | Line height multiplier (e.g. 1.35) |
| marginTop | number | Top page margin in mm |
| marginBottom | number | Bottom page margin in mm |
| marginX | number | Left/right page margin in mm |
| sectionSpacing | number | Vertical spacing between sections in pt |
| agencyName | string | Branding: recruiter agency name (optional) |
| agencyWebsite | string | Branding: recruiter agency URL (optional) |
Request example
curl -X PUT "https://cvreader.fr/api/resume-settings/api-key/update-with-canvas" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"layout": "modern",
"fontStyle": "Calibri",
"fontSize": 11,
"lineHeight": 1.35,
"marginTop": 20,
"marginBottom": 18,
"marginX": 18,
"sectionSpacing": 10,
"agencyName": "Acme Recruiting",
"agencyWebsite": "https://acme.example"
}'Response 200 OK
Returns a ResumeSettingsResponseDto JSON object:
| Field | Type | Description |
|---|---|---|
| id* | UUID | Unique settings record ID |
| layout* | string | Active layout name |
| settings* | object | Full settings object (font, margins, spacing, branding) |
| privacy* | object | Privacy/anonymization configuration |
| canvas_page_count* | number | Number of regenerated canvas preview pages |
| canvas_pages* | array | Array of { index: number, url: string } — public preview image URLs per page |
Response example
{
"id": "a3f4e2b1-0c91-4d2e-bc57-7f3a6e9d0012",
"layout": "modern",
"settings": {
"fontStyle": "Calibri",
"fontSize": 11,
"lineHeight": 1.35,
"marginTop": 20,
"marginBottom": 18,
"marginX": 18,
"sectionSpacing": 10,
"agencyName": "Acme Recruiting",
"agencyWebsite": "https://acme.example"
},
"privacy": {
"hidePhoto": false,
"hideEmail": false,
"hidePhone": false,
"hideName": false
},
"canvas_page_count": 2,
"canvas_pages": [
{ "index": 0, "url": "https://cdn.cvreader.fr/canvas/page_0.png" },
{ "index": 1, "url": "https://cdn.cvreader.fr/canvas/page_1.png" }
]
}Error responses
| Status | Description |
|---|---|
| 401 | Invalid or missing ApiKey |
Generate PDF by resume ID
/api/resume-settings/api-key/resumes/{resumeId}/generate-pdfGenerates a PDF for the given resumeId using the current settings of the ApiKey owner. Candidate ownership is enforced — the resume must belong to the authenticated user. Returns the PDF as binary bytes with Content-Type: application/pdf.
Path parameters
| Field | Type | Description |
|---|---|---|
| resumeId* | UUID | UUID of the resume to render. Must belong to the authenticated ApiKey user. |
Request example
# Replace RESUME_ID with a valid UUID
curl -X POST \
"https://cvreader.fr/api/resume-settings/api-key/resumes/RESUME_ID/generate-pdf" \
-H "Authorization: ApiKey YOUR_API_KEY" \
--output resume.pdfResponse 200 OK
| Header / Field | Value |
|---|---|
| Content-Type | application/pdf |
| Content-Disposition | attachment; filename="resume_{resumeId}.pdf" |
| Body | PDF binary stream |
responseType: blob (Axios) or response.blob() (fetch). Save the blob as a .pdf file or open via URL.createObjectURL().Error responses
| Status | Description |
|---|---|
| 401 | Invalid or missing ApiKey |
| 404 | Resume not found for this user |
| 4xx | No credits remaining (NoMoreCreditException) |
Instant PDF generation (1–10)
/api/resume-settings/v1/generate-pdfSynchronously generates up to 10 PDFs in a single blocking request. All PDFs are ready when the response arrives — download URLs are included directly in the body. For larger batches (1–500) use the async webhook endpoint below.
10 resume IDs per request. For larger batches configure a webhook and use POST /api/webhook/generate-pdfs.Request body application/json
| Field | Type | Description |
|---|---|---|
| resumeIds* | UUID[] | List of 1–10 resume UUIDs to generate PDFs for synchronously. |
Request example
curl -X POST "https://cvreader.fr/api/resume-settings/v1/generate-pdf" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '["9f6ad665-25ce-4107-8ec5-b2a2fba572cc", "a1b2c3d4-5678-90ab-cdef-000000000001"]'Response 200 OK
| Field | Type | Description |
|---|---|---|
| jobId* | UUID | Internal queue ID for this batch. |
| status* | string | "COMPLETED" | "PARTIAL" | "FAILED" |
| progress* | string | Percentage of successfully processed PDFs (e.g. "100%"). |
| results* | array | Per-resume result objects — each contains resumeId, downloadUrl, generatedAt, or an error field. |
{
"jobId": "b72e9a01-3f4c-4e12-9a1d-000000000001",
"status": "COMPLETED",
"progress": "100%",
"results": [
{
"resumeId": "9f6ad665-25ce-4107-8ec5-b2a2fba572cc",
"downloadUrl": "https://cdn.cvreader.fr/pdfs/resume_9f6ad665.pdf",
"generatedAt": "2026-05-14T10:00:00Z"
}
]
}Error responses
| Status | Description |
|---|---|
| 400 | No resume IDs provided, or more than 10 IDs in a single request |
| 401 | Invalid or missing ApiKey |
| 403 | One or more resume IDs do not belong to the current user |
| 429 | Webhook delivery queue full, or no credits remaining |
Bulk async PDF generation (1–500)
/api/webhook/generate-pdfsEnqueues a large PDF batch for asynchronous processing. Returns immediately with a 202 Accepted response containing a job ID and status URL. Results are pushed to your configured webhook URL once processing completes. Requires a webhook configured with pdfGenerated=true.
pdfGenerated=true via POST /api/webhook. Without this, the endpoint returns 400.Request body application/json
| Field | Type | Description |
|---|---|---|
| resumeIds* | UUID[] | List of 1–500 resume UUIDs. All must belong to the authenticated user. |
Request example
curl -X POST "https://cvreader.fr/api/webhook/generate-pdfs" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '["<uuid-1>", "<uuid-2>", ..., "<uuid-50>"]'Response 202 Accepted
| Field | Type | Description |
|---|---|---|
| jobId* | UUID | Unique identifier for the async generation job. Use with the status endpoint. |
| status* | string | "QUEUED" — processing has started asynchronously. |
| statusUrl* | string | Polling URL: GET /api/webhook/generate-pdfs/{jobId} |
| message* | string | Human-readable confirmation. |
| webhookSecurity* | object | HMAC-SHA256 signing metadata: algorithm, signatureHeader, timestampHeader, signedPayload format. |
{
"jobId": "c8a12f44-0000-0000-0000-000000000002",
"status": "QUEUED",
"statusUrl": "/api/webhook/generate-pdfs/c8a12f44-0000-0000-0000-000000000002",
"message": "Processing started. Results will be sent to your webhook URL.",
"webhookSecurity": {
"algorithm": "HmacSHA256",
"signatureHeader": "X-Webhook-Signature",
"timestampHeader": "X-Webhook-Timestamp",
"signedPayload": "<timestamp>.<raw-json-body>"
}
}Error responses
| Status | Description |
|---|---|
| 400 | Resume ID list is empty, below minimum (1), above maximum (500), or webhook not configured with pdfGenerated=true |
| 401 | Invalid or missing ApiKey |
| 403 | One or more resume IDs do not belong to the current user |
| 429 | Too many pending webhook deliveries |
PDF generation job status
/api/webhook/generate-pdfs/{jobId}Polls the status of an asynchronous PDF generation job. Returns per-resume processing results and webhook delivery attempts. Poll periodically until status is "COMPLETED".
Path parameters
| Field | Type | Description |
|---|---|---|
| jobId* | UUID | The job ID returned by POST /api/webhook/generate-pdfs. |
Request example
JOB_ID="c8a12f44-0000-0000-0000-000000000002"
curl "https://cvreader.fr/api/webhook/generate-pdfs/${JOB_ID}" \
-H "Authorization: ApiKey YOUR_API_KEY"Response 200 OK
| Field | Type | Description |
|---|---|---|
| jobId* | UUID | Job identifier. |
| status* | string | "QUEUED" | "PROCESSING" | "COMPLETED" |
| total* | number | Total number of resume items in the batch. |
| processed* | number | Number of items already processed. |
| results* | array | Per-resume: resumeId, processed (bool), downloadUrl, generatedAt. |
| deliveries* | array | Webhook delivery attempts with status, attemptCount, responseStatusCode, errorMessage, and retry timing. |
{
"jobId": "c8a12f44-0000-0000-0000-000000000002",
"status": "PROCESSING",
"total": 25,
"processed": 12,
"results": [
{ "resumeId": "9f6ad665-...", "processed": true, "downloadUrl": "https://cdn.cvreader.fr/pdfs/...", "generatedAt": "2026-05-14T10:02:00Z" },
{ "resumeId": "a1b2c3d4-...", "processed": false, "downloadUrl": null, "generatedAt": null }
],
"deliveries": [
{
"deliveryId": "d1e2f3a4-...",
"type": "PDF_GENERATED",
"delivered": false,
"attemptCount": 1,
"lastAttempt": "2026-05-14T10:01:00Z",
"nextAttempt": "2026-05-14T10:06:00Z",
"responseStatusCode": 500,
"responseBody": "Internal Server Error",
"errorMessage": "Connection refused"
}
]
}Error responses
| Status | Description |
|---|---|
| 401 | Invalid or missing ApiKey |
| 403 | This job does not belong to the current user |
| 404 | PDF generation job not found |
Batch format (standard or anonymized)
/api/resume-settings/formatConfigurez les règles d'anonymisation dans votre espace abonné ("Paramètres du CV").
Request body application/json — array of resume UUIDs
[
"resume-data-uuid-1",
"a10288d7-b4ad-4181-8a45-2b7af9671b7c"
]Request example
curl -X POST "https://cvreader.fr/api/resume-settings/format" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '["resume-data-uuid-1", "a10288d7-b4ad-4181-8a45-2b7af9671b7c"]'Les CV générés sont livrés par webhook ou email avec un lien de téléchargement.
Cas d'utilisation
1. Automatiser le pré‑filtrage des candidats
Analysez les CVs → obtenez les resumeId → envoyez-les à /api/jobs/queue → recevez les scores par webhook.
2. Recrutement équitable avec CVs anonymisés
Configurez l'anonymisation dans les paramètres, puis générez des CVs sans données personnelles.
Gestion des erreurs
| Code | Cause | Solution |
|---|---|---|
| 400 | Requête mal formée | Vérifiez le format du corps. |
| 401 | Clé API invalide | Vérifiez l'en-tête Authorization. |
| 404 | Ressource non trouvée | Vérifiez resumeId/jobId. |
| 429 | Trop de requêtes | Réduisez la fréquence. |
Meilleures pratiques
- Testez dans l'environnement de bac à sable (sandbox) avant la production.
- Anonymisez systématiquement les CVs pour les rôles sensibles.
- Surveillez vos webhooks/emails pour les résultats asynchrones.
- Archivez les CVs originaux de manière sécurisée (RGPD).
Besoin d'aide ?