Publier un poste depuis votre propre système
Mis à jour
Si vos postes vivent déjà ailleurs — un ATS, un outil interne, un tableur que quelqu’un garde jalousement — voici comment ils arrivent dans Orbit sans que personne ne les ressaisisse.
Ce qu’il vous faut
Une clé portant la portée lecture et gestion des offres, créée dans Orbit → Paramètres → Clés d’API. Une clé en lecture seule répond 403 à toutes les requêtes de cette page, délibérément : publier consomme vos crédits, et la clé qui alimente une page carrières ne devrait pas pouvoir en plus publier des annonces.
export ORBIT_API_KEY="…une clé lecture et gestion des offres…"
La forme : deux appels
Créer et publier sont séparés.
POST /v1/jobscrée un brouillon. Rien n’est public. Rien n’est facturé.POST /v1/jobs/{jobId}/publishle met en ligne et facture les frais de publication.
C’est délibéré. Publier place le poste sur votre page d’offre hébergée, permet aux candidats de postuler, l’ajoute au flux des chercheurs d’emploi Wipperoz et démarre le tour d’appariement par IA. Un appel unique qui ferait tout cela signifierait qu’une clé prise dans une boucle mal configurée dépense votre solde avant que quiconque ne lise un log.
Cela laisse aussi une personne dans la boucle quand vous en voulez une : créez les brouillons depuis votre système et laissez un recruteur les publier depuis Orbit après les avoir lus. Si vous n’en voulez pas, appelez publish vous-même. Les deux sont pris en charge ; le choix vous revient, pas à nous.
Créer le brouillon
curl -X POST https://api.wipperoz.com/v1/jobs \
-H "Authorization: Bearer $ORBIT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ats-job-4471" \
-d '{
"title": "Ingénieur backend senior",
"description": "<p>Prendre en charge les services derrière notre pipeline de recrutement.</p>",
"responsibilities": ["Concevoir et livrer des services sur AWS Lambda et DynamoDB"],
"skills": [
{"name": "TypeScript", "level": "required"},
{"name": "DynamoDB", "level": "nice_to_have"}
],
"employmentType": "full_time",
"contractType": "permanent",
"salary": {"min": 150000, "max": 180000, "currency": "AUD", "period": "year"},
"location": {"country": "AU", "state": "NSW", "city": "Sydney", "remotePolicy": "hybrid"}
}'
{
"job": {
"id": "job_01J9A0B1C2EXAMPLE",
"status": "draft",
"title": "Ingénieur backend senior",
"applyLink": "https://www.wipperoz.com/fr/apply/job_01J9A0B1C2EXAMPLE?src=careers&account=acc_01J8Z3EXAMPLE"
}
}
Gardez l’id. C’est par lui que vous publierez, modifierez et clôturerez le poste, et c’est l’identifiant à stocker en face du poste dans votre propre système.
Seul title est obligatoire. Tout le reste est facultatif ici — description devient obligatoire au moment de publier, et rien d’autre ne bloque jamais la publication. description accepte du HTML, ce que produit l’éditeur d’Orbit ; du texte brut convient aussi.
Le publier
curl -X POST https://api.wipperoz.com/v1/jobs/job_01J9A0B1C2EXAMPLE/publish \
-H "Authorization: Bearer $ORBIT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ats-job-4471-publish" \
-d '{"expiryDays": 30}'
{
"job": {"id": "job_01J9A0B1C2EXAMPLE", "status": "published", "url": "…"},
"creditsCharged": 500,
"firstPublish": true
}
expiryDaysvaut30,60,90, ounullpour aucune expiration.nullest la valeur par défaut : un poste qui disparaît à une date que personne n’a choisie est pire qu’un poste qui reste en ligne.creditsChargedest le coût de cet appel. Republier un poste qui a déjà été en ligne — un poste clos que vous rouvrez — conserve son URL et ne coûte rien ;firstPublishvous dit lequel des deux cas s’est produit.- Crédits insuffisants : réponse
402avec le solde, et rien n’est écrit. Rechargez et rappelez le même endpoint. - Un poste sans titre ou sans description reçoit un
422avec une listemissing, plutôt qu’un400vague.
Modifier un poste
curl -X PATCH https://api.wipperoz.com/v1/jobs/job_01J9A0B1C2EXAMPLE \
-H "Authorization: Bearer $ORBIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"salary": {"min": 170000, "max": 200000, "currency": "AUD", "period": "year"}}'
N’envoyez que les champs que vous changez ; les autres sont laissés tels quels.
Sur un brouillon, la modification s’applique immédiatement. Sur un poste publié, les nouveaux mots sont mis en attente au lieu de remplacer ce que les candidats lisent en ce moment, et la réponse le dit :
{"job": {"…": "…tel qu'il se lit encore aujourd'hui"}, "pendingRevision": true}
Les candidats postulent au regard des mots présents sur la page, et les changer sous une candidature ouverte revient à modifier ce que quelqu’un a accepté après qu’il l’a accepté. Un recruteur promeut donc la modification dans Orbit — ou vous la promouvez vous-même dans le même appel :
-d '{"salary": {...}, "publishEdits": true}'
Deux champs sautent la file et s’appliquent toujours immédiatement : expiresAt et maxMatches. Tous deux existent pour arrêter quelque chose, et garder « arrêter à cinquante correspondances » derrière une promotion continuerait de dépenser les crédits que le plafond devait économiser.
Clôturer un poste
curl -X POST https://api.wipperoz.com/v1/jobs/job_01J9A0B1C2EXAMPLE/close \
-H "Authorization: Bearer $ORBIT_API_KEY"
La page hébergée cesse d’accepter les candidatures et indique que le poste est clos, le poste quitte le flux des chercheurs d’emploi, et l’accès aux CV que ce poste avait accordé à vos recruteurs prend fin avec lui — la raison de cet accès était une candidature ouverte.
Les candidatures déjà reçues restent, et restent consultables dans Orbit. Clôturer n’est pas supprimer, et cette API n’a pas de suppression. Seul un poste publié peut être clos ; un brouillon ou un poste déjà clos reçoit un 409.
Des tentatives répétées qui ne facturent pas deux fois
Envoyez une Idempotency-Key sur chaque POST. N’importe quelle valeur qui identifie l’intention convient — l’identifiant du poste dans votre propre système est idéal.
- Une nouvelle tentative avec la même clé renvoie la première réponse, avec
Idempotent-Replay: true. Pas de seconde annonce, pas de second débit. - La même clé avec un corps différent reçoit un
409. Deux intentions sous un même nom sont un bug qu’il vaut mieux connaître. - Les clés sont mémorisées 24 heures, par compte.
- Une requête refusée libère sa clé : un
402que vous corrigez en rechargeant peut être retenté avec la même clé.
Sans l’en-tête, deux créations identiques font deux annonces. Les réseaux expirent : envoyez l’en-tête.
Tenir une synchronisation honnête
- Stockez notre
iden face de votre poste. C’est la seule prise stable. - Clôturez ce qui a été clos en amont. Une annonce périmée coûte son après-midi à un candidat, ce qui est pire qu’une annonce absente.
- Ne recréez pas à chaque synchronisation. Faites un
PATCHsur le poste déjà créé ; un nouveauPOSTfabrique une seconde annonce, avec un second coût et une seconde URL. - Limite de débit : 120 requêtes par minute et par clé. Quarante postes font quarante appels, largement dans les clous.
Référence
Create a draft jobPOST /v1/jobs
Publish a jobPOST /v1/jobs/{jobId}/publish
Edit a jobPATCH /v1/jobs/{jobId}
Close a jobPOST /v1/jobs/{jobId}/close