Dernière mise à jour : 15 octobre 2026
Candidate Analyzer API¶
Port local (Docker Compose) : 30003 | Repo : solyntek/djinn/services/djinn-candidate-analyzer
Aide à la décision de recrutement : scoring déterministe, explicable et rejouable de candidats par rapport à un poste. Aucun LLM ni embeddings dans le calcul (ADR-028). Le service classe et explique ; il ne décide jamais, ne rejette jamais.
Endpoints¶
| Méthode | Route | Description |
|---|---|---|
GET |
/health |
Health check (sans authentification) ; renvoie version et scoring_version |
POST |
/v1/analyze |
Scorer 1 candidat vs 1 poste |
POST |
/v1/analyze/batch |
Scorer 1 à 100 candidats, retour trié par score (meilleur d'abord) |
POST |
/v1/analyze/competency-file |
Scorer un dossier de compétences (texte brut, 500 000 caractères max) : les termes du poste trouvés dans le texte deviennent les compétences |
POST |
/v1/hr/analyses/{analysis_id}/decisions |
Enregistrer la décision humaine prise sur une analyse (201) |
POST |
/v1/hr/subjects/ref |
Références pseudonymes d'un candidat, une par mois (limitée à 10/min) |
PUT |
/v1/hr/settings |
Rétention du journal et arrêt d'urgence par client |
Scoring (5 dimensions)¶
| Dimension | Poids par défaut | Méthode |
|---|---|---|
| Skills | 0.30 | Correspondance par jetons entiers de required_skills / preferred_skills (80 % / 20 % si les deux sont fournis) |
| Experience | 0.25 | Mois d'expérience (postes qui se chevauchent comptés une fois) vs min_experience_years ; non évaluée sans min_experience_years |
| Education | 0.15 | required_education trouvé dans l'intitulé ou le domaine d'un diplôme |
| Languages | 0.15 | required_languages trouvées parmi les langues du candidat |
| Location | 0.15 | Lieu du candidat vs location et remote_policy du poste ; non évaluée sans location du poste, si remote_policy vaut remote, ou si anonymize est vrai |
Les poids (weights, optionnels) doivent totaliser 1.0. Ils sont renormalisés sur les seules dimensions évaluées. La correspondance ignore casse et accents, normalise les formes genrées françaises et garde exacts les noms à symboles (C, C++, C#, .NET, R, Go, F#) : java ne correspond pas à javascript.
Le score global est compris entre 0 et 1 ; fit_level vaut excellent (>= 0.8), good (>= 0.6), moderate (>= 0.4) ou weak.
Options de requête (les trois routes d'analyse)¶
| Champ | Défaut | Description |
|---|---|---|
weights |
0.30 / 0.25 / 0.15 / 0.15 / 0.15 | Poids par dimension, somme = 1.0 |
anonymize |
false |
Retire le lieu pour toute la requête ; la dimension lieu n'est alors pas évaluée |
as_of |
aujourd'hui (UTC) | Date de référence du calcul de l'expérience, renvoyée dans la réponse |
lang |
fr |
Langue de l'explication (fr ou en) |
candidate.id est l'identifiant du candidat chez vous : utilisez une valeur opaque (ni e-mail, ni entier séquentiel). Il est pseudonymisé avant journalisation. firstname, lastname, email, phone, linkedin et raw_text sont dépréciés : acceptés pour que la sortie CV de doc-extract puisse être envoyée telle quelle, mais ignorés, jamais journalisés, et listés dans minimization.ignored_fields.
Contenu de la réponse¶
analysis_id, scoring_version, notice_version, as_of, overall_score, fit_level, weights_used, une entrée par dimension (score, weight appliqué, evaluated, evidence.matched / evidence.missing, rationale issue d'un gabarit versionné, template_id), proxy_criteria (lieu et/ou formation lorsqu'ils ont pesé sur le score), human_review_required (toujours true), explanation, minimization, strengths, gaps, summary. Même entrée, même scoring_version et même as_of donnent toujours le même score.
Décision humaine, contestation et arrêt d'urgence¶
POST /v1/hr/analyses/{analysis_id}/decisions:decisionvautshortlisted,not_retained,on_hold,review_requested(le candidat conteste, RGPD art. 22(3)) ourevised;reviewer_refest un identifiant opaque du relecteur ;supersedesest ledecision_idremplacé. La réponse donnedecision_id,agrees_with_score(calculé par le serveur) etseconds_since_scoring.POST /v1/hr/subjects/refavec{"subject_id": "<candidate.id>"}renvoie lesubject_refpseudonyme de chaque mois dont la clé existe encore. C'est l'entrée duPOST /v1/gdpr/exportd'audit-trail (subject_type: "resource_id") pour répondre à une demande d'accès.PUT /v1/hr/settings:retention_months(6 à 60, 6 par défaut) etscoring_enabled.falseest l'arrêt d'urgence : les routes d'analyse répondent423. Réduire la rétention purge immédiatement ; l'augmenter ne ramène pas les clés détruites.
Scores et décisions sont écrits dans l'audit trail sans donnée d'identité. La rétention se fait par destruction des clés mensuelles de pseudonymisation : ensuite, les références ne sont plus reliables côté Djinn (ce n'est pas une anonymisation au sens du RGPD).
Erreurs¶
Les erreurs de ce service ont la forme {"detail": {"code": "...", "message": "..."}} :
| HTTP | code |
Signification |
|---|---|---|
404 |
analysis_not_found |
Analyse inconnue, purgée, ou d'un autre client |
422 |
no_evaluable_criteria |
Le poste et les poids ne laissent aucune dimension évaluable : fixez au moins un critère de poids positif |
422 |
(validation) | Requête invalide (poids ne totalisant pas 1.0, remote_policy inconnu, plus de 100 candidats...) |
423 |
scoring_disabled |
Arrêt d'urgence activé pour ce client |
500 |
audit emission failed : rien n'a été écrit, réessayer |
|
503 |
Base non configurée |
Notice et limites (ADR-028)¶
Le recrutement est un usage à haut risque au sens de l'AI Act européen (annexe III, 4(a)). Djinn est le fournisseur, vous êtes le déployeur ; détourner la finalité fait de vous un fournisseur (art. 25). notice_version identifie la notice d'utilisation (art. 13) qui décrit le scoring renvoyé avec chaque analyse. En particulier :
- Aide à la décision uniquement : chaque analyse exige une relecture humaine (
human_review_required: true). N'utilisez pas le score comme décision automatisée. - Correspondance lexicale : la liste de compétences d'un candidat peut être gonflée ; aucune évaluation de la personnalité ni des soft skills.
- Critères indirects : le lieu et la formation restent configurables et sont signalés dans
proxy_criteria; un rapport de biais est publié pour chaquescoring_version. - L'exactitude n'est pas mesurée dans cette version (un plan de mesure existe).
Exemple¶
curl -X POST http://localhost:30003/v1/analyze \
-H "X-API-Key: votre-cle-locale" \
-H "Content-Type: application/json" \
-d '{
"job": {"title": "Python Developer", "required_skills": ["Python", "FastAPI"]},
"candidate": {"id": "cand-7f3a", "skills": ["Python", "FastAPI", "Docker"]},
"lang": "fr"
}'
curl -X POST https://api.dev.djinn.solyntek.io/v1/analyze \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"job": {"title": "Python Developer", "required_skills": ["Python", "FastAPI"]},
"candidate": {"id": "cand-7f3a", "skills": ["Python", "FastAPI", "Docker"]},
"lang": "fr"
}'
Référence interactive¶
Générée à chaque build depuis la spec versionnée openapi/candidate-analyzer-v1.json (ADR-011) — aucune route documentée à la main.
Djinn Candidate Analyzer 0.1.0¶
Aide à la décision de recrutement : scoring explicable, journalisé et minimisé (ADR-028)
Endpoints¶
GET /health¶
Health
Description
Health check, without authentication.
Responses
Schema of the response body
{
"properties": {
"status": {
"type": "string",
"title": "Status",
"default": "ok"
},
"version": {
"type": "string",
"title": "Version",
"default": "0.1.0"
},
"scoring_version": {
"type": "string",
"title": "Scoring Version",
"default": "2026.10.1"
}
},
"type": "object",
"title": "HealthResponse",
"description": "Response for health check."
}
POST /v1/analyze¶
Analyze
Description
Score one candidate against one job: decision support, never a rejection.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
X-API-Key |
header | No |
Request body
{
"weights": {
"skills": 10.12,
"experience": 10.12,
"education": 10.12,
"languages": 10.12,
"location": 10.12
},
"anonymize": true,
"as_of": null,
"lang": "fr",
"job": {
"title": "string",
"description": "string",
"required_skills": [
"string"
],
"preferred_skills": [
"string"
],
"min_experience_years": null,
"required_languages": [
"string"
],
"required_education": null,
"location": null,
"remote_policy": null
},
"candidate": {
"id": null,
"firstname": null,
"lastname": null,
"email": null,
"phone": null,
"linkedin": null,
"raw_text": null,
"skills": [
"string"
],
"languages": [
"string"
],
"experiences": [
{
"company": "string",
"title": "string",
"location": "string",
"start_date": "string",
"end_date": "string",
"description": "string"
}
],
"diplomas": [
{
"school": "string",
"degree": "string",
"field_of_study": "string",
"start_date": "string",
"end_date": "string"
}
],
"certifications": [
{}
],
"location": null
}
}
Schema of the request body
{
"properties": {
"weights": {
"$ref": "#/components/schemas/ScoringWeights"
},
"anonymize": {
"type": "boolean",
"title": "Anonymize",
"description": "Retire le lieu (profil et expériences) pour tout le lot ; la localisation n'est alors pas évaluée.",
"default": false
},
"as_of": {
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "null"
}
],
"title": "As Of",
"description": "Date de référence du calcul de l'expérience ; défaut : date du jour (UTC), renvoyée dans l'analyse."
},
"lang": {
"type": "string",
"enum": [
"fr",
"en"
],
"title": "Lang",
"description": "Langue de l'explication.",
"default": "fr"
},
"job": {
"$ref": "#/components/schemas/JobDescription"
},
"candidate": {
"$ref": "#/components/schemas/CandidateProfile"
}
},
"type": "object",
"required": [
"job",
"candidate"
],
"title": "AnalyzeRequest",
"description": "Requête d'analyse d'un candidat."
}
Responses
{
"analysis_id": "ba081868-516e-40d6-a19a-19dcca795e3f",
"candidate_id": null,
"scoring_version": "string",
"notice_version": "string",
"as_of": "2022-04-13",
"overall_score": 10.12,
"fit_level": "excellent",
"weights_used": {},
"dimension_scores": [
{
"dimension": "skills",
"score": 10.12,
"weight": 10.12,
"evaluated": true,
"evidence": {
"matched": [
"string"
],
"missing": [
"string"
]
},
"rationale": "string",
"template_id": "string",
"details": "string"
}
],
"proxy_criteria": [
"location"
],
"human_review_required": true,
"explanation": [
"string"
],
"minimization": {
"ignored_fields": [
"string"
],
"dimensions_not_evaluated": [
"string"
]
},
"strengths": [
"string"
],
"gaps": [
"string"
],
"summary": "string"
}
Schema of the response body
{
"properties": {
"analysis_id": {
"type": "string",
"format": "uuid",
"title": "Analysis Id"
},
"candidate_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Candidate Id"
},
"scoring_version": {
"type": "string",
"title": "Scoring Version"
},
"notice_version": {
"type": "string",
"title": "Notice Version"
},
"as_of": {
"type": "string",
"format": "date",
"title": "As Of"
},
"overall_score": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Overall Score"
},
"fit_level": {
"type": "string",
"enum": [
"excellent",
"good",
"moderate",
"weak"
],
"title": "Fit Level"
},
"weights_used": {
"additionalProperties": {
"type": "number"
},
"propertyNames": {
"enum": [
"skills",
"experience",
"education",
"languages",
"location"
]
},
"type": "object",
"title": "Weights Used"
},
"dimension_scores": {
"items": {
"$ref": "#/components/schemas/DimensionScore"
},
"type": "array",
"title": "Dimension Scores"
},
"proxy_criteria": {
"items": {
"type": "string",
"enum": [
"location",
"education"
]
},
"type": "array",
"title": "Proxy Criteria",
"description": "Critères indirects (lieu, formation) qui ont pesé : poids > 0 et dimension évaluée."
},
"human_review_required": {
"type": "boolean",
"const": true,
"title": "Human Review Required",
"default": true
},
"explanation": {
"items": {
"type": "string"
},
"type": "array",
"title": "Explanation"
},
"minimization": {
"$ref": "#/components/schemas/MinimizationReport"
},
"strengths": {
"items": {
"type": "string"
},
"type": "array",
"title": "Strengths"
},
"gaps": {
"items": {
"type": "string"
},
"type": "array",
"title": "Gaps"
},
"summary": {
"type": "string",
"title": "Summary",
"default": ""
}
},
"type": "object",
"required": [
"analysis_id",
"scoring_version",
"notice_version",
"as_of",
"overall_score",
"fit_level",
"weights_used",
"dimension_scores",
"explanation",
"minimization"
],
"title": "CandidateAnalysis",
"description": "Analyse d'un candidat : aide à la décision, jamais un rejet."
}
POST /v1/analyze/batch¶
Analyze Batch
Description
Score up to 100 candidates against one job, best first.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
X-API-Key |
header | No |
Request body
{
"weights": {
"skills": 10.12,
"experience": 10.12,
"education": 10.12,
"languages": 10.12,
"location": 10.12
},
"anonymize": true,
"as_of": null,
"lang": "fr",
"job": {
"title": "string",
"description": "string",
"required_skills": [
"string"
],
"preferred_skills": [
"string"
],
"min_experience_years": null,
"required_languages": [
"string"
],
"required_education": null,
"location": null,
"remote_policy": null
},
"candidates": [
{
"id": null,
"firstname": null,
"lastname": null,
"email": null,
"phone": null,
"linkedin": null,
"raw_text": null,
"skills": [
"string"
],
"languages": [
"string"
],
"experiences": [
{
"company": "string",
"title": "string",
"location": "string",
"start_date": "string",
"end_date": "string",
"description": "string"
}
],
"diplomas": [
{
"school": "string",
"degree": "string",
"field_of_study": "string",
"start_date": "string",
"end_date": "string"
}
],
"certifications": [
{}
],
"location": null
}
]
}
Schema of the request body
{
"properties": {
"weights": {
"$ref": "#/components/schemas/ScoringWeights"
},
"anonymize": {
"type": "boolean",
"title": "Anonymize",
"description": "Retire le lieu (profil et expériences) pour tout le lot ; la localisation n'est alors pas évaluée.",
"default": false
},
"as_of": {
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "null"
}
],
"title": "As Of",
"description": "Date de référence du calcul de l'expérience ; défaut : date du jour (UTC), renvoyée dans l'analyse."
},
"lang": {
"type": "string",
"enum": [
"fr",
"en"
],
"title": "Lang",
"description": "Langue de l'explication.",
"default": "fr"
},
"job": {
"$ref": "#/components/schemas/JobDescription"
},
"candidates": {
"items": {
"$ref": "#/components/schemas/CandidateProfile"
},
"type": "array",
"maxItems": 100,
"minItems": 1,
"title": "Candidates"
}
},
"type": "object",
"required": [
"job",
"candidates"
],
"title": "AnalyzeBatchRequest",
"description": "Requête d'analyse de plusieurs candidats (100 au plus)."
}
Responses
{
"job_title": "string",
"candidates": [
{
"analysis_id": "edbb6810-c94b-4121-94fb-ff3896acbd9c",
"candidate_id": null,
"scoring_version": "string",
"notice_version": "string",
"as_of": "2022-04-13",
"overall_score": 10.12,
"fit_level": "excellent",
"weights_used": {},
"dimension_scores": [
{
"dimension": "skills",
"score": 10.12,
"weight": 10.12,
"evaluated": true,
"evidence": {
"matched": [
"string"
],
"missing": [
"string"
]
},
"rationale": "string",
"template_id": "string",
"details": "string"
}
],
"proxy_criteria": [
"location"
],
"human_review_required": true,
"explanation": [
"string"
],
"minimization": {
"ignored_fields": [
"string"
],
"dimensions_not_evaluated": [
"string"
]
},
"strengths": [
"string"
],
"gaps": [
"string"
],
"summary": "string"
}
],
"total_analyzed": 0
}
Schema of the response body
{
"properties": {
"job_title": {
"type": "string",
"title": "Job Title"
},
"candidates": {
"items": {
"$ref": "#/components/schemas/CandidateAnalysis"
},
"type": "array",
"title": "Candidates"
},
"total_analyzed": {
"type": "integer",
"title": "Total Analyzed"
}
},
"type": "object",
"required": [
"job_title",
"candidates",
"total_analyzed"
],
"title": "AnalyzeBatchResponse",
"description": "Réponse d'analyse batch (triée par score décroissant)."
}
POST /v1/analyze/competency-file¶
Analyze Competency File
Description
Score a competency file: the job's terms found in the text become the skills.
The text is read once and never stored or journaled; the other dimensions have no input, so those the job sets a criterion for are evaluated with nothing found.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
X-API-Key |
header | No |
Request body
{
"weights": {
"skills": 10.12,
"experience": 10.12,
"education": 10.12,
"languages": 10.12,
"location": 10.12
},
"anonymize": true,
"as_of": null,
"lang": "fr",
"job": {
"title": "string",
"description": "string",
"required_skills": [
"string"
],
"preferred_skills": [
"string"
],
"min_experience_years": null,
"required_languages": [
"string"
],
"required_education": null,
"location": null,
"remote_policy": null
},
"competency_text": "string"
}
Schema of the request body
{
"properties": {
"weights": {
"$ref": "#/components/schemas/ScoringWeights"
},
"anonymize": {
"type": "boolean",
"title": "Anonymize",
"description": "Retire le lieu (profil et expériences) pour tout le lot ; la localisation n'est alors pas évaluée.",
"default": false
},
"as_of": {
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "null"
}
],
"title": "As Of",
"description": "Date de référence du calcul de l'expérience ; défaut : date du jour (UTC), renvoyée dans l'analyse."
},
"lang": {
"type": "string",
"enum": [
"fr",
"en"
],
"title": "Lang",
"description": "Langue de l'explication.",
"default": "fr"
},
"job": {
"$ref": "#/components/schemas/JobDescription"
},
"competency_text": {
"type": "string",
"maxLength": 500000,
"minLength": 1,
"title": "Competency Text"
}
},
"type": "object",
"required": [
"job",
"competency_text"
],
"title": "CompetencyFileRequest",
"description": "Requête d'analyse d'un dossier de compétences (texte brut, jamais journalisé)."
}
Responses
{
"analysis_id": "9f96978d-27cc-4ad3-8383-beb359ead27b",
"candidate_id": null,
"scoring_version": "string",
"notice_version": "string",
"as_of": "2022-04-13",
"overall_score": 10.12,
"fit_level": "excellent",
"weights_used": {},
"dimension_scores": [
{
"dimension": "skills",
"score": 10.12,
"weight": 10.12,
"evaluated": true,
"evidence": {
"matched": [
"string"
],
"missing": [
"string"
]
},
"rationale": "string",
"template_id": "string",
"details": "string"
}
],
"proxy_criteria": [
"location"
],
"human_review_required": true,
"explanation": [
"string"
],
"minimization": {
"ignored_fields": [
"string"
],
"dimensions_not_evaluated": [
"string"
]
},
"strengths": [
"string"
],
"gaps": [
"string"
],
"summary": "string"
}
Schema of the response body
{
"properties": {
"analysis_id": {
"type": "string",
"format": "uuid",
"title": "Analysis Id"
},
"candidate_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Candidate Id"
},
"scoring_version": {
"type": "string",
"title": "Scoring Version"
},
"notice_version": {
"type": "string",
"title": "Notice Version"
},
"as_of": {
"type": "string",
"format": "date",
"title": "As Of"
},
"overall_score": {
"type": "number",
"maximum": 1.0,
"minimum": 0.0,
"title": "Overall Score"
},
"fit_level": {
"type": "string",
"enum": [
"excellent",
"good",
"moderate",
"weak"
],
"title": "Fit Level"
},
"weights_used": {
"additionalProperties": {
"type": "number"
},
"propertyNames": {
"enum": [
"skills",
"experience",
"education",
"languages",
"location"
]
},
"type": "object",
"title": "Weights Used"
},
"dimension_scores": {
"items": {
"$ref": "#/components/schemas/DimensionScore"
},
"type": "array",
"title": "Dimension Scores"
},
"proxy_criteria": {
"items": {
"type": "string",
"enum": [
"location",
"education"
]
},
"type": "array",
"title": "Proxy Criteria",
"description": "Critères indirects (lieu, formation) qui ont pesé : poids > 0 et dimension évaluée."
},
"human_review_required": {
"type": "boolean",
"const": true,
"title": "Human Review Required",
"default": true
},
"explanation": {
"items": {
"type": "string"
},
"type": "array",
"title": "Explanation"
},
"minimization": {
"$ref": "#/components/schemas/MinimizationReport"
},
"strengths": {
"items": {
"type": "string"
},
"type": "array",
"title": "Strengths"
},
"gaps": {
"items": {
"type": "string"
},
"type": "array",
"title": "Gaps"
},
"summary": {
"type": "string",
"title": "Summary",
"default": ""
}
},
"type": "object",
"required": [
"analysis_id",
"scoring_version",
"notice_version",
"as_of",
"overall_score",
"fit_level",
"weights_used",
"dimension_scores",
"explanation",
"minimization"
],
"title": "CandidateAnalysis",
"description": "Analyse d'un candidat : aide à la décision, jamais un rejet."
}
POST /v1/hr/analyses/{analysis_id}/decisions¶
Record Decision
Description
Journal a human decision; agreement with the score is computed here.
review_requested records a contest (GDPR art. 22(3)), revised the new review;
supersedes names the decision_id it replaces. Unknown, purged and other tenants'
analyses answer the same 404.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
analysis_id |
path | string | No | ||
X-API-Key |
header | No |
Request body
Schema of the request body
{
"properties": {
"decision": {
"type": "string",
"enum": [
"shortlisted",
"not_retained",
"on_hold",
"review_requested",
"revised"
],
"title": "Decision"
},
"reviewer_ref": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"title": "Reviewer Ref",
"description": "Identifiant opaque du relecteur chez le client ; pseudonymisé avant journalisation."
},
"supersedes": {
"anyOf": [
{
"type": "string",
"format": "uuid"
},
{
"type": "null"
}
],
"title": "Supersedes",
"description": "`decision_id` de la décision remplacée."
}
},
"type": "object",
"required": [
"decision",
"reviewer_ref"
],
"title": "DecisionRequest",
"description": "Décision humaine sur une analyse (spec §4.3)."
}
Responses
{
"decision_id": "f4fd8c93-bc50-4176-a366-2f9c361102ea",
"agrees_with_score": true,
"seconds_since_scoring": 0
}
Schema of the response body
{
"properties": {
"decision_id": {
"type": "string",
"format": "uuid",
"title": "Decision Id"
},
"agrees_with_score": {
"type": "boolean",
"title": "Agrees With Score"
},
"seconds_since_scoring": {
"type": "integer",
"title": "Seconds Since Scoring"
}
},
"type": "object",
"required": [
"decision_id",
"agrees_with_score",
"seconds_since_scoring"
],
"title": "DecisionResponse"
}
POST /v1/hr/subjects/ref¶
Subject Refs
Description
Pseudonymous reference of a candidate, one per month whose key still exists.
Input of audit-trail's POST /v1/gdpr/export (subject_type="resource_id"). Each
reference returned is journaled; Kong rate-limits this route harder.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
X-API-Key |
header | No |
Request body
Responses
PUT /v1/hr/settings¶
Put Settings
Description
Retention (6 to 60 months) and the per-tenant emergency stop, journaled.
Lowering the retention purges in the same transaction; raising it does not bring destroyed keys back.
Input parameters
| Parameter | In | Type | Default | Nullable | Description |
|---|---|---|---|---|---|
X-API-Key |
header | No |
Request body
Schema of the request body
{
"properties": {
"retention_months": {
"type": "integer",
"maximum": 60.0,
"minimum": 6.0,
"title": "Retention Months",
"description": "Conservation du journal RH, en mois (6 à 60)."
},
"scoring_enabled": {
"type": "boolean",
"title": "Scoring Enabled",
"description": "false = arrêt d'urgence : les routes d'analyse répondent 423."
}
},
"type": "object",
"required": [
"retention_months",
"scoring_enabled"
],
"title": "HrSettingsUpdate"
}
Responses
Schemas¶
AnalyzeBatchRequest¶
| Name | Type | Description |
|---|---|---|
anonymize |
boolean | Retire le lieu (profil et expériences) pour tout le lot ; la localisation n'est alors pas évaluée. |
as_of |
Date de référence du calcul de l'expérience ; défaut : date du jour (UTC), renvoyée dans l'analyse. | |
candidates |
Array<CandidateProfile> | |
job |
JobDescription | |
lang |
string | Langue de l'explication. |
weights |
ScoringWeights |
AnalyzeBatchResponse¶
| Name | Type | Description |
|---|---|---|
candidates |
Array<CandidateAnalysis> | |
job_title |
string | |
total_analyzed |
integer |
AnalyzeRequest¶
| Name | Type | Description |
|---|---|---|
anonymize |
boolean | Retire le lieu (profil et expériences) pour tout le lot ; la localisation n'est alors pas évaluée. |
as_of |
Date de référence du calcul de l'expérience ; défaut : date du jour (UTC), renvoyée dans l'analyse. | |
candidate |
CandidateProfile | |
job |
JobDescription | |
lang |
string | Langue de l'explication. |
weights |
ScoringWeights |
CandidateAnalysis¶
| Name | Type | Description |
|---|---|---|
analysis_id |
string(uuid) | |
as_of |
string(date) | |
candidate_id |
||
dimension_scores |
Array<DimensionScore> | |
explanation |
Array<string> | |
fit_level |
string | |
gaps |
Array<string> | |
human_review_required |
boolean | |
minimization |
MinimizationReport | |
notice_version |
string | |
overall_score |
number | |
proxy_criteria |
Array<string> | Critères indirects (lieu, formation) qui ont pesé : poids > 0 et dimension évaluée. |
scoring_version |
string | |
strengths |
Array<string> | |
summary |
string | |
weights_used |
CandidateProfile¶
| Name | Type | Description |
|---|---|---|
certifications |
Array<> | |
diplomas |
Array<Diploma> | |
email |
Ignoré (minimisation), jamais journalisé ; déprécié. | |
experiences |
Array<Experience> | |
firstname |
Ignoré (minimisation), jamais journalisé ; déprécié. | |
id |
Identifiant opaque du candidat chez le client (ni e-mail, ni entier séquentiel). Pseudonymisé avant journalisation. | |
languages |
Array<string> | |
lastname |
Ignoré (minimisation), jamais journalisé ; déprécié. | |
linkedin |
Ignoré (minimisation), jamais journalisé ; déprécié. | |
location |
||
phone |
Ignoré (minimisation), jamais journalisé ; déprécié. | |
raw_text |
Ignoré (minimisation), jamais journalisé ; déprécié. | |
skills |
Array<string> |
CompetencyFileRequest¶
| Name | Type | Description |
|---|---|---|
anonymize |
boolean | Retire le lieu (profil et expériences) pour tout le lot ; la localisation n'est alors pas évaluée. |
as_of |
Date de référence du calcul de l'expérience ; défaut : date du jour (UTC), renvoyée dans l'analyse. | |
competency_text |
string | |
job |
JobDescription | |
lang |
string | Langue de l'explication. |
weights |
ScoringWeights |
DecisionRequest¶
| Name | Type | Description |
|---|---|---|
decision |
string | |
reviewer_ref |
string | Identifiant opaque du relecteur chez le client ; pseudonymisé avant journalisation. |
supersedes |
`decision_id` de la décision remplacée. |
DecisionResponse¶
| Name | Type | Description |
|---|---|---|
agrees_with_score |
boolean | |
decision_id |
string(uuid) | |
seconds_since_scoring |
integer |
DimensionScore¶
| Name | Type | Description |
|---|---|---|
details |
string | Déprécié : reprend `rationale`. |
dimension |
string | |
evaluated |
boolean | |
evidence |
Evidence | |
rationale |
string | |
score |
number | |
template_id |
string | |
weight |
number | Poids appliqué, après renormalisation sur les dimensions évaluées. |
Diploma¶
| Name | Type | Description |
|---|---|---|
degree |
string | |
end_date |
string | |
field_of_study |
string | |
school |
string | |
start_date |
string |
Evidence¶
| Name | Type | Description |
|---|---|---|
matched |
Array<string> | |
missing |
Array<string> |
Experience¶
| Name | Type | Description |
|---|---|---|
company |
string | |
description |
string | |
end_date |
string | Même format ; vide, « present » ou « en cours » pour un poste en cours. |
location |
string | |
start_date |
string | AAAA ou AAAA-MM : premier jour du mois (janvier si l'année seule). |
title |
string |
HealthResponse¶
| Name | Type | Description |
|---|---|---|
scoring_version |
string | |
status |
string | |
version |
string |
HrSettings¶
| Name | Type | Description |
|---|---|---|
retention_months |
integer | |
scoring_enabled |
boolean |
HrSettingsUpdate¶
| Name | Type | Description |
|---|---|---|
retention_months |
integer | Conservation du journal RH, en mois (6 à 60). |
scoring_enabled |
boolean | false = arrêt d'urgence : les routes d'analyse répondent 423. |
HTTPValidationError¶
| Name | Type | Description |
|---|---|---|
detail |
Array<ValidationError> |
JobDescription¶
| Name | Type | Description |
|---|---|---|
description |
string | |
location |
||
min_experience_years |
||
preferred_skills |
Array<string> | |
remote_policy |
onsite | hybrid | remote. Common aliases (e.g. full-remote, télétravail, hybride, présentiel) are normalised; any other value is refused (422). remote: the location dimension is not evaluated. | |
required_education |
||
required_languages |
Array<string> | |
required_skills |
Array<string> | |
title |
string |
MinimizationReport¶
| Name | Type | Description |
|---|---|---|
dimensions_not_evaluated |
Array<string> | Processing dimensions skipped because of that minimisation. |
ignored_fields |
Array<string> | Input paths received then dropped before processing (e.g. `email`, `experiences[].location`). |
ScoringWeights¶
| Name | Type | Description |
|---|---|---|
education |
number | |
experience |
number | |
languages |
number | |
location |
number | |
skills |
number |
SubjectRef¶
| Name | Type | Description |
|---|---|---|
period |
string | Mois de la clé, AAAA-MM. |
subject_ref |
string |
SubjectRefRequest¶
| Name | Type | Description |
|---|---|---|
subject_id |
string | Le `CandidateProfile.id` des analyses. |
SubjectRefResponse¶
| Name | Type | Description |
|---|---|---|
subject_refs |
Array<SubjectRef> |
ValidationError¶
| Name | Type | Description |
|---|---|---|
ctx |
||
input |
||
loc |
Array<> | |
msg |
string | |
type |
string |