Offres et candidatures
Lire les offres publiées d'un client et y déposer des candidatures avec CV
Ce guide s'adresse aux outils de sourcing et de préqualification qui envoient des candidats sur les offres d'un client Marvin. Deux appels suffisent : lire les offres que le client publie sur son site carrière, puis déposer une candidature sur l'une d'elles.
La candidature arrive dans l'onglet Candidatures de l'offre, où le recruteur la traite comme une candidature reçue sur son site carrière. Le CV est analysé et le profil du candidat rattaché ou créé.
Clé d'API
L'administrateur du client génère la clé depuis Paramètres → Intégrations,
sur la page du connecteur de votre outil, puis vous la transmet avec l'identifiant
de son compte ({slug}).
- C'est une clé partenaire, générée par un connecteur prévu pour ces routes :
partner:projects:readouvre la lecture des offres,partner:candidates:writele dépôt des candidatures. Toutes les clés partenaires ne les ouvrent pas — en cas de403, vérifiez avec Marvin que votre connecteur est bien celui-ci. - Elle s'envoie uniquement dans le header
X-Marvin-Public-Key. Passée dans l'URL (?key=), elle est refusée (401). - C'est un secret côté serveur : ne l'exposez jamais dans du code exécuté par un navigateur.
X-Marvin-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxLire les offres
GET https://api.marvins.ai/v1/public/careers/{slug}/feed.xmlLe flux liste les offres publiées sur le site carrière du client : ce sont les
seules sur lesquelles une candidature peut être déposée. Chaque offre est un élément
<job>, dont <id> est l'identifiant à utiliser pour le dépôt.
curl "https://api.marvins.ai/v1/public/careers/{slug}/feed.xml" \
-H "X-Marvin-Public-Key: pk_live_…"La même liste existe en JSON : GET https://api.marvins.ai/v1/public/careers/{slug}.
Les erreurs du flux sont au format XML
(<error><code>…</code><message>…</message></error>) : 401 et 403 comme
ci-dessous. Un slug qui n'est pas celui du client de la clé renvoie
403 slug_mismatch.
Déposer une candidature
POST https://api.marvins.ai/v1/public/careers/{slug}/jobs/{jobId}/applyoù {jobId} est l'<id> de l'offre lu dans le flux. Le corps s'envoie en
multipart/form-data (pour joindre le CV) ou en application/json.
| Champ | Type | Requis | Description |
|---|---|---|---|
firstName | string | oui | Prénom (100 caractères max.) |
lastName | string | oui | Nom (100 caractères max.) |
email | string | oui | E-mail du candidat |
phoneNumber | string | non | Téléphone |
linkedin | string | non | URL du profil LinkedIn |
motivationText | string | non | Message, notes de préqualification (5 000 caractères max.) |
resume | file | non | CV (resume ou cv), en multipart |
languages | string | non | Langues du candidat, séparées par une virgule (fr, en) |
city | string | non | Ville du candidat (voir « Localisation » ci-dessous) |
postalCode | string | non | Code postal du candidat |
countryCode | string | non | Pays du candidat, code ISO 3166-1 alpha-2 |
| champs perso | — | non | Champs personnalisés du formulaire du client |
firstName, lastName ou email manquant ou invalide renvoie 400. Le client peut
rendre d'autres champs obligatoires dans son formulaire de candidature : un tel champ
manquant renvoie 422, avec son nom dans error.field.
CV : PDF, DOC, DOCX, JPEG, PNG, WEBP ou GIF, 10 Mo maximum (au-delà : 413).
Langues : languages ajoute les langues du candidat à sa fiche. Chaque langue est
désignée par son code ISO 639-1 à deux lettres (fr, en… ; fra n'est pas reconnu) ou par son nom en français ou en
anglais, parmi la centaine de langues courantes que Marvin connaît. La candidature ne
modifie ni ne retire les langues que la fiche porte déjà ; une valeur non reconnue est
ignorée sans faire échouer la candidature. Au plus 10 langues distinctes sont retenues par candidature.
Localisation : city renseigne la localisation du candidat sur sa fiche, rattachée
au référentiel de lieux de Marvin (une ville, jamais une rue) ; le recruteur peut ensuite
rechercher ses candidats par zone. Une précision après une virgule est ignorée
(Lyon, France vaut Lyon). postalCode départage les communes homonymes
(Saint-Martin + 38410). countryCode limite la recherche à un pays, en code ISO
3166-1 alpha-2 (FR, BE, CH…) ; sans lui, la France est privilégiée mais une ville
étrangère reste trouvée. Une localisation déjà présente sur la fiche n'est jamais
remplacée. Une ville introuvable est ignorée ; une valeur que Marvin ne sait pas lire
(dans city, postalCode ou countryCode) fait ignorer toute la localisation. Dans
les deux cas, la candidature est acceptée. postalCode seul, sans city, est ignoré.
En JSON, postalCode peut aussi s'envoyer en nombre.
Provenance : elle est fixée par la clé. La candidature et le candidat sont attribués à votre outil, sans paramètre à passer.
Doublons : une candidature pour une offre où le même e-mail a déjà une
candidature active est acceptée (201) et mise en quarantaine pour arbitrage par le
recruteur. Aucun profil en double n'est créé.
curl -X POST \
"https://api.marvins.ai/v1/public/careers/{slug}/jobs/{jobId}/apply" \
-H "X-Marvin-Public-Key: pk_live_…" \
-F "firstName=Marie" \
-F "lastName=Dupont" \
-F "email=marie.dupont@example.com" \
-F "motivationText=Disponible sous un mois, prétentions 45 k€." \
-F "resume=@/chemin/vers/cv.pdf"Candidature spontanée
Pour un candidat qui ne vise aucune offre : POST https://api.marvins.ai/v1/public/careers/{slug}/apply,
avec les mêmes champs.
Champ personnalisé à choix multiple
Sur ces deux routes, un champ personnalisé n'est accepté que s'il figure dans le formulaire de candidature du client ; les autres sont ignorés. Pour un champ à choix multiple, la valeur s'envoie toujours sous forme de chaîne :
- une option : son libellé, par exemple
AlphaouConseil, audit; - plusieurs options : un tableau JSON sérialisé en chaîne, par exemple
["Alpha","Beta"]. Chaque élément du tableau est une chaîne ; un élément vide ou d'un autre type est écarté.
La casse est indifférente, de même que les espaces en début et en fin de libellé. Si
l'une des valeurs n'est pas une option du champ, la candidature est refusée : 409,
avec error.code à conflict, et ni le candidat ni la candidature ne sont créés.
Exception : une nouvelle candidature du même e-mail sur une offre où il a déjà une
candidature active est mise en quarantaine (201, voir Doublons) ; ses champs
personnalisés ne sont alors ni vérifiés ni enregistrés.
Les options d'un champ se lisent dans
GET https://api.marvins.ai/v1/public/careers/{slug} : dans data.formConfig.fields,
fieldKey est le nom du champ à envoyer et options la liste de ses options.
Deux limites :
- dans un corps
application/json, un tableau natif ("domaines": ["Alpha", "Beta"]) n'est pas lu, seules les chaînes le sont : envoyez"domaines": "[\"Alpha\",\"Beta\"]"; - en
multipart/form-data, un champ répété ne garde que sa dernière valeur.
Réponses
Succès : 201 avec l'identifiant de la candidature, { "data": { "id": "…" } }.
Les erreurs du dépôt ont la forme { "error": { "code": "…", "message": "…" } }
({ "error": { "code": "…", "field": "…" } } pour un 422). Testez le code, qui
est stable.
| Statut | code | Cas |
|---|---|---|
400 | validation_error | Champ obligatoire manquant ou invalide, type de fichier refusé |
401 | unauthorized | Clé absente, malformée, révoquée, ou clé partenaire passée dans l'URL |
403 | insufficient_scope | Droit manquant sur la clé — le message nomme le scope manquant |
403 | slug_mismatch | Lecture du flux : slug d'un autre client que la clé |
404 | job_not_found | Offre inconnue, ou dépôt avec le slug d'un autre client que la clé |
410 | job_removed | Offre fermée, dépubliée ou supprimée |
413 | — | CV trop lourd (plus de 10 Mo) — testez le statut, pas le code |
422 | missing_required_field | Champ rendu obligatoire par le client — error.field nomme le champ |
429 | rate_limited | Trop de dépôts (30 par minute et par clé) |
Bonnes pratiques
- Relisez le flux avant d'envoyer : une offre fermée ou dépubliée renvoie
410. - Envoyez le CV quand vous l'avez : c'est lui qui remplit le profil du candidat.
- Mettez vos notes de préqualification dans
motivationText: le recruteur les lit sur la candidature.
Pour les schémas complets, voir la Référence API — Careers (Public).
API partenaire
Lister les projets et étapes d'un client, et y créer des candidats
Site web — diffuser vos offres et recevoir les candidatures
Afficher les offres Marvin sur le site du client via un flux XML, renvoyer les candidatures du site dans Marvin via l'API, et faire remonter les demandes de contact (entreprises, particuliers) dans le CRM