Integrazione ATS
Invia i candidati abbinati al tuo ATS esistente
InTransparency non sostituisce il tuo ATS: lo alimenta. Quando scatta un match ad alta affidabilità, inviamo un webhook firmato; un relay di 30 righe lo trasforma in un prospect Greenhouse, un'opportunity Lever o un candidate di requisition Workday.
Lo schema
InTransparency invia un webhook → il tuo piccolo relay verifica la firma → il relay chiama l'endpoint candidates del tuo ATS. Nessun middleware custom, nessun polling, nessuna sincronizzazione pianificata. Il relay gira ovunque (Vercel, Cloudflare Workers, AWS Lambda o un container FastAPI).
Crea una chiave agent e registra 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_SECRETRelay Greenhouse (Node / TypeScript)
Relay 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}
Altre piattaforme ATS
Workday Recruiting
Usa il Recruiting Staffing Web Service (SOAP): aggiungi un candidato con l'operazione Add_Candidate. Stesso schema di relay, payload diverso.
SmartRecruiters
POST a /candidates con jobId e status=LEAD. I campi personalizzati si mappano facilmente.
Recruitee
POST a /candidates con placements=[{offer_id}]. Allega l'URL delle evidenze come nota.
Teamtailor
Il push nativo è live in beta: aggiungi la API key TeamTailor nelle impostazioni recruiter. Se preferisci costruirlo: POST a /v1/candidates con job-applications incluse; i candidati sourced appaiono in pipeline come lead.
Personio
Usa la Recruiting API: POST /v1/recruiting/applications. I team HR italiani che già usano Personio possono collegarlo in meno di un'ora.
Ashby
Il push nativo è live in beta: aggiungi la API key Ashby nelle impostazioni recruiter e salti il relay. Se preferisci costruirlo: POST a /candidate.create, poi /candidate.addApplication.