Intégration ATS
Envoyez les candidats correspondants dans votre ATS existant
InTransparency ne remplace pas votre ATS : il l'alimente. Lorsqu'une correspondance à haut niveau de confiance se déclenche, nous envoyons un webhook signé ; un relais de 30 lignes le transforme en prospect Greenhouse, en opportunité Lever ou en candidat de réquisition Workday.
Le principe
InTransparency déclenche un webhook → votre petit relais vérifie la signature → votre relais appelle l'endpoint candidates de votre ATS. Aucun middleware personnalisé, aucun polling, aucune synchronisation planifiée. Le relais s'exécute n'importe où (Vercel, Cloudflare Workers, AWS Lambda ou un conteneur FastAPI).
Créez une clé d'agent et enregistrez un webhook
InTransparency API
# Step 1: Create an InTransparency agent key with webhook scope curl -X POST https://www.in-transparency.com/api/agents/keys \ -H "Cookie: <your session>" \ -H "Content-Type: application/json" \ -d '{"name":"ATS-relay","scopes":["agent:webhook"]}' # Response: { "key": "ita_...", ... } — save it once; never shown again # Step 2: Register your webhook endpoint with InTransparency curl -X POST https://www.in-transparency.com/api/agents/webhooks \ -H "Authorization: Bearer ita_..." \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-relay.example.com/webhooks/intransparency", "events": ["match.created", "credential.issued"] }' # Response includes { "secret": "..." } — store as INTRANSPARENCY_WEBHOOK_SECRETRelais Greenhouse (Node / TypeScript)
Relais Lever (Python / FastAPI)
Greenhouse Harvest API
// Deno / Node webhook relay: InTransparency → Greenhouse Harvest API // Env: GREENHOUSE_API_KEY, GREENHOUSE_USER_ID, GREENHOUSE_JOB_ID, // INTRANSPARENCY_WEBHOOK_SECRET import crypto from 'node:crypto' export default async function relay(req: Request): Promise<Response> { // 1. Verify the signature (constant-time compare) const body = await req.text() const sig = req.headers.get('X-InTransparency-Signature') || '' const expected = 'sha256=' + crypto .createHmac('sha256', process.env.INTRANSPARENCY_WEBHOOK_SECRET!) .update(body).digest('hex') const ok = sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)) if (!ok) return new Response('bad signature', { status: 401 }) const { event, data } = JSON.parse(body) if (event !== 'match.created' || data.matchScore < 70) { return new Response('ignored', { status: 200 }) } // 2. Create a prospect in Greenhouse. Before the student accepts contact, // the webhook carries no email or surname — only a first name with an // initial ("Giulia M."), a stable pseudonym and the evidence link. The // recruiter opens the link, writes to the student on InTransparency, and // the full contact arrives once the student says yes. const [firstName, ...rest] = String(data.candidateName).split(' ') await fetch('https://harvest.greenhouse.io/v1/candidates', { method: 'POST', headers: { 'Authorization': 'Basic ' + Buffer.from(process.env.GREENHOUSE_API_KEY + ':').toString('base64'), 'Content-Type': 'application/json', 'On-Behalf-Of': process.env.GREENHOUSE_USER_ID!, }, body: JSON.stringify({ first_name: firstName, last_name: rest.join(' ') || data.candidatePseudonym, applications: [{ job_id: Number(process.env.GREENHOUSE_JOB_ID) }], website_addresses: [{ value: data.url, type: 'other' }], tags: ['InTransparency', data.decisionLabel], custom_fields: [ { name_key: 'intransparency_match_id', value: data.matchId }, { name_key: 'intransparency_match_score', value: data.matchScore }, ], }), }) return new Response('ok', { status: 200 }) }Lever Opportunities API
# Python / FastAPI webhook relay: InTransparency → Lever API # Env: LEVER_API_KEY, INTRANSPARENCY_WEBHOOK_SECRET, LEVER_POSTING_ID import hashlib, hmac, os, json, httpx from fastapi import FastAPI, Request, HTTPException app = FastAPI() @app.post("/webhooks/intransparency") async def relay(req: Request): body = await req.body() sig = req.headers.get("X-InTransparency-Signature", "") expected = "sha256=" + hmac.new( os.environ["INTRANSPARENCY_WEBHOOK_SECRET"].encode(), body, hashlib.sha256, ).hexdigest() if not hmac.compare_digest(sig, expected): raise HTTPException(401, "bad signature") payload = json.loads(body) if payload["event"] != "match.created": return {"ok": True} data = payload["data"] if data["matchScore"] < 70: return {"ok": True} # Lever: create an opportunity (candidate attached to a posting) async with httpx.AsyncClient(auth=(os.environ["LEVER_API_KEY"], "")) as client: r = await client.post( "https://api.lever.co/v1/opportunities", json={ "name": data["candidateName"], "origin": "sourced", "sources": ["InTransparency"], "postings": [os.environ["LEVER_POSTING_ID"]], "tags": [f"intransparency-score-{data['matchScore']}"], "links": [data["url"]], }, ) r.raise_for_status() return {"ok": True}
Autres plateformes ATS
Workday Recruiting
Utilisez le Recruiting Staffing Web Service (SOAP) : ajoutez un Candidate avec l'opération Add_Candidate. Même principe de relais, payload différent.
SmartRecruiters
Faites un POST vers /candidates avec jobId et status=LEAD. Les champs personnalisés se mappent proprement.
Recruitee
Faites un POST vers /candidates avec placements=[{offer_id}]. Joignez l'URL de preuve en tant que note.
Teamtailor
Le push natif est disponible en bêta : ajoutez une clé API TeamTailor dans les réglages recruteur. Si vous préférez le construire : POST vers /v1/candidates avec les job-applications incluses ; les candidats sourcés apparaissent dans le pipeline en tant que leads.
Personio
Utilisez la Recruiting API : POST /v1/recruiting/applications. Les équipes RH italiennes déjà familières avec Personio peuvent mettre cela en place en moins d'une heure.
Ashby
Le push natif est disponible en bêta : ajoutez une clé API Ashby dans les réglages recruteur et le relais devient inutile. Si vous préférez le construire : POST vers /candidate.create, puis /candidate.addApplication.