Invia candidati verificati nel 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).
1. Crea una chiave agent e registra un webhook
# 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_SECRET2. Relay Greenhouse (Node / TypeScript)
Greenhouse Harvest API
// Deno / Node webhook relay: InTransparency → Greenhouse Harvest API
// Env: GREENHOUSE_API_KEY, INTRANSPARENCY_WEBHOOK_SECRET, GREENHOUSE_JOB_ID
import crypto from 'node:crypto'
export default async function relay(req: Request): Promise<Response> {
// 1. Verify the signature
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')
if (sig !== expected) 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. Fetch the candidate's full profile from InTransparency
const candidate = await fetch(
'https://www.in-transparency.com/api/agents/companies/' + data.candidateSlug,
).then(r => r.json())
// 3. Create a prospect in Greenhouse — the "Prospects" stage is perfect
// for sourced leads; they convert to candidates once a recruiter adds them
// to a job.
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: data.candidateName.split(' ')[0],
last_name: data.candidateName.split(' ').slice(1).join(' '),
email_addresses: [{ value: candidate.email, type: 'personal' }],
applications: [{ job_id: Number(process.env.GREENHOUSE_JOB_ID) }],
attachments: [{
filename: 'intransparency-evidence.pdf',
type: 'other',
url: 'https://www.in-transparency.com/en/matches/' + data.matchId + '/why',
}],
custom_fields: {
intransparency_match_score: data.matchScore,
intransparency_match_id: data.matchId,
},
}),
})
return new Response('ok', { status: 200 })
}3. Relay Lever (Python / FastAPI)
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
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
POST a /candidate.create, poi /candidate.addApplication. La loro API è nativa webhook, quindi logica di relay minima.