Geliştiriciler
Herkese açık API ve webhook’lar: neyi kapsadıkları, nasıl davrandıkları ve değişiklik konusunda ne söz verdiğimiz.
OpenAPI belgesi (JSON) · v0.537.0-beta
Kimlik doğrulama
Her istek bir API anahtarını bearer token olarak taşır: Authorization: Bearer <anahtar>. Kurumunuzun bir yöneticisi anahtarları Entegrasyonlar altında oluşturur; her birinin açık bir yetki listesi ve isteğe bağlı bir son kullanma tarihi vardır. Bir anahtar yalnızca ait olduğu kurumun verisini görür; süresi dolmuş ya da iptal edilmiş anahtar 401, işlemin yetkisini taşımayan anahtar 403 döner.
Sınırlar
Her anahtarın dakikada 120 isteklik kendi penceresi vardır; yazma işlemleri için daha dar bir sınır geçerlidir: dakikada 30. Her yanıt RateLimit-Limit, RateLimit-Remaining ve RateLimit-Reset taşır; 429 yanıtına Retry-After eklenir.
Sandbox anahtarı
API’yi sentetik veriyle deneyin: bir sandbox anahtarı herkese açık demonun her kaynağını okur, tüm okuma yetkilerini taşır ama hiçbir yazma yetkisi yoktur; 24 saat sonra sona erer ve günde 1000 isteğe izin verir.
Sandbox anahtarları yalnızca sentetik veri barındıran herkese açık demoda verilir. Demonun geliştirici sayfasını aç
Kurallar
- Her liste { data, page: { nextCursor, hasMore } } döner ve limit (varsayılan 50, en fazla 200), cursor ve updatedSince alır. Gezinti son değişikliğe göre artan sıradadır; istemci id üzerinden tekilleştirir.
- Yazma işlemleri Idempotency-Key başlığını kabul eder: aynı anahtar ve aynı gövde ilk yanıtı tekrarlar, farklı gövdeyle 409 döner. Geçersiz bir gövde, alan başına bir kayıtla 422 döner.
- Her hata, kararlı bir type taşıyan RFC 9457 problem belgesidir (application/problem+json). Kararı type üzerinden verin; başlık ya da açıklama metnine göre değil.
Uç noktalar
| Yöntem | Yol | Yetki | Ne yapar |
|---|---|---|---|
| GET | /api/v1/candidates | candidates:read | List candidates (mentees) |
| POST | /api/v1/candidates | candidates:write | Create a candidate |
| GET | /api/v1/candidates/{id} | candidates:read | Get a candidate |
| PATCH | /api/v1/candidates/{id} | candidates:write | Update a candidate |
| PATCH | /api/v1/relationships/{id}/stage | relationships:write | Move a relationship’s pipeline stage |
| GET | /api/v1/me | — | Who am I (connector auth test) |
| GET | /api/v1/hooks | hooks:write | List this key’s subscriptions |
| POST | /api/v1/hooks | hooks:write | Subscribe (REST hook) |
| DELETE | /api/v1/hooks/{id} | hooks:write | Unsubscribe |
| POST | /api/v1/exports | — | Export a whole resource (asynchronous) |
| GET | /api/v1/exports/{id} | — | Get an export |
| POST | /api/v1/imports/candidates | candidates:write | Import candidates in bulk (queued) |
| GET | /api/v1/imports/{id} | candidates:write | Get an import and its report |
| GET | /api/v1/relationships | relationships:read | List relationships |
| GET | /api/v1/relationships/{id} | relationships:read | Get a relationship |
| GET | /api/v1/interactions | interactions:read | List interactions |
| POST | /api/v1/interactions | interactions:write | Log an interaction |
| GET | /api/v1/interactions/{id} | interactions:read | Get an interaction |
| GET | /api/v1/meetings | meetings:read | List meetings |
| GET | /api/v1/meetings/{id} | meetings:read | Get a meeting |
| GET | /api/v1/companies | companies:read | List companies |
| GET | /api/v1/companies/{id} | companies:read | Get a company |
| GET | /api/v1/requisitions | hiring:read | List requisitions |
| GET | /api/v1/requisitions/{id} | hiring:read | Get a requisition |
| GET | /api/v1/offers | hiring:read | List offers |
| GET | /api/v1/offers/{id} | hiring:read | Get an offer |
| GET | /api/v1/interview-requests | hiring:read | List interview requests |
| GET | /api/v1/interview-requests/{id} | hiring:read | Get an interview request |
Hata türleri
| type | HTTP durumu |
|---|---|
| invalid_api_key | 401 |
| insufficient_scope | 403 |
| org_unbound | 403 |
| feature_locked | 403 |
| invalid_link | 403 |
| company_key_not_allowed | 403 |
| not_found | 404 |
| validation_failed | 400 / 422 |
| idempotency_key_reused | 409 |
| idempotency_in_progress | 409 |
| limit_reached | 409 |
| duplicate_candidate | 409 |
| invalid_transition | 409 |
| stage_conflict | 409 |
| rate_limited | 429 |
| quota_exceeded | 429 |
Webhook’lar
Bir webhook, { event, data, sentAt } gövdesiyle yapılan bir POST’tur; X-Signature başlığı gövdenin tam haliyle webhook gizli anahtarı altında alınmış onaltılık HMAC-SHA256 değeridir; yanında X-Event ve X-Delivery-Id gelir. İmzayı gövdeyi ayrıştırmadan önce ham gövde üzerinde doğrulayın ve X-Delivery-Id ile tekilleştirin: teslimat en az bir kezdir.
Bir teslimatı doğrulamak (Node.js)
const { createHmac, timingSafeEqual } = require('node:crypto');
// rawBody: the request body exactly as received (string or Buffer), before JSON.parse.
function verifyWebhook(secret, rawBody, signatureHeader) {
const expected = Buffer.from(createHmac('sha256', secret).update(rawBody).digest('hex'), 'hex');
const given = Buffer.from(String(signatureHeader || ''), 'hex');
return given.length === expected.length && timingSafeEqual(given, expected);
}Olaylar
application.created@1
data alanının şeması
{
"version": 1,
"description": "Someone applied to a mentor through the public application form.",
"schema": {
"type": "object",
"properties": {
"mentorId": {
"type": "string",
"minLength": 1
},
"menteeName": {
"type": "string"
},
"email": {
"type": "string"
}
},
"required": [
"mentorId",
"menteeName",
"email"
],
"additionalProperties": false
}
}pipeline.stage_change@1
data alanının şeması
{
"version": 1,
"description": "A mentorship moved to another pipeline stage (`from` and `to` are stage keys).",
"schema": {
"type": "object",
"properties": {
"relationId": {
"type": "string",
"minLength": 1
},
"from": {
"type": "string"
},
"to": {
"type": "string"
}
},
"required": [
"relationId",
"from",
"to"
],
"additionalProperties": false
}
}mentorship.created@1
data alanının şeması
{
"version": 1,
"description": "A mentor was assigned to a mentee.",
"schema": {
"type": "object",
"properties": {
"relationId": {
"type": "string",
"minLength": 1
},
"mentorId": {
"type": "string",
"minLength": 1
},
"menteeId": {
"type": "string",
"minLength": 1
},
"companyId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"relationId",
"mentorId",
"menteeId",
"companyId"
],
"additionalProperties": false
}
}interaction.logged@1
data alanının şeması
{
"version": 1,
"description": "An interaction (meeting, feedback, e-mail …) was logged on a mentorship.",
"schema": {
"type": "object",
"properties": {
"relationId": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string"
},
"date": {
"type": "string",
"format": "date-time"
},
"autoLogged": {
"const": true
}
},
"required": [
"relationId",
"type",
"date"
],
"additionalProperties": false
}
}evaluation.added@1
data alanının şeması
{
"version": 1,
"description": "An evaluation was submitted for a mentorship.",
"schema": {
"type": "object",
"properties": {
"relationId": {
"type": "string",
"minLength": 1
},
"type": {
"type": "string"
},
"authorId": {
"type": "string",
"minLength": 1
}
},
"required": [
"relationId",
"type",
"authorId"
],
"additionalProperties": false
}
}meeting.scheduled@1
data alanının şeması
{
"version": 1,
"description": "One or more meetings were scheduled (a batch, an instant meeting or a series occurrence).",
"schema": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"scheduledAt": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"count": {
"type": "integer",
"minimum": 0
},
"instant": {
"const": true
},
"seriesId": {
"type": "string",
"minLength": 1
}
},
"required": [
"title",
"scheduledAt",
"count"
],
"additionalProperties": false
}
}meeting.rescheduled@1
data alanının şeması
{
"version": 1,
"description": "A meeting moved to another time.",
"schema": {
"type": "object",
"properties": {
"meetingId": {
"type": "string",
"minLength": 1
},
"scheduledAt": {
"type": "string",
"format": "date-time"
},
"previousScheduledAt": {
"type": [
"string",
"null"
],
"format": "date-time"
}
},
"required": [
"meetingId",
"scheduledAt",
"previousScheduledAt"
],
"additionalProperties": false
}
}meeting.cancelled@1
data alanının şeması
{
"version": 1,
"description": "A meeting (or `count` meetings of one batch) was called off.",
"schema": {
"type": "object",
"properties": {
"meetingId": {
"type": "string",
"minLength": 1
},
"scheduledAt": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"count": {
"type": "integer",
"exclusiveMinimum": 0
}
},
"required": [
"meetingId",
"scheduledAt",
"count"
],
"additionalProperties": false
}
}interview_panel.completed@1
data alanının şeması
{
"version": 1,
"description": "Every interviewer on a panel has scored, or an admin closed it.",
"schema": {
"type": "object",
"properties": {
"panelId": {
"type": "string",
"minLength": 1
},
"subjectId": {
"type": "string",
"minLength": 1
}
},
"required": [
"panelId",
"subjectId"
],
"additionalProperties": false
}
}interview_panel.outcome@1
data alanının şeması
{
"version": 1,
"description": "A closed panel's decision was recorded.",
"schema": {
"type": "object",
"properties": {
"panelId": {
"type": "string",
"minLength": 1
},
"applicationId": {
"type": "string",
"minLength": 1
},
"outcome": {
"type": "string",
"enum": [
"ADVANCE",
"REJECT",
"OFFER"
]
}
},
"required": [
"panelId",
"applicationId",
"outcome"
],
"additionalProperties": false
}
}interview_request.scheduled@1
data alanının şeması
{
"version": 1,
"description": "An approved interview request got a meeting.",
"schema": {
"type": "object",
"properties": {
"requestId": {
"type": "string",
"minLength": 1
},
"meetingId": {
"type": "string",
"minLength": 1
},
"scheduledAt": {
"type": "string",
"format": "date-time"
},
"panelId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"requestId",
"meetingId",
"scheduledAt",
"panelId"
],
"additionalProperties": false
}
}interview_request.cancelled@1
data alanının şeması
{
"version": 1,
"description": "An interview request was called off.",
"schema": {
"type": "object",
"properties": {
"requestId": {
"type": "string",
"minLength": 1
},
"meetingId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"requestId",
"meetingId"
],
"additionalProperties": false
}
}offer.accepted@1
data alanının şeması
{
"version": 1,
"description": "The candidate accepted an offer.",
"schema": {
"type": "object",
"properties": {
"offerId": {
"type": "string",
"minLength": 1
},
"applicationId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"requisitionId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"offerId",
"applicationId",
"requisitionId"
],
"additionalProperties": false
}
}offer.declined@1
data alanının şeması
{
"version": 1,
"description": "The candidate declined an offer.",
"schema": {
"type": "object",
"properties": {
"offerId": {
"type": "string",
"minLength": 1
},
"applicationId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"requisitionId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"offerId",
"applicationId",
"requisitionId"
],
"additionalProperties": false
}
}requisition.filled@1
data alanının şeması
{
"version": 1,
"description": "An acceptance took the last opening of a requisition.",
"schema": {
"type": "object",
"properties": {
"requisitionId": {
"type": "string",
"minLength": 1
},
"offerId": {
"type": "string",
"minLength": 1
}
},
"required": [
"requisitionId",
"offerId"
],
"additionalProperties": false
}
}mentorship.lifecycle_changed@1
data alanının şeması
{
"version": 1,
"description": "A mentorship was paused, resumed, ended or reopened (`from` and `to` are lifecycle states).",
"schema": {
"type": "object",
"properties": {
"relationId": {
"type": "string",
"minLength": 1
},
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"reasonCode": {
"type": [
"string",
"null"
]
}
},
"required": [
"relationId",
"from",
"to",
"reasonCode"
],
"additionalProperties": false
}
}application.stage_changed@1
data alanının şeması
{
"version": 1,
"description": "A candidate's application for a requisition moved to another stage (`from` and `to` are stage keys, e.g. SHORTLISTED → INTERVIEW).",
"schema": {
"type": "object",
"properties": {
"applicationId": {
"type": "string",
"minLength": 1
},
"requisitionId": {
"type": "string",
"minLength": 1
},
"from": {
"type": "string"
},
"to": {
"type": "string"
}
},
"required": [
"applicationId",
"requisitionId",
"from",
"to"
],
"additionalProperties": false
}
}mentorship.transferred@1
data alanının şeması
{
"version": 1,
"description": "A mentee's mentor changed — corrected in place, or a new pairing that carries the stage over.",
"schema": {
"type": "object",
"properties": {
"relationId": {
"type": "string",
"minLength": 1
},
"previousRelationId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"menteeId": {
"type": "string",
"minLength": 1
},
"fromMentorId": {
"type": "string",
"minLength": 1
},
"toMentorId": {
"type": "string",
"minLength": 1
},
"mode": {
"type": "string",
"enum": [
"corrected",
"transferred"
]
},
"reasonCode": {
"type": "string"
}
},
"required": [
"relationId",
"previousRelationId",
"menteeId",
"fromMentorId",
"toMentorId",
"mode",
"reasonCode"
],
"additionalProperties": false
}
}offer.sent@1
data alanının şeması
{
"version": 1,
"description": "An offer was sent to the candidate.",
"schema": {
"type": "object",
"properties": {
"offerId": {
"type": "string",
"minLength": 1
},
"applicationId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"requisitionId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"offerId",
"applicationId",
"requisitionId"
],
"additionalProperties": false
}
}offer.withdrawn@1
data alanının şeması
{
"version": 1,
"description": "A sent offer was withdrawn before the candidate decided.",
"schema": {
"type": "object",
"properties": {
"offerId": {
"type": "string",
"minLength": 1
},
"applicationId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"requisitionId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"offerId",
"applicationId",
"requisitionId"
],
"additionalProperties": false
}
}offer.expired@1
data alanının şeması
{
"version": 1,
"description": "A sent offer passed its expiry date without a decision.",
"schema": {
"type": "object",
"properties": {
"offerId": {
"type": "string",
"minLength": 1
},
"applicationId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"requisitionId": {
"type": [
"string",
"null"
],
"minLength": 1
}
},
"required": [
"offerId",
"applicationId",
"requisitionId"
],
"additionalProperties": false
}
}interview_request.created@1
data alanının şeması
{
"version": 1,
"description": "A company asked to interview a shortlisted candidate for a requisition.",
"schema": {
"type": "object",
"properties": {
"requestId": {
"type": "string",
"minLength": 1
},
"requisitionId": {
"type": "string",
"minLength": 1
},
"menteeId": {
"type": "string",
"minLength": 1
},
"companyId": {
"type": "string",
"minLength": 1
}
},
"required": [
"requestId",
"requisitionId",
"menteeId",
"companyId"
],
"additionalProperties": false
}
}interview_request.approved@1
data alanının şeması
{
"version": 1,
"description": "The programme approved an interview request; scheduling comes next.",
"schema": {
"type": "object",
"properties": {
"requestId": {
"type": "string",
"minLength": 1
},
"requisitionId": {
"type": "string",
"minLength": 1
},
"menteeId": {
"type": "string",
"minLength": 1
}
},
"required": [
"requestId",
"requisitionId",
"menteeId"
],
"additionalProperties": false
}
}interview_request.declined@1
data alanının şeması
{
"version": 1,
"description": "The programme declined an interview request (`reasonCode` is a decline code, never the note).",
"schema": {
"type": "object",
"properties": {
"requestId": {
"type": "string",
"minLength": 1
},
"requisitionId": {
"type": "string",
"minLength": 1
},
"menteeId": {
"type": "string",
"minLength": 1
},
"reasonCode": {
"type": "string"
}
},
"required": [
"requestId",
"requisitionId",
"menteeId",
"reasonCode"
],
"additionalProperties": false
}
}company_interest.changed@1
data alanının şeması
{
"version": 1,
"description": "A company flagged a candidate as interesting, shortlisted or passed (`from` and `to` are interest states).",
"schema": {
"type": "object",
"properties": {
"interestId": {
"type": "string",
"minLength": 1
},
"companyId": {
"type": "string",
"minLength": 1
},
"menteeId": {
"type": "string",
"minLength": 1
},
"requisitionId": {
"type": [
"string",
"null"
],
"minLength": 1
},
"from": {
"type": [
"string",
"null"
]
},
"to": {
"type": "string"
}
},
"required": [
"interestId",
"companyId",
"menteeId",
"requisitionId",
"from",
"to"
],
"additionalProperties": false
}
}Sürümleme ve kullanımdan kaldırma
v1 içinde değişiklikler yalnızca eklemelidir: yeni uç noktalar, yeni isteğe bağlı parametreler, yeni alanlar ve yeni hata türleri her an gelebilir; tanımadığınızı yok sayın. Bir alanı, parametreyi ya da uç noktayı kaldırmak veya yeniden adlandırmak, bir türü değiştirmek ya da doğrulamayı sıkılaştırmak kırıcıdır: en az 6 ay önceden duyurulur ve aşağıda listelenir; kullanımdan kalkan bir işlem Deprecation ve Sunset başlıklarıyla yanıt verir. Bu sözü tutamayan bir değişiklik v1 içinde isteğe bağlı bir parametre olarak ya da v2 olarak gelir.
Duyurulmuş kaldırmalar
| Ne | Başlangıç | Kaldırılma tarihi |
|---|---|---|
| `candidates` key on `GET /api/v1/candidates` (alias of `data`) | #1988 | 2027-01-31 |
API dahil her yayımlanan değişiklik sürüm notlarında tarihli olarak yer alır. Sürüm notları