Dokumentacja API
Uwierzytelnij się i odpytuj API rekrutacyjne, żeby pobrać dane o ogłoszeniach o pracę, kandydatach i aplikacjach.
Dlaczego to ważne
API rekrutacyjne umożliwia systemom zewnętrznym odczyt danych rekrutacyjnych — portale z ofertami pracy pobierają opublikowane ogłoszenia, systemy HRIS synchronizują dane kandydatów, a panele kontrolne śledzą metryki procesu rekrutacji. Zakresy uprawnień tokenu zapewniają, że każda integracja widzi tylko to, czego potrzebuje.
Bazowy URL
Wszystkie endpointy API są dostępne pod adresem:
https://startupkit.app/api/v1
Uwierzytelnianie
Każde żądanie wymaga tokenu API w nagłówku Authorization:
Authorization: Bearer YOUR_TOKEN
Alternatywny format (oba działają):
Authorization: token YOUR_TOKEN
Tokeny można utworzyć w sekcji Settings > API. Każdy token musi mieć jawnie przypisane zakresy uprawnień, aby uzyskać dostęp do endpointów rekrutacyjnych.
| Zakres | Dostęp |
|---|---|
job_postings:read |
Ogłoszenia o pracę i etapy |
candidates:read |
Dane osobowe kandydatów (imię, e-mail, telefon), pola meta aplikacji, pobieranie CV |
applications:read |
Aplikacje, historia etapów, pobieranie CV |
Tokeny bez przypisanych zakresów nie mają dostępu do endpointów rekrutacyjnych.
Format i cykl życia tokenu
-
Format: 24-znakowy ciąg base58 (np.
k3Jf9pQ2mZ7xR4nL8vT6bWyH) - Pokazywany tylko raz: Surowy token wyświetla się dokładnie raz — na ekranie potwierdzenia zaraz po utworzeniu. Skopiuj go od razu; później nie da się go odzyskać.
- Przechowywany tylko jako skrót: Kit zapisuje wyłącznie skrót SHA-256 tokenu, nigdy postaci jawnej. Jeśli zgubisz token, unieważnij go i utwórz nowy; pierwotnej wartości nie da się odzyskać.
-
Śledzenie ostatniego użycia: Każde udane żądanie aktualizuje pole
last_used_at - Brak daty wygaśnięcia: Tokeny nie wygasają po upływie czasu. Formularz tworzenia nie ma opcji wygaśnięcia, a Settings > API nie pokazuje żadnej takiej daty — token pozostaje ważny, dopóki go nie unieważnisz.
- Alerty o braku aktywności: Tokeny nieużywane przez ponad 30 dni generują powiadomienia dla administratorów
- Automatyczne unieważnienie: Tokeny są automatycznie unieważniane po usunięciu użytkownika z konta
Zalecana praktyka: twórz osobne tokeny dla każdej integracji z minimalnymi wymaganymi zakresami uprawnień.
Zakres konta
Każdy token API jest powiązany z konkretnym kontem. Konto jest ustalane automatycznie na podstawie tokenu — parametr account_id nie jest wymagany.
Gdy członek zespołu zostanie usunięty z konta, jego tokeny dla tego konta są automatycznie unieważniane.
Odpowiedzi z błędami
| Status | Znaczenie | Najczęstsze przyczyny |
|---|---|---|
400 |
Nieprawidłowe żądanie | Brak kontekstu konta (przypadek brzegowy przy uwierzytelnianiu sesyjnym) |
401 |
Brak autoryzacji | Brakujący, nieprawidłowy lub unieważniony token |
403 |
Brak dostępu | Token nie ma wymaganego zakresu uprawnień dla tego endpointu |
404 |
Nie znaleziono | Zasób nie istnieje lub nie należy do danego konta |
422 |
Błąd walidacji | Błędy walidacji (głównie dla endpointów spoza modułu rekrutacji) |
Paginacja
Endpointy listowe zwracają wyniki z paginacją:
{
"data": [...],
"pagination": {
"current_page": 1,
"total_pages": 3,
"total_count": 42,
"per_page": 20
}
}
Przekaż parametr ?page=2, żeby pobrać kolejne strony.
Ogłoszenia o pracę
Wymagany zakres: job_postings:read
Lista ogłoszeń o pracę
GET /api/v1/job_postings
Przykład:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://startupkit.app/api/v1/job_postings?status=published
Parametry:
| Parametr | Typ | Opis |
|---|---|---|
status |
string | Filtrowanie według statusu: draft, published, paused lub closed
|
page |
integer | Numer strony |
Odpowiedź:
{
"data": [
{
"id": "job_abc123",
"title": "Senior Rails Developer",
"status": "published",
"department": "Engineering",
"location": "New York, NY",
"employment_type": "full_time",
"remote": true,
"salary_min": "120000.0",
"salary_max": "180000.0",
"salary_currency": "USD",
"salary_period": "year",
"published_at": "2026-01-15T10:00:00Z",
"closed_at": null,
"created_at": "2026-01-10T08:30:00Z",
"updated_at": "2026-02-01T14:20:00Z",
"stages": [
{
"id": "stg_def456",
"name": "Screening",
"stage_type": "default",
"position": 0
}
],
"counts": {
"total_applications": 24,
"active_applications": 18,
"rejected": 6
}
}
],
"pagination": { ... }
}
Pobieranie ogłoszenia o pracę
GET /api/v1/job_postings/:id
Zwraca dane w tym samym formacie co pojedynczy element odpowiedzi listowej.
Lista etapów
GET /api/v1/job_postings/:job_posting_id/stages
Odpowiedź:
{
"data": [
{
"id": "stg_def456",
"name": "Screening",
"stage_type": "default",
"position": 0
}
]
}
Etapy są posortowane według pozycji. Bez paginacji.
Kandydaci
Wymagany zakres: candidates:read
Lista kandydatów
GET /api/v1/candidates
Przykład:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://startupkit.app/api/v1/[email protected]
Parametry:
| Parametr | Typ | Opis |
|---|---|---|
search |
string | Wyszukiwanie według imienia, nazwiska lub adresu e-mail |
page |
integer | Numer strony |
Odpowiedź:
{
"data": [
{
"id": "cand_ghi789",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone": "+1-555-0100",
"status": "active",
"github_username": "johndoe",
"created_at": "2026-01-20T09:15:00Z",
"applications": [
{
"id": "app_jkl012",
"job_posting_id": "job_abc123",
"job_posting_title": "Senior Rails Developer",
"current_stage_name": "Interview",
"status": "active",
"submitted_at": "2026-01-20T09:15:00Z"
}
]
}
],
"pagination": { ... }
}
Pobieranie kandydata
GET /api/v1/candidates/:id
Zwraca dane w tym samym formacie co pojedynczy element odpowiedzi listowej.
Aplikacje
Wymagany zakres: applications:read
Lista aplikacji
GET /api/v1/applications
Przykład:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://startupkit.app/api/v1/applications?job_posting_id=job_abc123&status=active
Parametry:
| Parametr | Typ | Opis |
|---|---|---|
job_posting_id |
string | Filtrowanie według prefiksowego ID ogłoszenia o pracę |
status |
string | Filtrowanie według statusu: active lub rejected
|
page |
integer | Numer strony |
Odpowiedź:
{
"data": [
{
"id": "app_jkl012",
"job_posting_id": "job_abc123",
"candidate_id": "cand_ghi789",
"current_stage_name": "Interview",
"status": "active",
"submitted_at": "2026-01-20T09:15:00Z",
"created_at": "2026-01-20T09:15:00Z",
"updated_at": "2026-02-10T11:30:00Z",
"candidate": {
"id": "cand_ghi789",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]"
},
"stage_history": [
{
"id": "sp_mno345",
"stage_name": "Screening",
"stage_type": "default",
"status": "completed",
"started_at": "2026-01-20T09:15:00Z",
"completed_at": "2026-01-25T16:00:00Z"
},
{
"id": "sp_pqr678",
"stage_name": "Interview",
"stage_type": "interview",
"status": "in_progress",
"started_at": "2026-01-25T16:00:00Z",
"completed_at": null
}
],
"metafields": [
{
"key": "years_of_experience",
"label": "Years of Experience",
"field_type": "number",
"value": "8",
"source": "ai",
"confidence": 0.92,
"extracted_at": "2026-01-20T09:18:00Z",
"edited": false,
"original_value": null
},
{
"key": "salary_expectation",
"label": "Salary Expectation",
"field_type": "number",
"value": "150000",
"source": "ai",
"confidence": 0.75,
"extracted_at": "2026-01-20T09:18:00Z",
"edited": true,
"original_value": "140000"
}
]
}
],
"pagination": { ... }
}
Dane pól meta
Wymagany zakres: candidates:read
Wartości pól meta mogą zawierać dane osobowe kandydata wyodrębnione przez AI, dlatego tablica metafields jest chroniona zakresem candidates:read — tym samym, który chroni blok candidate — a nie zakresem applications:read. Token z zakresem applications:read, ale bez candidates:read, dostaje odpowiedzi o aplikacjach w ogóle bez klucza metafields. Przykładowa odpowiedź powyżej pokazuje to, co widzi token z obydwoma zakresami.
Jeśli token ma zakres candidates:read, każda aplikacja zawiera tablicę metafields z ustrukturyzowanymi polami danych wyodrębnionymi lub wprowadzonymi dla tej aplikacji. Każdy wpis zawiera:
| Pole | Typ | Opis |
|---|---|---|
key |
string | Maszynowy identyfikator pola |
label |
string | Czytelna dla człowieka nazwa wyświetlana |
field_type |
string | Typ danych — dokładnie jeden z tych dziewięciu: text, textarea, number, date, select, boolean, url, rating, tags
|
value |
string | null | Bieżąca wartość (zawsze serializowana jako ciąg znaków) |
source |
string | Sposób ustawienia wartości — dokładnie jedna z dwóch wartości: manual (wprowadzona lub zmieniona przez człowieka) albo ai (wyodrębniona lub ustawiona przez AI) |
confidence |
float | null | Wskaźnik pewności AI (0.0–1.0), gdy source to ai; w przeciwnym razie null
|
extracted_at |
timestamp | null | Kiedy wartość została ustawiona lub wyodrębniona |
edited |
boolean |
true tylko wtedy, gdy wartość pochodząca z AI została później nadpisana czymś innym niż surowe wyodrębnienie przez AI (w praktyce wywołaniem MCP hiring_update_metafield_value). Zmiany wprowadzone przez człowieka we własnym interfejsie Kit zapisują source: manual i zawsze zwracają edited: false. |
original_value |
string | null | Pierwotna wartość wyodrębniona przez AI przed edycją przez człowieka; null, jeśli nigdy nie edytowano |
W obrębie tokenu z zakresem candidates:read tablica metafields nie jest już dodatkowo filtrowana według flagi widoczności managers_only. Każde pole meta zdefiniowane w ogłoszeniu o pracę — w tym pola oznaczone jako managers_only w konfiguracji ogłoszenia — jest zwracane niezależnie od roli właściciela tokenu. Zakres candidates:read jest więc jedynym mechanizmem kontrolującym dostęp do pól meta: jeśli pole zawiera dane wrażliwe, których nie chcesz udostępniać integracji, nie przyznawaj tej integracji zakresu candidates:read, ponieważ API nie stosuje filtrowania widoczności dla menedżerów używanego w innych częściach aplikacji. Sam zakres applications:read jest pod tym względem bezpieczny — zwraca historię etapów i status aplikacji, bez pól meta.
Pobieranie aplikacji
GET /api/v1/applications/:id
Zwraca dane w tym samym formacie co pojedynczy element odpowiedzi listowej. Gdy token ma zakres candidates:read, a do aplikacji dołączono CV, odpowiedź zawiera metadane CV:
{
"id": "app_jkl012",
"resume_filename": "john_doe_resume.pdf",
"resume_content_type": "application/pdf",
"resume_byte_size": 245760,
...
}
Te pola są pomijane, gdy CV nie jest dołączone lub brakuje zakresu candidates:read.
Pobieranie CV
Wymagane zakresy: applications:read + candidates:read
GET /api/v1/applications/:application_id/resume
Pobiera CV kandydata dla wskazanej aplikacji. Zwraca przekierowanie 302 na podpisany URL z ograniczonym czasem ważności (30 minut).
Przykład:
curl -L -H "Authorization: Bearer YOUR_TOKEN" \
-o resume.pdf \
https://startupkit.app/api/v1/applications/app_jkl012/resume
Odpowiedź:
-
302 Found– Przekierowanie na podpisany URL do pobrania. Użyj-L(podążanie za przekierowaniami) w curl. -
403 Forbidden– Token nie ma zakresuapplications:readlubcandidates:read. -
404 Not Found– Nie znaleziono aplikacji lub brak dołączonego CV.
Uwagi:
- Podpisane URL wygasają po 30 minutach. Po wygaśnięciu pobierz nowy.
- Nagłówek
Content-Dispositionjest ustawiony naattachment(wymusza pobranie pliku przez przeglądarkę). - Obsługiwane formaty CV: PDF, DOC, DOCX (zgodnie z tym, co przesłał kandydat).
Maskowanie danych osobowych kandydata
Gdy token ma zakres applications:read, ale nie ma zakresu candidates:read, dane kandydata w odpowiedziach dotyczących aplikacji są ograniczone wyłącznie do identyfikatora:
{
"candidate": {
"id": "cand_ghi789"
}
}
Pola first_name, last_name ani email nie są uwzględniane. Ta sama zasada obejmuje tablicę metafields oraz pola z metadanymi CV — one również są całkowicie pomijane, bo także mogą zawierać dane osobowe kandydata. Dzięki temu integracje z portalami ofert pracy mogą śledzić status aplikacji bez ujawniania danych kontaktowych kandydatów.
Rozwiązywanie problemów
Problemy z uwierzytelnianiem
401 Unauthorized
Jeśli dostajesz odpowiedź 401, sprawdź:
- Format tokenu: Token powinien odpowiadać wartości pokazanej jednorazowo podczas tworzenia (24-znakowy ciąg base58). Jeśli już go nie masz, unieważnij token i utwórz nowy — Kit przechowuje tylko zahaszowany skrót i nie pokaże go ponownie.
-
Nagłówek Authorization: Musi mieć format
Authorization: Bearer TOKENlubAuthorization: token TOKEN - Czy token nadal istnieje: Sprawdź, czy token wciąż jest na liście w Settings > API — unieważniony token zostaje usunięty, a nie wyłączony
- Członkostwo w koncie: Upewnij się, że właściciel tokenu nadal jest członkiem konta
403 Forbidden
Gdy dostajesz odpowiedź 403, token jest prawidłowy, ale nie ma wymaganego zakresu uprawnień:
-
Sprawdź wymagane zakresy: Każdy endpoint dokumentuje wymagany zakres (np.
job_postings:read) - Dodaj brakujące zakresy: Edytuj token w Settings > API i dodaj potrzebny zakres
-
Format zakresu: Musi dokładnie odpowiadać wzorcowi —
job_postings:read, a niejob_postingslubread
Problemy z dostępem do danych
Pusta tablica data w odpowiedziach
Jeżeli API zwraca {"data": [], "pagination": {...}}, a spodziewane są wyniki:
- Izolacja kont: Tokeny API widzą tylko dane z konta, do którego są przypisane
- Weryfikacja konta: Sprawdź, do którego konta należy token w Settings > API
- Dostęp między kontami: Tokeny nie mogą uzyskać dostępu do danych z innych kont, nawet jeśli użytkownik jest ich członkiem
Dane osobowe kandydata są zamaskowane
Jeżeli widoczne jest jedynie {"candidate": {"id": "cand_..."}} bez imienia i adresu e-mail:
-
Oczekiwane zachowanie: Dzieje się tak, gdy token ma zakres
applications:read, ale nie ma zakresucandidates:read -
Dodaj zakres: Żeby zobaczyć pełne dane kandydata, dodaj zakres
candidates:readdo tokenu - Ochrona prywatności: Dzięki temu integracje mogą śledzić aplikacje bez ujawniania danych kontaktowych
Brak tablicy metafields w odpowiedziach o aplikacjach
Tablica metafields jest chroniona zakresem candidates:read, a nie applications:read, bo wartości pól meta mogą zawierać dane osobowe kandydata wyodrębnione przez AI. Jeśli w odpowiedziach nie ma klucza metafields, token nie ma zakresu candidates:read. Dodaj go tylko wtedy, gdy integracja ma widzieć również imiona i nazwiska kandydatów, adresy e-mail oraz CV — te dane idą w parze.
Problemy z zapytaniami i filtrowaniem
404 przy wyszukiwaniu konkretnych rekordów
-
Prefiksowe ID: Ogłoszenia o pracę używają formatu
job_abc123, a nie identyfikatorów bazodanowych takich jak42 - Wielkość liter: Prefiksowe ID rozróżniają wielkość liter
- Zakres konta: Zasób musi należeć do konta powiązanego z tokenem
Parametry filtrowania nie działają
-
Dopuszczalne wartości statusów:
- Ogłoszenia o pracę:
draft,published,paused,closed(z uwzględnieniem wielkości liter) - Aplikacje:
active,rejected(z uwzględnieniem wielkości liter)
- Ogłoszenia o pracę:
-
Format parametrów: Używaj
?status=published, a nie?status=Publishedlub?filter[status]=published
Często zadawane pytania
Jak działa paginacja?
Wszystkie endpointy listowe zwracają 20 elementów na stronę (wartość stała). Żeby przejść do następnej strony, użyj parametru ?page=2. Obiekt pagination zawiera pola total_pages i total_count.
Czy tokeny wygasają automatycznie?
Nie. Przy tworzeniu tokenu nie ma żadnego ustawienia wygaśnięcia, więc token pozostaje ważny do momentu:
- Ręcznego unieważnienia w Settings > API
- Usunięcia użytkownika z konta
- Usunięcia konta
Czy należy używać jednego tokenu dla wielu integracji?
Nie. Zalecana praktyka to jeden token na integrację z minimalnymi zakresami uprawnień. Ułatwia to:
- Audyt żądań poszczególnych integracji (poprzez pole
last_used_at) - Unieważnienie dostępu konkretnej integracji bez wpływu na pozostałe
- Nadawanie różnych uprawnień różnym systemom
Jaki jest związek między webhookami a API?
Webhooki powiadamiają o zdarzeniach (nowa aplikacja, zmiana etapu). API umożliwia odpytywanie bieżącego stanu. Używaj webhooków do wyzwalania działań w systemie, a następnie API do pobierania pełnych danych.
Czy można pobrać więcej niż 20 elementów na stronę?
Nie. Rozmiar strony jest ustalony na 20 elementów, żeby zapewnić stałą wydajność. Używaj parametru page do iterowania po wszystkich wynikach.
Szybka lista kontrolna
- Utwórz token API w sekcji Settings > API — każdy token jest powiązany z danym kontem
- Przypisz tylko te zakresy, których wymaga integracja (zalecana praktyka: jeden token na integrację z minimalnymi zakresami)
-
Nie przyznawaj zakresu
candidates:read, jeśli integracja nie musi widzieć danych osobowych kandydatów — ten zakres kontroluje też tablicęmetafieldsi dostęp do CV -
Dołączaj nagłówek
Authorization: Bearer TOKENdo każdego żądania -
Używaj prefiksowych ID (np.
job_abc123) w adresach URL zamiast identyfikatorów bazodanowych -
Obsługuj odpowiedzi
400i422w przypadku błędów walidacji -
Obsługuj odpowiedzi
401— token mógł zostać unieważniony -
Obsługuj odpowiedzi
403— token może nie mieć wymaganego zakresu uprawnień -
Używaj parametru
pagedo paginacji dużych zbiorów wyników (20 elementów na stronę)