Přeskočit na obsah

Pro vývojáře

Dokumentace API.

Napojte Evaluro na svůj ATS: zakládejte uchazeče a screeningy, stahujte výsledky a dostávejte je webhookem.

Aktualizováno 29. 9. 2026

Rychlý start.

  1. V HR portálu → Integrace vytvořte API klíč (smí vlastník nebo správce firmy) a zkopírujte si ID pozice z GET /positions.
  2. Vyzkoušejte napojení nanečisto: POST /intake s "dryRun": true projde všechny kontroly a řekne, co by se stalo – nic nezaloží ani neodešle.
  3. Přidejte adresu webhooku a stiskněte Odeslat test. Každý pokus o doručení uvidíte v přehledu „Doručení webhooků“ i s důvodem případné chyby.
curl https://hireup.inflexion.cz/api/v1/intake \
  -H "x-api-key: hu_…" -H "content-type: application/json" \
  -d '{ "positionId": "…", "dryRun": true,
        "candidate": { "fullName": "Eva Nováková", "email": "eva@example.com", "externalRef": "ats-123" },
        "cvText": "…text CV, aspoň 100 znaků…" }'

200 { "dryRun": true, "wouldCreate": "candidate_and_screening", "cv": "text",
      "candidate": { "existing": false, "candidateId": null, "profileReady": false },
      "warnings": [] }

Základy.

  • Základní adresa: https://hireup.inflexion.cz/api/v1, JSON přes HTTPS. Strojově čitelná specifikace: OpenAPI 3.1.
  • Autentizace hlavičkou x-api-key. Klíč vydává vlastník nebo správce firmy v HR portálu (Integrace) a patří firmě, ne osobě. Každý klíč vidí jen data své firmy.
  • Limit: 10 000 požadavků za 24 hodin na klíč (pak 429). Na výsledky nečekejte dotazováním – použijte webhook.
  • Chyby vrací JSON { "error": "kód" } se stavem 400/401/404/409.
curl https://hireup.inflexion.cz/api/v1/positions \
  -H "x-api-key: hu_…"

Nejrychlejší napojení: jedno volání.

Webhook vašeho ATS zavolá POST /intake hned, jak uchazeč přijde z inzerátu. Pošlete pozici, uchazeče a CV – právě jedno z cvText, cvPdfBase64 (PDF do 3 MB) a cvDocxBase64 (Word .docx do 3 MB; použijeme jen text, soubor neukládáme). Vše ostatní uděláme my: profil z CV, screening a pozvánku e-mailem ("sendInvite": false ji vypne).

POST https://hireup.inflexion.cz/api/v1/intake
{ "positionId": "…",
  "candidate": { "fullName": "Eva Nováková", "email": "eva@example.com", "externalRef": "ID v ATS" },
  "cvPdfBase64": "JVBERi0x…" }

202 { "candidateId": "…", "status": "waiting_for_profile", "existingCandidate": false }
    // nebo "screening_created" + screeningId (+ inviteUrl při novém založení)
  • Profil z CV trvá obvykle do 30 s. Do té doby je stav waiting_for_profile; screening založíme, jakmile bude hotový, a dáme vám vědět webhookem screening.created.
  • Opakované volání se stejným externalRef nezaloží duplicitu – vrátí existujícího uchazeče (a jeho živý screening). inviteUrl se vrací jen při novém založení.
  • Celý požadavek smí mít nejvýš 4,5 MB, proto PDF a Word posílejte do 3 MB; větší CV pošlete jako cvText.
  • "dryRun": true = zkušební režim: stejné kontroly (klíč, pozice, rubrika, CV) a odpověď 200 s tím, co by se stalo (wouldCreate, warnings). Nic se neuloží ani neodešle – vhodné pro ladění napojení z ATS.

Bez programování: Make, Zapier, n8n.

Pokud váš ATS umí poslat webhook nebo má aplikaci v Make či Zapieru, napojení zvládnete bez vývojáře:

  1. Spouštěč v ATS: nový uchazeč nebo přesun do fáze „Screening“ (Recruitis: webhook answer.add / answer.flow_change; Datacruit: Zapier „New/Updated Status“; Teamtailor, Workable: webhook nebo aplikace).
  2. HTTP modul: POST https://hireup.inflexion.cz/api/v1/intake, hlavička x-api-key, tělo jako výše. Jako externalRef použijte ID reakce v ATS – opakované spuštění pak nezaloží duplicitu.
  3. Výsledek zpět: v Make/Zapieru založte „custom webhook“, jeho adresu přidejte v HR portálu a z události screening.completed zapište do ATS poznámku s doporučením, shrnutím a odkazem reportUrl.

Když nástroj neumí ověřit podpis HMAC, ověřte zprávu aspoň dotazem GET /screenings/{screeningId} s vaším klíčem – podvrženou zprávu tak odhalíte. Do ATS zapisujte doporučení, ne automatické zamítnutí: o uchazeči rozhoduje člověk.

Podrobný postup po krocích.

  1. GET /positions – aktivní pozice se schválenou rubrikou. Každá nese i visualMode (avatar = AI avatar, orb = animovaný asistent bez tváře): podobu rozhovoru, kterou nový screening na pozici dostane. Přes API se nenastavuje; mění se v HR portálu u pozice, a to jen dokud na pozici nejsou pozvaní uchazeči (všichni uchazeči na pozici mají stejné podmínky).
  2. POST /candidates – uchazeč s textem CV; profil je hotový obvykle do 30 s (profileReady).
  3. POST /screenings – screening a odkaz pro uchazeče (inviteUrl, jen v této odpovědi). S "sendInvite": true pošleme pozvánku e-mailem my.
  4. Po dokončení přijde webhook screening.completed s doporučením a odkazem na report. Rozhoduje personalista v Evaluru.

Endpointy.

get/api/v1/me

200 Firma, ke které API klíč patří

get/api/v1/positions

Aktivní pozice firmy (se schválenou rubrikou)

200 Seznam pozic

post/api/v1/candidates

Založit uchazeče (z textu CV se připraví profil, obvykle do 30 s)

PoleTypPopis
fullName*string
email*string (email)
cvText*stringText CV (min. 100 znaků). PDF nebo Word pošlete v base64 přes POST /intake.
externalRefstring

201 Uchazeč založen409 Uchazeč se stejným externalRef už existuje

post/api/v1/intake

Jednokrokový vstup z ATS: uchazeč + CV → screening a pozvánka

Jedno volání pro webhook ATS. Založí uchazeče (nebo najde podle `externalRef`), z CV připraví profil a založí screening s pozvánkou e-mailem. Když je profil hotový, screening vznikne hned (odpověď obsahuje `inviteUrl`); jinak `waiting_for_profile` a screening vznikne do několika minut – ATS se to dozví webhookem `screening.created`. Pozice musí být aktivní se schválenou rubrikou.

PoleTypPopis
positionId*string (uuid)
candidate*object
cvTextstringText CV. Pošlete právě jedno z `cvText`, `cvPdfBase64` a `cvDocxBase64`.
cvPdfBase64stringCV jako PDF v base64 (max. 5 MB po dekódování; uložíme do šifrovaného úložiště).
cvDocxBase64stringCV ve Wordu (.docx) v base64, max. 5 MB. Použijeme jen jeho text, soubor neukládáme. Starý formát .doc nepodporujeme.
variantdemo | short | medium | long
languagecs | en
sendInvitebooleanPozvánku pošleme uchazeči e-mailem (výchozí). Jinak ji z API odkaz získáte jen při synchronním založení.
dryRunbooleanZkušební režim: projde všechny kontroly a vrátí, co by se stalo (200), ale nic nezaloží ani neodešle. Pro ladění napojení.

200 Zkušební režim (`dryRun`): co by se stalo202 Přijato400 Neplatný vstup nebo soubor (invalid_pdf, pdf_too_large, invalid_docx, docx_too_large, docx_empty)403 Délka screeningu (`variant`) není v tarifu firmy (variant_not_in_tariff)404 Pozice neexistuje409 Pozice není aktivní nebo nemá schválenou rubriku503 Nahrávání PDF není dostupné (pdf_unavailable), pošlete cvText

get/api/v1/candidates/{id}

Uchazeč a stav jeho profilu

Parametry cesty: id

200 Uchazeč404 Uchazeč neexistuje

delete/api/v1/candidates/{id}

Smazat uchazeče a všechna jeho data (CV, screeningy, záznamy, hodnocení)

Pro žádosti uchazečů o výmaz (GDPR čl. 17) a úklid ve vašem ATS. Nevratné. Data se jinak mažou automaticky po lhůtě uchování nastavené firmou.

Parametry cesty: id

204 Smazáno404 Uchazeč neexistuje

post/api/v1/screenings

Založit screening a získat odkaz pro uchazeče

Odkaz `inviteUrl` se vrací jen v této odpovědi (ukládáme jen jeho otisk). Pošlete ho uchazeči. Po dokončení přijde webhook `screening.completed`.

PoleTypPopis
positionId*string (uuid)
candidateId*string (uuid)
variantdemo | short | medium | long
languagecs | en
reportLanguagecs | en
answerModevoice | textvoice = rozhovor s AI avatarem (výchozí), text = písemné odpovědi (přiměřená úprava)
extendedTimebooleanPřiměřená úprava: dvojnásobný čas na odpovědi (max. 180 s na odpověď)
sendInvitebooleanPošleme uchazeči pozvánku e-mailem (v jazyce rozhovoru). Jinak ji pošlete sami.

201 Screening založen403 Délka screeningu (`variant`) není v tarifu firmy (variant_not_in_tariff)404 Pozice nebo uchazeč neexistuje409 Pozice nemá schválenou rubriku nebo uchazeč nemá hotový profil503 Přípravu rozhovoru se nepodařilo zařadit (plan_not_queued) – zkuste volání zopakovat

get/api/v1/screenings

Seznam screeningů firmy (nejnovější první, stránkování přes before)

Pro synchronizaci s ATS, když webhook nedorazil. Filtry: stav, uchazeč, dokončené od. Další stránku získáte parametrem before = nextBefore z předchozí odpovědi.

200 Screeningy

get/api/v1/screenings/{id}

Stav screeningu, doporučení a praktické informace uchazeče

Parametry cesty: id

200 Screening404 Screening neexistuje

post/api/v1/screenings/{id}/decision

Zapsat rozhodnutí personalisty z ATS

Pipeline uchazeče řídí ATS: rozhodnutí z ATS se zapíše do Evalura (zdroj `ats`). Stejné rozhodnutí jako poslední se nezapíše (`changed: false`), takže zpětný zápis vlastního webhooku nic nezdvojí. Zamítnutí před začátkem rozhovoru zruší pozvánku. Rozhodnutí s `changed: true` odejde webhookem `screening.decided` se `source: "ats"`.

Parametry cesty: id

PoleTypPopis
decision*advance | hold | reject
notestringDůvod (interní). Povinný, když je `decision` = `reject`; jinak volitelný.
decidedBy*stringPovinné. Kdo v ATS rozhodl (jméno nebo e-mail oprávněné osoby).

200 Rozhodnutí zapsané (nebo beze změny)400 Neplatný vstup; u `reject` chybí `note` (invalid_request, issues[].path = note)404 Screening neexistuje

post/api/v1/screenings/{id}/cancel

Zrušit pozvánku (jen než uchazeč začne)

Parametry cesty: id

204 Zrušeno404 Screening neexistuje409 Rozhovor už začal nebo skončil

post/api/v1/screenings/{id}/invite

Nový odkaz pro uchazeče (starý přestane platit, platnost 7 dní)

Pro vypršelé pozvánky nebo ztracený odkaz. Jde jen před začátkem rozhovoru. Volitelné tělo `{ "sendInvite": true }` pošle uchazeči nový odkaz e-mailem.

Parametry cesty: id

200 Nový odkaz404 Screening neexistuje409 Rozhovor už začal nebo skončil

Webhooky.

Adresu webhooku (https) přidá správce v HR portálu → Integrace. Posíláme tyto události: screening.created (screening založený přes /intake; v data jen screeningId, candidate a position s ID, status a inviteSent), screening.completed, screening.decided, screening.expired, screening.failed a screening.accommodation_requested (níže). Adresa odebírá události, které existovaly při jejím přidání – pro novou událost přidejte adresu znovu. Po dokončení hodnocení pošleme POST s tělem:

{
  "id": "…",                      // ID doručení (pro deduplikaci)
  "type": "screening.completed",
  "createdAt": "2026-09-26T10:00:00.000Z",
  "data": {
    "screeningId": "…",
    "candidate": { "id": "…", "externalRef": "ID ve vašem ATS" },
    "position": { "id": "…", "title": "…" },
    "recommendation": "advance" | "consider" | "reject" | "insufficient",
    "summary": "…",
    "competencies": [{ "key": "…", "name": "…", "score": 1–5 | null, "confidence": "…" }],
    "logistics": { "salary": { "min", "max", "currency" } | null, "start": { "kind", "date" } | null,
                   "employment", "note", "skipped", "answeredAt" } | null,  // od uchazeče, mimo hodnocení AI
    "reportUrl": "https://hireup.inflexion.cz/dashboard/screenings/…",
    "decisionRequired": true
  }
}

Každá zpráva má hlavičku Evaluro-Signature: t=<unix>,v1=<hex>, kde v1 = HMAC-SHA256(tajemství, "t.tělo"). Ověřte podpis a odmítněte zprávy starší než 5 minut. Neúspěšné doručení (jiný stav než 2xx, timeout 10 s) opakujeme až 5×.

Rozhodnutí personalisty – pipeline řídí ATS

Rozhodnutí z HR portálu (pozvat, odložit, zamítnout) pošleme událostí screening.decided; vaše integrace podle něj posune uchazeče v ATS. Rozhodnutí v ATS zapište do Evalura přes POST /screenings/{id}/decision – v reportu se ukáže jako rozhodnutí v ATS a zamítnutí před začátkem rozhovoru zruší pozvánku. Stejné rozhodnutí jako poslední se nezapíše (changed: false). Pole decidedBy (jméno nebo e-mail osoby, která v ATS rozhodla) je povinné, aby šlo doložit lidský přezkum. Webhook se source: "ats" vznikl z vašeho zápisu – do ATS ho znovu nezapisujte. note je interní důvod pro personalisty, ne text pro uchazeče. Pokud uchazeči po zamítnutí píše e-mail vaše ATS, v Evaluru e-mail o výsledku neposílejte.

{
  "id": "…",
  "type": "screening.decided",
  "createdAt": "2026-09-30T10:00:00.000Z",
  "data": {
    "screeningId": "…",
    "decisionId": "…",
    "candidate": { "id": "…", "externalRef": "ID ve vašem ATS" },
    "position": { "id": "…", "title": "…" },
    "status": "completed",
    "decision": "advance" | "hold" | "reject",
    "note": "…" | null,
    "source": "hireup" | "ats",
    "decidedBy": "Jméno personalisty" | null,
    "decidedAt": "2026-09-30T10:00:00.000Z",
    "reportUrl": "https://hireup.inflexion.cz/dashboard/screenings/…"
  }
}

Uchazeč rozhovor neudělal

screening.expired přijde, když pozvánka vyprší bez rozhovoru (pozvánku jde obnovit přes POST /screenings/{id}/invite). screening.failed přijde, když rozhovor nebo jeho příprava selhaly – založte nový screening. Technický důvod selhání je jen v reportu.

"data": {
  "screeningId": "…",
  "candidate": { "id": "…", "externalRef": "ID ve vašem ATS" },
  "position": { "id": "…", "title": "…" },
  "status": "expired" | "failed",
  "started": false,          // uchazeč rozhovor začal
  "expiresAt": "…",
  "renewable": true,         // jen u expired
  "reportUrl": "…"
}

Žádost o jinou formu rozhovoru

screening.accommodation_requested přijde, když uchazeč požádá o delší čas, písemné odpovědi nebo rozhovor s člověkem. Posíláme jen druhy úprav – vlastní text uchazeče může obsahovat údaje o zdraví, proto zůstává v reportu (hasNote řekne, že tam je). V ATS z toho udělejte úkol pro personalistu.

"data": {
  "screeningId": "…",
  "requestId": "…",
  "candidate": { "id": "…", "externalRef": "ID ve vašem ATS" },
  "position": { "id": "…", "title": "…" },
  "kinds": ["more_time" | "text_answers" | "human_interview" | "other" | "new_link"],
  "hasNote": true,
  "requestedAt": "…",
  "reportUrl": "…"
}
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyEvaluro(secret, rawBody, header, toleranceSec = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
  const given = Buffer.from(parts.v1 ?? "", "hex");
  return given.length === expected.length && timingSafeEqual(given, expected);
}

Verzování a změny.

  • Verze v1 je stabilní. Bez ohlášení jen přidáváme: nová pole v odpovědích a webhoocích, nové volitelné parametry, nové události a endpointy. Neznámá pole proto ignorujte.
  • Změnu, která by rozbila existující napojení (odebrání nebo přejmenování pole, jiný význam), vydáme jen jako v2. v1 pak poběží souběžně nejméně 6 měsíců a vlastníky firem s aktivním klíčem upozorníme e-mailem.
30. 9. 2026 (večer)
Rozhodnutí personalisty oběma směry: webhook screening.decided, POST /screenings/{id}/decision (rozhodnutí z ATS) a pole decision v GET /screenings/{id}. Webhooky screening.expired, screening.failed a screening.accommodation_requested.
30. 9. 2026
POST /intake: CV ve Wordu (cvDocxBase64) a zkušební režim (dryRun). V HR portálu přehled doručení webhooků.
29. 9. 2026
POST /intake (jedno volání z ATS), webhook screening.created, praktické informace od uchazeče v screening.completed (pole logistics).
26. 9. 2026
GET /screenings se stránkováním, POST /screenings/{id}/cancel a /invite, DELETE /candidates/{id}, jednotné chyby, limit 10 000 požadavků za den.
24. 9. 2026
První verze API v1 a webhooku screening.completed.

Osobní údaje přes API.

  • Na žádost uchazeče o výmaz zavolejte DELETE /candidates/{id} – smaže CV, screeningy, záznamy i hodnocení.
  • Jinak se data smažou automaticky po lhůtě uchování nastavené firmou.
  • Webhook nenese přepis ani citace – ty zůstávají v reportu v Evaluru.