API publique des offres d'emploi
Construisez votre propre site d'emploi (par exemple avec Next.js sur Vercel) au-dessus de votre pipeline de recrutement Kit. Listez les postes publiés et recevez des candidatures via une API REST publique et un SDK TypeScript.
Pourquoi c’est important
Le portail carrière hébergé par Kit et le widget intégrable couvrent la plupart des besoins. Mais si vous voulez un contrôle total sur le design — un site carrière sur mesure, une landing page dédiée par poste ou un site d’emploi assorti à votre produit — la Public Jobs API vous permet de lire vos offres publiées et d’envoyer les candidatures directement dans votre pipeline Kit, pendant que Kit continue de gérer la présélection, les étapes, les entretiens et la communication avec les candidats.
Il existe aussi un template Next.js officiel déployable en un clic et un SDK TypeScript, pour livrer un site d’emploi personnalisé en quelques minutes.
Clés API
Créez une paire de clés sous Hiring → Career Portal → Public API Keys. Chaque paire comprend :
-
Clé publiable (
pk_…) — peut être embarquée sans risque dans un navigateur. Elle peut lire les offres publiées et soumettre des candidatures, rien de plus. Elle n’expose jamais les données des candidats. Vous pouvez la restreindre à des origines spécifiques et la protéger avec votre propre widget Cloudflare Turnstile. -
Clé secrète (
sk_…) — réservée à un usage côté serveur (par exemple une Server Action Next.js). Elle contourne les vérifications navigateur d’origine et de Turnstile. Ne l’exposez jamais dans du code côté client. Aucune des deux clés ne peut lire les données personnelles des candidats.
La clé secrète n’est affichée qu’une seule fois, à sa création ou à sa rotation. Vous pouvez la faire tourner à tout moment depuis la page de paramètres de la clé ; l’ancienne clé secrète cesse de fonctionner immédiatement.
Authentifiez chaque requête avec un en-tête bearer :
Authorization: Bearer sk_your_secret_key
Endpoints
URL de base : https://app.startupkit.app (ou votre domaine carrière personnalisé).
Lister les offres publiées
GET /api/public/v1/jobs?department=&location=&employment_type=&remote=&page=&per_page=
Retourne uniquement les postes publiés de votre compte.
{
"data": [
{
"id": "JdK2hQ8…",
"title": "Senior Rails Developer",
"department": "Engineering",
"location": "Remote",
"employment_type": "full_time",
"remote": true,
"published_at": "2026-06-01T12:00:00Z",
"url": "https://careers.yourco.com/JdK2hQ8…",
"salary": { "min": 120000, "max": 160000, "currency": "USD", "period": "YEAR" }
}
],
"pagination": { "current_page": 1, "total_pages": 3, "total_count": 42, "per_page": 20 }
}
L’id est le jeton public de l’offre — utilisez-le pour les endpoints de détail et de candidature.
Récupérer une offre et son formulaire de candidature
GET /api/public/v1/jobs/:public_token
Retourne l’offre, accompagnée d’un application_form décrivant précisément les champs et questions à afficher, la mention de consentement à présenter, les types et la taille de CV acceptés, et si Turnstile est requis.
{
"id": "JdK2hQ8…",
"title": "Senior Rails Developer",
"description_html": "<p>We're hiring…</p>",
"accepting_applications": true,
"stages": [{ "name": "Application Review", "type": "application_form" }],
"application_form": {
"fields": [
{ "name": "cover_letter", "type": "textarea", "label": "Cover letter", "required": false }
],
"questions": [
{ "key": "why_us", "type": "text", "prompt": "Why do you want to join?", "required": true, "max_length": 2000 }
],
"consent_disclosure_html": "<p>By applying you agree…</p>",
"resume": {
"content_types": ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
"max_byte_size": 10485760
},
"turnstile": { "required": false, "sitekey": null }
}
}
Téléverser un CV (URL présignée)
Les CV sont téléversés directement vers le stockage : ils ne transitent jamais par votre serveur (ce qui évite les limites de taille de corps des environnements serverless).
POST /api/public/v1/direct_uploads
{ "blob": { "filename": "cv.pdf", "byte_size": 102400, "checksum": "<base64 MD5>", "content_type": "application/pdf" } }
{
"signed_id": "eyJf…",
"direct_upload": { "url": "https://…s3…", "headers": { "Content-Type": "application/pdf", "Content-MD5": "…" } }
}
Envoyez les octets du fichier en PUT vers direct_upload.url avec les headers retournés, puis transmettez le signed_id comme resume_signed_id au moment de soumettre la candidature.
Soumettre une candidature
POST /api/public/v1/jobs/:public_token/applications
{
"application": {
"email": "[email protected]",
"first_name": "Ada",
"last_name": "Lovelace",
"phone": "+1 555 0100",
"responses": { "cover_letter": "…", "why_us": "…" },
"resume_signed_id": "eyJf…"
},
"turnstile_token": "<token>"
}
Retourne 201 avec une confirmation minimale, sans données personnelles :
{ "id": "app_9fQ…", "status": "submitted", "job": "JdK2hQ8…", "submitted_at": "2026-06-11T09:30:00Z" }
Le turnstile_token n’est nécessaire que pour les soumissions depuis un navigateur (pk_) lorsque Turnstile est configuré sur la clé ; les appels côté serveur (sk_) s’en passent.
Erreurs
Les erreurs sont retournées dans une enveloppe cohérente :
{ "error": { "code": "validation_failed", "message": "Email can't be blank", "fields": { "email": ["can't be blank"] } } }
| Statut | Code | Signification |
|---|---|---|
| 401 | invalid_key |
Clé API manquante ou invalide |
| 403 | origin_not_allowed |
Origine du navigateur absente de la liste autorisée de la clé |
| 404 | not_found |
Offre introuvable ou non publiée |
| 409 | already_applied |
Cette adresse e-mail a déjà postulé à cette offre |
| 422 | validation_failed |
Champs de candidature invalides (voir fields) |
| 422 | turnstile_failed |
Échec de la vérification Turnstile |
| 422 |
invalid_content_type / file_too_large
|
Téléversement de CV refusé |
Suivi des statuts via webhooks
Pour suivre les candidatures après leur soumission, configurez des webhooks sortants. Les événements pertinents incluent application.submitted, application.advanced et application.rejected, ainsi que job_posting.published/paused/closed. Les payloads de candidature contiennent à la fois l’id numérique et le prefix_id de l’API (app_…), ainsi que le public_token de l’offre, pour corréler les événements webhook avec les enregistrements de l’API.
SDK et template Next.js
-
SDK TypeScript —
npm install @startupkit-app/jobs. Un client typé, sans dépendance, aveclistJobs,getJob,uploadFileetapply. - Template Next.js — un site d’emploi déployable en un clic (Deploy to Vercel) que vous pouvez forker et personnaliser. Il câble d’office la clé secrète, les formulaires de candidature dynamiques, le téléversement présigné des CV et le SEO/JSON-LD.
Les deux consomment le contrat décrit ci-dessus : vous pouvez donc aussi développer avec n’importe quel framework, en HTTP simple.
Limites de débit
Les soumissions de candidatures sont limitées à 10/heure par IP et les requêtes de téléversement à 30/heure par IP, en plus des limites de débit globales de l’API. Les clés navigateur sont en outre protégées par leur liste d’origines autorisées et, en option, par Turnstile.