{"openapi":"3.1.0","info":{"title":"API partenaire tview","version":"1.3.1","description":"API serveur-à-serveur pour intégrer les processus de recrutement tview aux plateformes partenaires et sites d’offres.\n\n## Modèle de données\n\n- **Project** — le conteneur de recrutement de niveau supérieur. Créez un projet par rôle ou cycle de recrutement, et non par candidat ou par sélection.\n- **Étapes du pipeline** : étapes ordonnées au sein d'un projet. Les valeurs persistantes de l'étape API `type` sont désormais `screening`, `coding_task`, `video_interview`, `case_study`, `documents_upload` ou `custom`.\n- **Candidature** — le parcours d'un candidat à travers un projet.\n- **Résultat de l'étape** — par application, état par étape : réponses, soumissions de code, évaluations et enregistrements.\n- **Séance de formation aux entretiens** : entretien pratique avec un candidat généré à partir d'un projet, d'une offre d'emploi ou d'une publication brute. Il ne fait pas partie du pipeline de recrutement évalué, à moins qu'un partenaire ne le mappe dans son propre flux.\n\n## Schéma d’intégration recommandé\n\n1. Créez un projet pour chaque rôle distinct ou cycle de recrutement.\n2. Configurez son pipeline en une ou plusieurs étapes.\n3. Invitez des candidats à participer au projet. Chaque candidat reçoit une candidature par projet.\n4. Laissez les candidats terminer les étapes du pipeline ; les résultats et les évaluations apparaissent sur les résultats des étapes.\n\nÉvitez de créer un projet pour chaque sélection — les sélections sont des étapes, pas des entités autonomes.\n\n## Types d’étapes du parcours\n\n- `screening` — questionnaire/étape de présélection. Les questions résident dans `config.questions` ou peuvent être composées par candidature via `/api/v1/applications/{id}/screening-compose`.\n- `coding_task` — tâche de programmation ou tâche technique. Le corps de la tâche principale se trouve généralement dans `config.challenge` ; les champs facultatifs incluent `config.language`, `config.difficulty` et `config.instructions`.\n- `video_interview` — étape d'entretien vidéo. Les questions vivent dans `config.questions` ; `config.recordingEnabled=false` désactive l'enregistrement de session.\n- `case_study` — étape d'étude de cas. Utilisez `config.brief` et `config.format` en option (`written`, `presentation` ou `both`).\n- `documents_upload` — étape de téléchargement du document. Utilisez `config.requiredDocuments`, `config.maxFileSizeMb`, `config.allowMultiple` et `config.acceptedFormats`.\n- `custom` — point d'extension pour marches non standard. Utilisez `config.customType` pour un comportement personnalisé lisible par machine.\n\nCompatibilité ascendante : les charges utiles utilisant l'ancienne représentation `type: custom` avec `config.subType: case_study` ou `config.subType: documents_upload` sont toujours acceptées et normalisées selon les nouveaux types de première classe.\n\n## Authentification\n\nClés API porteur (`tv_live_*` / `tv_test_*`). Les réponses authentifiées incluent `X-Request-Id`, `X-Correlation-Id`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` et `X-RateLimit-Reset`.\n\n## Idempotence\n\nPOST `/api/v1/projects`, `/api/v1/projects/{id}/generate-pipeline`, `/api/v1/projects/{id}/candidates`, `/api/v1/projects/{id}/candidates/bulk`, `/api/v1/applications/{id}/evaluate`, `/api/v1/interview-training/sessions`, `/api/v1/interview-training/sessions/{id}/answers`, `/api/v1/interview-training/sessions/{id}/summary` et `/api/v1/webhooks/test` prennent en charge l’en-tête `Idempotency-Key`.\n\n## Parcours de candidature hébergé par le partenaire\n\n- créer des sessions de candidature tokenisées sans inscription/connexion du candidat\n- marquer les profils de candidats comme fournis par les partenaires et ignorer la collecte de profils hébergés\n- consentement du partenaire du magasin\n- personnaliser la copie d'écran de l'application hébergée par application avec `applicationPage`\n- basculez éventuellement le flux hébergé en mode marque blanche Vanilla Shadcn avec `hostedBranding` par application\n- faire écho à `externalCandidateId` et au public `metadata` dans les API d'application et les webhooks\n\n## Composition de la sélection\n\n`POST /api/v1/applications/{id}/screening-compose` compose des questions manuelles et générées pour chaque candidature. Utilisez `stepId` lorsqu’une candidature comporte plusieurs étapes de présélection. Les réponses de présélection conservent une copie de la question afin que les modifications ultérieures ne réécrivent pas l’historique.\n\n## Formation à l’entretien\n\n- créer des séances de pratique à partir d'un projet, d'une offre d'emploi ou d'un texte brut d'offre d'emploi\n- servir la prochaine question sans réponse pour les flux de candidats intégrés\n- soumettre les réponses des candidats aux pratiques et renvoyer les commentaires du coaching\n- générer un rapport de préparation final pour l'affichage spécifique\n\n## Points de terminaison facturés à l’usage\n\n- `POST /api/v1/projects/{id}/generate-pipeline` → crédit de génération\n- `POST /api/v1/applications/{id}/evaluate` → crédit de sélection/évaluation du code\n- `POST /api/v1/interview-training/sessions` → crédit de génération lorsque la génération d'IA réussit\n- `POST /api/v1/interview-training/sessions/{id}/answers` → crédit d'évaluation de dépistage lorsque le feedback de l'IA réussit\n- `POST /api/v1/interview-training/sessions/{id}/summary` → crédit récapitulatif lorsque le résumé AI réussit\n\n## Webhooks\n\nContrat de charge utile : `{ event, timestamp, data }` avec signature HMAC SHA-256 en `X-Tview-Signature`.\n\nAvailable application et usage events: `application.created`, `application.started`, `application.completed`, `application.decided`, `application.stage_changed`, `screening.submitted`, `screening.evaluated`, `code.submitted`, `code.evaluated`, `interview.started`, `interview.completed`, `balance.low`, `balance.depleted`.\n\n`application.decided` is sent when a recruiter moves a candidate forward, rejects them, records a withdrawal or reopens the application. `data.decision` carries `type` (`advanced`, `rejected`, `withdrawn`, `reopened`), the resulting `status`, `reason` et `decidedAt`. Internal recruiter notes are never included.\n\n`application.stage_changed` is sent when a candidate moves between hiring stages (for example from AI screening to Interview). `data.stage` carries `from` et `to`, each with `id`, `kind` (`new`, `screening`, `interview`, `offer`, `hired`) and `name`.\n\n## Métadonnées\n\n`metadata.__tview` est réservé à un usage interne et ne doit pas être envoyé par les partenaires."},"servers":[{"url":"https://tview.work","description":"API de production (primaire)"},{"url":"https://jobs.tview.work","description":"API de production (hôte candidat)"},{"url":"http://localhost:3000","description":"Développement local"}],"externalDocs":{"description":"Documents complémentaires et notes d'intégration","url":"https://tview.work/docs"},"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Clé API partenaire au format `tv_live_*` ou `tv_test_*`"}},"parameters":{"PageParam":{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},"LimitParam":{"name":"limit","in":"query","schema":{"type":"integer","default":20,"minimum":1,"maximum":100}},"ProjectId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"ApplicationId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"CandidateId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"WebhookId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"InterviewTrainingSessionId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request payload"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"title"},"message":{"type":"string","example":"Required"},"code":{"type":"string","example":"invalid_type"}}}}}}}},"PaginationMeta":{"type":"object","properties":{"total":{"type":"integer","example":42},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":20}}},"Project":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"roleType":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","active","archived","closed"]},"isPublished":{"type":"boolean"},"defaultHostedBranding":{"$ref":"#/components/schemas/HostedBrandingResolved"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ProjectReadiness":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["draft","active","archived","closed"]},"isPublished":{"type":"boolean"},"hasScreeningStep":{"type":"boolean"},"hasDefaultHostedBranding":{"type":"boolean"},"defaultHostedBranding":{"$ref":"#/components/schemas/HostedBrandingResolved"},"isWhitelabelActive":{"type":"boolean"},"effectiveHostedBranding":{"$ref":"#/components/schemas/HostedBrandingResolved"},"hasActiveJobOffer":{"type":"boolean"},"issues":{"type":"array","items":{"type":"string"}}}},"PipelineStep":{"type":"object","description":"Étape de pipeline de recrutement persistante. `case_study` et `documents_upload` sont des types de marches de première classe. Les charges utiles existantes `type: custom` et `config.subType` pour ces étapes sont toujours acceptées et normalisées.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["screening","coding_task","video_interview","case_study","documents_upload","custom"]},"title":{"type":"string"},"order":{"type":"integer"},"config":{"type":"object","additionalProperties":true,"description":"Configuration spécifique à l'étape. Pour video_interview, RecordingEnabled est défini par défaut sur true ; définissez RecordingEnabled=false pour désactiver l’enregistrement de session. Pour les études de cas, utilisez type=case_study avec config.brief et config.format facultatif. Pour les téléchargements de documents, utilisez type=documents_upload avec config.requiredDocuments, config.maxFileSizeMb, config.allowMultiple et config.acceptedFormats.","properties":{"recordingEnabled":{"type":"boolean","default":true},"subType":{"type":"string","enum":["case_study","documents_upload"],"deprecated":true,"description":"Compatibilité héritée uniquement. Préférez les valeurs de type step de première classe."},"customType":{"type":"string","example":"manual_review"},"brief":{"type":"string","description":"Résumé d'étude de cas pour type=case_study"},"format":{"type":"string","enum":["written","presentation","both"]},"requiredDocuments":{"type":"array","items":{"type":"string"},"description":"Noms de documents requis pour type=documents_upload"},"maxFileSizeMb":{"type":"integer"},"allowMultiple":{"type":"boolean"},"acceptedFormats":{"type":"string","example":".pdf,.doc,.docx,.txt,.zip"},"questions":{"type":"array","items":{},"description":"Questions de sélection ou d'entretien"},"challenge":{"type":"string","description":"Corps de défi des tâches de codage"},"instructions":{"type":"string"},"durationMinutes":{"type":"integer"}}},"isRequired":{"type":"boolean"}}},"GeneratedPipelineStep":{"type":"object","description":"Nœud de pipeline généré par l'IA. `type` est le type d'API/base de données persistant. `nodeType` reflète le nœud sémantique généré et est conservé pour les clients qui distinguent les formes générées et persistantes.","properties":{"type":{"type":"string","enum":["screening","coding_task","video_interview","case_study","documents_upload","custom"]},"nodeType":{"type":"string","enum":["screening","coding_task","video_interview","case_study","documents_upload","custom"]},"title":{"type":"string"},"description":{"type":"string"},"isRequired":{"type":"boolean"},"config":{"type":"object","additionalProperties":true}}},"CandidateInvite":{"type":"object","required":["email","firstName","lastName"],"properties":{"email":{"type":"string","format":"email"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"cvText":{"type":"string"},"cvUrl":{"type":"string","format":"uri"},"externalCandidateId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"profileCollectionMode":{"type":"string","enum":["hosted","partner_provided"]},"partnerProvidedConsent":{"type":"object","additionalProperties":true,"properties":{"dataProcessing":{"type":"boolean"},"aiProcessing":{"type":"boolean"},"recording":{"type":"boolean"},"profileSharing":{"type":"boolean"},"source":{"type":"string"},"collectedAt":{"type":"string","format":"date-time"},"metadata":{"type":"object","additionalProperties":true}}},"profile":{"$ref":"#/components/schemas/CandidateProfileUpsert"},"applicationPage":{"$ref":"#/components/schemas/ApplicationPageInput"},"hostedBranding":{"$ref":"#/components/schemas/HostedBrandingInput"}}},"ApplicationPageInput":{"type":"object","description":"Remplacements de copie d'écran d'application hébergée par application. Prend en charge la copie brute ou les modèles avec des variables.","properties":{"locale":{"type":"string","enum":["en","pl"]},"title":{"type":"string"},"subtitle":{"type":"string"},"description":{"type":"string"},"profileNotice":{"type":"string"},"consentNotice":{"type":"string"},"ctaLabel":{"type":"string"},"titleTemplate":{"type":"string"},"subtitleTemplate":{"type":"string"},"descriptionTemplate":{"type":"string"},"profileNoticeTemplate":{"type":"string"},"consentNoticeTemplate":{"type":"string"},"variables":{"type":"object","additionalProperties":true},"labels":{"type":"object","properties":{"applicationHeader":{"type":"string"},"processHeader":{"type":"string"},"profileSectionTitle":{"type":"string"},"consentSectionTitle":{"type":"string"}}}}},"ApplicationPageResolved":{"type":"object","description":"Résolution de la copie d'écran de l'application hébergée renvoyée par les API de l'application après l'application des modèles/valeurs par défaut.","properties":{"locale":{"type":"string","enum":["en","pl"]},"title":{"type":"string"},"subtitle":{"type":"string"},"description":{"type":"string"},"profileNotice":{"type":"string"},"consentNotice":{"type":"string"},"ctaLabel":{"type":"string"},"labels":{"type":"object","properties":{"applicationHeader":{"type":"string"},"processHeader":{"type":"string"},"profileSectionTitle":{"type":"string"},"consentSectionTitle":{"type":"string"}}}}},"HostedBrandingInput":{"type":"object","description":"Remplacements de la marque hébergée par application. Utilisez `mode=whitelabel` pour restituer le flux hébergé avec un shell neutre de style shadcn et un logo/couleurs de partenaire en option.","properties":{"mode":{"type":"string","enum":["default","whitelabel"]},"logoUrl":{"type":"string","format":"uri"},"companyName":{"type":"string"},"primaryColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"},"accentColor":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"}}},"HostedBrandingResolved":{"type":"object","description":"Résolution de la marque hébergée renvoyée par les API d'application après l'application des valeurs par défaut/de secours.","properties":{"mode":{"type":"string","enum":["default","whitelabel"]},"logoUrl":{"type":"string","format":"uri","nullable":true},"companyName":{"type":"string","nullable":true},"primaryColor":{"type":"string","nullable":true},"accentColor":{"type":"string","nullable":true},"isWhitelabel":{"type":"boolean"}}},"ScreeningQuestionEntry":{"type":"object","description":"Entrée de résultat de présélection au niveau des questions, utilisée dans les API de candidature et les webhooks de présélection.","properties":{"questionId":{"type":"string"},"source":{"type":"string","enum":["manual","generated"]},"externalQuestionId":{"type":"string","nullable":true},"text":{"type":"string"},"answer":{"nullable":true},"score":{"type":"number","nullable":true},"metadata":{"type":"object","additionalProperties":true,"nullable":true}}},"ScreeningComposeRequest":{"type":"object","properties":{"stepId":{"type":"string","format":"uuid"},"locale":{"type":"string","enum":["en","pl"]},"manualQuestions":{"type":"array","items":{"type":"object","properties":{"externalQuestionId":{"type":"string"},"text":{"type":"string"},"type":{"type":"string","enum":["scale","single_choice","multiple_choice","ordering","open"]},"options":{"type":"array","items":{"type":"string"}},"scaleMin":{"type":"integer"},"scaleMax":{"type":"integer"},"scaleMinLabel":{"type":"string"},"scaleMaxLabel":{"type":"string"},"isRequired":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":true}}}},"generatedQuestions":{"type":"object","properties":{"enabled":{"type":"boolean"},"count":{"type":"integer"},"basedOn":{"type":"array","items":{"type":"string"}},"instructions":{"type":"string"}}},"mergeStrategy":{"type":"string","enum":["manual_first","generated_first","interleave"]},"deduplicate":{"type":"boolean"},"replaceExisting":{"type":"boolean"}}},"CandidateProfileUpsert":{"type":"object","properties":{"headline":{"type":"string","nullable":true},"bio":{"type":"string","nullable":true},"skills":{"type":"array","items":{"type":"string"}},"experienceYears":{"type":"integer","nullable":true},"cvUrl":{"type":"string","format":"uri","nullable":true},"linkedinUrl":{"type":"string","format":"uri","nullable":true},"githubUrl":{"type":"string","format":"uri","nullable":true}}},"InterviewTrainingSessionCreate":{"type":"object","description":"Fournissez exactement l’un des éléments suivants : projectId, jobOfferId ou postingText.","properties":{"projectId":{"type":"string","format":"uuid"},"jobOfferId":{"type":"string","format":"uuid"},"postingText":{"type":"string","minLength":100,"maxLength":50000},"title":{"type":"string","maxLength":500},"roleType":{"type":"string","maxLength":100},"locale":{"type":"string","enum":["en","pl"],"default":"en"},"questionCount":{"type":"integer","minimum":3,"maximum":12,"default":6}}},"InterviewTrainingQuestion":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["hr","technical","experience","situational"]},"text":{"type":"string"},"expectedSignals":{"type":"array","items":{"type":"string"}}}},"InterviewTrainingFeedback":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100},"summary":{"type":"string"},"strengths":{"type":"array","items":{"type":"string"}},"improvements":{"type":"array","items":{"type":"string"}},"suggestedAnswer":{"type":"string"}}},"InterviewTrainingAnswerCreate":{"type":"object","required":["questionId","answerText"],"properties":{"questionId":{"type":"string"},"answerText":{"type":"string","maxLength":20000}}},"InterviewTrainingAnswer":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sessionId":{"type":"string","format":"uuid"},"questionId":{"type":"string"},"questionIndex":{"type":"integer"},"questionText":{"type":"string"},"answerText":{"type":"string"},"feedback":{"$ref":"#/components/schemas/InterviewTrainingFeedback"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"InterviewTrainingSummary":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100},"readiness":{"type":"string","enum":["low","medium","high"]},"summary":{"type":"string"},"strengths":{"type":"array","items":{"type":"string"}},"gaps":{"type":"array","items":{"type":"string"}},"nextSteps":{"type":"array","items":{"type":"string"}}}},"InterviewTrainingProgress":{"type":"object","properties":{"answered":{"type":"integer"},"total":{"type":"integer"},"completed":{"type":"boolean"}}},"InterviewTrainingSession":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"projectId":{"type":"string","format":"uuid","nullable":true},"jobOfferId":{"type":"string","format":"uuid","nullable":true},"sourceType":{"type":"string","enum":["project","job_offer","raw_text"]},"status":{"type":"string","enum":["active","completed"]},"title":{"type":"string"},"roleType":{"type":"string","nullable":true},"locale":{"type":"string","enum":["en","pl"]},"questions":{"type":"array","items":{"$ref":"#/components/schemas/InterviewTrainingQuestion"}},"summary":{"anyOf":[{"$ref":"#/components/schemas/InterviewTrainingSummary"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time","nullable":true}}},"ShortlistCandidate":{"type":"object","required":["applicationId","overall","overallLower","overallUpper","coverage","gateStatus","conflicts"],"properties":{"applicationId":{"type":"string","format":"uuid"},"overall":{"type":"number","example":71.25},"overallLower":{"type":"number","example":66.5},"overallUpper":{"type":"number","example":76},"coverage":{"type":"number","minimum":0,"maximum":1,"description":"Part des compétences de la rubrique portant des preuves"},"gateStatus":{"type":"string","enum":["pass","failed","insufficient_evidence"]},"conflicts":{"type":"array","items":{"type":"string"},"description":"Clés de compétences avec preuves contradictoires"},"rank":{"type":"integer","minimum":1,"description":"Position basée sur 1 parmi les candidats classés. Absent sur les candidats épinglés, qui sont en tête de liste."}}},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["application.created","application.started","application.completed","application.decided","application.stage_changed","screening.submitted","screening.evaluated","interview.started","interview.completed","code.submitted","code.evaluated","balance.low","balance.depleted","test.ping"]}},"secret":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"HealthChecks":{"type":"object","properties":{"database":{"type":"boolean"},"blob":{"type":"boolean"},"ai":{"type":"boolean"},"tavus":{"type":"boolean"},"stripe":{"type":"boolean"},"workos":{"type":"boolean"}}}},"responses":{"Unauthorized":{"description":"Clé API manquante ou invalide","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request payload"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"title"},"message":{"type":"string","example":"Required"},"code":{"type":"string","example":"invalid_type"}}}}}}}}}}},"ValidationError":{"description":"Échec de la validation de la demande","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request payload"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"title"},"message":{"type":"string","example":"Required"},"code":{"type":"string","example":"invalid_type"}}}}}}}}}}},"Forbidden":{"description":"Le compte partenaire est suspendu","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request payload"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"title"},"message":{"type":"string","example":"Required"},"code":{"type":"string","example":"invalid_type"}}}}}}}}}}},"NotFound":{"description":"Ressource introuvable","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request payload"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"title"},"message":{"type":"string","example":"Required"},"code":{"type":"string","example":"invalid_type"}}}}}}}}}}},"RateLimited":{"description":"Limite de débit dépassée","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Invalid request payload"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"title"},"message":{"type":"string","example":"Required"},"code":{"type":"string","example":"invalid_type"}}}}}}}}}}}}},"paths":{"/api/v1/health":{"get":{"summary":"État de santé","tags":["Health"],"security":[],"responses":{"200":{"description":"Résultat du contrôle de santé","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"checks":{"$ref":"#/components/schemas/HealthChecks"}}}}}},"503":{"description":"Service dégradé","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"checks":{"$ref":"#/components/schemas/HealthChecks"}}}}}}}}},"/api/v1/ready":{"get":{"summary":"État de préparation","tags":["Health"],"security":[],"responses":{"200":{"description":"Le service est prêt","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ready"},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"database":{"type":"boolean"},"env":{"type":"boolean"}}}}}}}},"503":{"description":"Le service n'est pas prêt","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"not_ready"},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"database":{"type":"boolean"},"env":{"type":"boolean"}}}}}}}}}}},"/api/v1/projects":{"get":{"summary":"Liste des projets","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","active","archived","closed"]}}],"responses":{"200":{"description":"Liste des projets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Project"}},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"summary":"Créer un projet","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"roleType":{"type":"string"},"defaultHostedBranding":{"$ref":"#/components/schemas/HostedBrandingInput"},"pipeline":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStep"}}}}}}},"responses":{"201":{"description":"Projet créé","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Project"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/projects/{id}":{"get":{"summary":"Obtenir le projet","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"responses":{"200":{"description":"Détails du projet","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/Project"},{"type":"object","properties":{"pipeline":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStep"}},"candidateCount":{"type":"integer"}}}]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"summary":"Mettre à jour le projet","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string","nullable":true},"roleType":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","active","archived","closed"]},"isPublished":{"type":"boolean"},"defaultHostedBranding":{"anyOf":[{"$ref":"#/components/schemas/HostedBrandingInput"},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Projet mis à jour","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Project"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Projet d'archives","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"responses":{"200":{"description":"Projet archivé","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","example":"archived"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/projects/{id}/readiness":{"get":{"summary":"Préparez votre projet","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"responses":{"200":{"description":"Résumé de l'état de préparation du projet","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProjectReadiness"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/projects/{id}/pipeline":{"get":{"summary":"Répertorier les étapes du pipeline","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"responses":{"200":{"description":"Étapes du pipeline","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStep"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"summary":"Remplacer le pipeline","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["steps"],"properties":{"steps":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStep"}}}}}}},"responses":{"200":{"description":"Pipeline mis à jour","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStep"}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Une étape de pipeline supprimée est toujours référencée par une application","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/projects/{id}/generate-pipeline":{"post":{"summary":"Générer un pipeline d'IA","description":"Génère une proposition de pipeline. Les étapes renvoyées incluent `type` persistant plus `nodeType` ; `case_study` et `documents_upload` sont des types de marches de première classe.","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string"},"roleType":{"type":"string"}}}}}},"responses":{"200":{"description":"Proposition de pipeline générée","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"steps":{"type":"array","items":{"$ref":"#/components/schemas/GeneratedPipelineStep"}}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/projects/{id}/context":{"get":{"summary":"Répertorier les documents contextuels du projet","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"responses":{"200":{"description":"Enregistrements de contexte","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Télécharger le contexte du projet","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","name"],"properties":{"type":{"type":"string","enum":["job_spec","rubric","requirements","other"]},"name":{"type":"string"},"content":{"type":"string"},"fileUrl":{"type":"string","format":"uri"}}}},"multipart/form-data":{"schema":{"type":"object","required":["type","name"],"properties":{"type":{"type":"string","enum":["job_spec","rubric","requirements","other"]},"name":{"type":"string"},"content":{"type":"string"},"fileUrl":{"type":"string","format":"uri"},"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":"Contexte stocké","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/projects/{id}/apply-url":{"get":{"summary":"Obtenir un projet public, postuler, lien permanent","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"}],"responses":{"200":{"description":"Lien permanent public destiné aux candidats sur l'hébergeur des offres d'emploi","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"kind":{"type":"string","enum":["offer_permalink","marketplace_fallback"]}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/projects/{id}/candidates":{"get":{"summary":"Lister les candidats au projet","description":"Répertorie les paires candidat/candidat pour un projet. Chaque ligne inclut le `metadata` public ainsi que tous les remplacements `applicationPage` et `hostedBranding` résolus par application.","tags":["Candidates"],"parameters":[{"$ref":"#/components/parameters/ProjectId"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"},{"name":"status","in":"query","schema":{"type":"string","enum":["new","invited","in_progress","completed","rejected","accepted","withdrawn"]}}],"responses":{"200":{"description":"Liste des candidats","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Créer une session de candidature tokenisée","description":"Crée ou réutilise un couple candidat/candidature et renvoie un `applyUrl` hébergé. Prend en charge les données de profil fournies par les partenaires, le consentement, les métadonnées, les remplacements de copie d'écran hébergés par application via `applicationPage` et les thèmes en marque blanche hébergés via `hostedBranding`.","tags":["Candidates"],"parameters":[{"$ref":"#/components/parameters/ProjectId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateInvite"}}}},"responses":{"200":{"description":"Candidat invité","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"candidateId":{"type":"string","format":"uuid"},"applicationId":{"type":"string","format":"uuid"},"token":{"type":"string"},"applyUrl":{"type":"string","format":"uri"},"externalCandidateId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"profileCollectionMode":{"type":"string","enum":["hosted","partner_provided"]},"partnerProvidedConsent":{"type":"object","additionalProperties":true},"applicationPage":{"$ref":"#/components/schemas/ApplicationPageResolved"},"hostedBranding":{"$ref":"#/components/schemas/HostedBrandingResolved"}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/ValidationError"}}}},"/api/v1/projects/{id}/candidates/bulk":{"post":{"summary":"Inviter des candidats en masse","description":"Crée ou réutilise des paires candidat/candidature en masse. Chaque résultat réussi inclut le `applyUrl` tokenisé, le `metadata` public et le `applicationPage`/`hostedBranding` résolu pour cette application.","tags":["Candidates"],"parameters":[{"$ref":"#/components/parameters/ProjectId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["candidates"],"properties":{"candidates":{"type":"array","items":{"$ref":"#/components/schemas/CandidateInvite"}}}}}}},"responses":{"200":{"description":"Résultat de l'importation groupée","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/ValidationError"}}}},"/api/v1/projects/{id}/shortlist":{"get":{"summary":"Obtenir la liste restreinte des projets","description":"Renvoie la liste déterministe d'un projet : les candidats épinglés d'abord, puis les candidats classés numérotés à partir de 1. Les candidats bloqués par une porte défaillante ou par des preuves minces ne sont pas renvoyés. Les scores sont sur une échelle de 0 à 100 ; `overallLower` / `overallUpper` délimitent l'intervalle de score et ne sont pas limités à cette plage. Les réponses ne portent aucune identité de candidat – rejoignez-nous sur `applicationId`.","tags":["Projects"],"parameters":[{"$ref":"#/components/parameters/ProjectId"},{"name":"mode","in":"query","description":"Signal de classement. `lcb` (par défaut) trie sur la limite de confiance inférieure, de sorte qu'un score confiant surpasse un score spéculatif ; `mean` trie sur l'estimation ponctuelle.","schema":{"type":"string","enum":["lcb","mean"],"default":"lcb"}}],"responses":{"200":{"description":"Liste restreinte des projets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","required":["mode","generatedAt","candidates"],"properties":{"mode":{"type":"string","enum":["lcb","mean"]},"generatedAt":{"type":"string","format":"date-time"},"candidates":{"type":"array","items":{"$ref":"#/components/schemas/ShortlistCandidate"}}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/applications/{id}":{"get":{"summary":"Obtenir les détails de la candidature","description":"Renvoie l'état de la candidature, la copie de la page de candidature hébergée, la marque blanche hébergée, les résultats au niveau des étapes et la sélection `questionEntries` qui préserve l'origine de la question (`manual` vs `generated`). Les candidatures complétées exposent également `recording`, `recordingUrl` et `transcript` lorsqu'un enregistrement/transcription d'entretien vidéo est disponible. Les URL d'enregistrement sont signées, expirent après une heure et peuvent être ouvertes par navigateur sans en-têtes d'API partenaire.","tags":["Applications"],"parameters":[{"$ref":"#/components/parameters/ApplicationId"}],"responses":{"200":{"description":"Détails de la candidature","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/applications/{id}/screening-compose":{"post":{"summary":"Composez des questions de sélection étape par étape pour une candidature","description":"Compose un ensemble de questions de sélection à partir de questions manuelles fournies par le partenaire et de questions facultatives basées sur le profil générées par tview. Si une candidature comporte plusieurs étapes de sélection, transmettez `stepId` pour cibler la bonne étape. Les instantanés de filtrage soumis sont immuables et conservés lors des lectures/webhooks ultérieurs.","tags":["Applications"],"parameters":[{"$ref":"#/components/parameters/ApplicationId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreeningComposeRequest"}}}},"responses":{"200":{"description":"Ensemble de questions composées","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"stepId":{"type":"string","format":"uuid"},"questionSetId":{"type":"string"},"generationVersion":{"type":"integer"},"questions":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/ValidationError"}}}},"/api/v1/applications/{id}/recording":{"get":{"summary":"Obtenir l'URL d'enregistrement de l'entretien signé","description":"Renvoie une URL signée ouvrable par le navigateur pour les enregistrements d'application terminés. L'URL signée expire après une heure et ne nécessite pas d'en-têtes d'API partenaire lorsqu'elle est ouverte dans un navigateur.","tags":["Applications"],"parameters":[{"$ref":"#/components/parameters/ApplicationId"}],"responses":{"200":{"description":"URL d'enregistrement","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"source":{"type":"string","enum":["tavus","browser"]},"contentType":{"type":"string","enum":["video/mp4","video/webm"]},"expiresAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/applications/{id}/recording/browser":{"get":{"summary":"Diffusez un enregistrement terminé du navigateur","description":"Diffuse le dernier enregistrement d’interview vidéo terminé à partir d’un stockage privé. Ce point de terminaison nécessite une clé de support d'API partenaire et la propriété de l'application ; malgré son nom, il ne s'agit pas d'une URL de navigateur non authentifiée. Servez-le par proxy via votre serveur ou obtenez une URL signée de courte durée à partir du point de terminaison d'enregistrement pour une lecture directe dans le navigateur. Renvoie la vidéo/webm (ou le type MIME enregistré) avec Cache-Control : privé, sans magasin. Si un enregistrement finalisé n'est pas disponible, les morceaux stockés sont diffusés dans l'ordre.","tags":["Applications"],"parameters":[{"$ref":"#/components/parameters/ApplicationId"}],"responses":{"200":{"description":"Flux d'enregistrement privé","content":{"video/webm":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/applications/{id}/recording/signed":{"get":{"summary":"Enregistrement d'entretien ouvert et signé","description":"Cible d'URL d'enregistrement signée publique et de courte durée. Les partenaires doivent obtenir cette URL auprès de `GET /api/v1/applications/{id}` ou `GET /api/v1/applications/{id}/recording` ; ne le construisez pas manuellement.","tags":["Applications"],"security":[],"parameters":[{"$ref":"#/components/parameters/ApplicationId"},{"name":"expires","in":"query","required":true,"schema":{"type":"integer"}},{"name":"signature","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Flux d'enregistrement du navigateur","content":{"video/webm":{"schema":{"type":"string","format":"binary"}}}},"302":{"description":"Redirection vers l'enregistrement hébergé"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/applications/{id}/evaluate":{"post":{"summary":"Évaluer l'étape de candidature","tags":["Applications"],"parameters":[{"$ref":"#/components/parameters/ApplicationId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["stepId"],"properties":{"stepId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"Résultat de l'évaluation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"score":{"type":"number"},"evaluation":{"type":"object","description":"Always carries summary, strengths, weaknesses et recommendation, plus correctness and codeQuality for coding steps. A project scored against a rubric additionally returns mode=\"two_stage\" with rubric, competencies and criterionScores; single-shot evaluations omit those keys.","additionalProperties":true,"properties":{"mode":{"type":"string","enum":["two_stage"]},"summary":{"type":"string"},"recommendation":{"type":"string"}}}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/candidates/{id}":{"get":{"summary":"Obtenez le profil du candidat","description":"Renvoie l'enregistrement du candidat, le profil facultatif fourni par le partenaire et toutes les candidatures visibles par le partenaire. Chaque application fait écho aux valeurs publiques `metadata` ainsi qu'aux valeurs résolues `applicationPage` et `hostedBranding`.","tags":["Candidates"],"parameters":[{"$ref":"#/components/parameters/CandidateId"}],"responses":{"200":{"description":"Profil du candidat et candidatures","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/candidates/{id}/profile":{"put":{"summary":"Insérer le profil de candidat fourni par le partenaire","tags":["Candidates"],"parameters":[{"$ref":"#/components/parameters/CandidateId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateProfileUpsert"}}}},"responses":{"200":{"description":"Profil du candidat inséré","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/usage":{"get":{"summary":"Résumé de l'utilisation actuelle","tags":["Usage"],"responses":{"200":{"description":"Utilisation du mois en cours","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/usage/history":{"get":{"summary":"Historique d'utilisation","tags":["Usage"],"parameters":[{"name":"months","in":"query","schema":{"type":"integer","default":6,"minimum":1,"maximum":24}}],"responses":{"200":{"description":"Historique d'utilisation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/balance":{"get":{"summary":"Solde courant","tags":["Usage"],"responses":{"200":{"description":"Paramètres de solde et de recharge automatique","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/interview-training/sessions":{"post":{"summary":"Créer une session de formation aux entretiens","description":"Crée une session pratique d'entretien basée sur une offre d'emploi à partir d'un projet, d'une offre d'emploi ou d'un texte de publication brut.","tags":["Interview Training"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTrainingSessionCreate"}}}},"responses":{"201":{"description":"Session de formation aux entretiens créée","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InterviewTrainingSession"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/interview-training/sessions/{id}":{"get":{"summary":"Bénéficiez d'une séance de formation aux entretiens","tags":["Interview Training"],"parameters":[{"$ref":"#/components/parameters/InterviewTrainingSessionId"}],"responses":{"200":{"description":"Séance de formation aux entretiens","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/InterviewTrainingSession"},{"type":"object","properties":{"answers":{"type":"array","items":{"$ref":"#/components/schemas/InterviewTrainingAnswer"}},"progress":{"$ref":"#/components/schemas/InterviewTrainingProgress"}}}]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/interview-training/sessions/{id}/next-question":{"get":{"summary":"Obtenez la prochaine question de formation à l'entretien","tags":["Interview Training"],"parameters":[{"$ref":"#/components/parameters/InterviewTrainingSessionId"}],"responses":{"200":{"description":"Question suivante sans réponse","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"question":{"anyOf":[{"$ref":"#/components/schemas/InterviewTrainingQuestion"},{"type":"null"}]},"progress":{"$ref":"#/components/schemas/InterviewTrainingProgress"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/interview-training/sessions/{id}/answers":{"post":{"summary":"Soumettre la réponse à l'entretien de formation","description":"Stocke une réponse pratique du candidat et renvoie les commentaires du coaching.","tags":["Interview Training"],"parameters":[{"$ref":"#/components/parameters/InterviewTrainingSessionId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTrainingAnswerCreate"}}}},"responses":{"200":{"description":"Répondre aux commentaires","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"answer":{"$ref":"#/components/schemas/InterviewTrainingAnswer"},"feedback":{"$ref":"#/components/schemas/InterviewTrainingFeedback"}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/interview-training/sessions/{id}/summary":{"post":{"summary":"Générer un résumé de la formation aux entretiens","description":"Génère ou renvoie un rapport de préparation final mis en cache pour la session d'exercices pratiques.","tags":["Interview Training"],"parameters":[{"$ref":"#/components/parameters/InterviewTrainingSessionId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Résumé de la formation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"summary":{"$ref":"#/components/schemas/InterviewTrainingSummary"},"cached":{"type":"boolean"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/webhooks":{"get":{"summary":"Répertorier les webhooks","tags":["Webhooks"],"responses":{"200":{"description":"Inscriptions aux webhooks","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"summary":"Créer un webhook","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","description":"URL du webhook HTTPS public. Les cibles IP localhost et privées/lien-local/réservées sont rejetées."},"events":{"type":"array","items":{"type":"string","enum":["application.created","application.started","application.completed","application.decided","application.stage_changed","screening.submitted","screening.evaluated","interview.started","interview.completed","code.submitted","code.evaluated","balance.low","balance.depleted","test.ping"]}},"secret":{"type":"string"}}}}}},"responses":{"200":{"description":"Webhook créé","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/webhooks/{id}":{"put":{"summary":"Mettre à jour le webhook","tags":["Webhooks"],"parameters":[{"$ref":"#/components/parameters/WebhookId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"URL du webhook HTTPS public. Les cibles IP localhost et privées/lien-local/réservées sont rejetées."},"events":{"type":"array","items":{"type":"string","enum":["application.created","application.started","application.completed","application.decided","application.stage_changed","screening.submitted","screening.evaluated","interview.started","interview.completed","code.submitted","code.evaluated","balance.low","balance.depleted","test.ping"]}},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Webhook mis à jour","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["application.created","application.started","application.completed","application.decided","application.stage_changed","screening.submitted","screening.evaluated","interview.started","interview.completed","code.submitted","code.evaluated","balance.low","balance.depleted","test.ping"]}},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"summary":"Supprimer le webhook","tags":["Webhooks"],"parameters":[{"$ref":"#/components/parameters/WebhookId"}],"responses":{"200":{"description":"Webhook supprimé","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/webhooks/{id}/deliveries":{"get":{"summary":"Lister les diffusions de webhooks","tags":["Webhooks"],"parameters":[{"$ref":"#/components/parameters/WebhookId"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"}],"responses":{"200":{"description":"Journal de livraison du webhook","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/webhooks/test":{"post":{"summary":"Envoyer un webhook de test","tags":["Webhooks"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["webhookId"],"properties":{"webhookId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"Résultat de livraison du test","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"statusCode":{"type":"integer"},"response":{"type":"string","nullable":true},"deliveredAt":{"type":"string","format":"date-time","nullable":true}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/ValidationError"}}}}},"tags":[{"name":"Health","description":"Préparation à la santé opérationnelle et à la dépendance","x-displayName":"État de l’API"},{"name":"Projects","description":"Projets de recrutement et pipelines générés par l'IA","x-displayName":"Projets"},{"name":"Candidates","description":"Invitations et profils des candidats","x-displayName":"Candidats"},{"name":"Applications","description":"Statut de la candidature, enregistrements et évaluations","x-displayName":"Applications"},{"name":"Usage","description":"Informations sur l'utilisation, la facturation et le solde","x-displayName":"Utilisation"},{"name":"Interview Training","description":"Entretiens pratiques basés sur des offres d'emploi pour les flux de partenaires intégrés","x-displayName":"Formation aux entretiens"},{"name":"Webhooks","description":"Enregistrement du webhook et suivi de livraison","x-displayName":"Webhooks"}]}