Zum Inhalt springen

Entwickler

Die öffentliche API und die Webhooks: was sie abdecken, wie sie sich verhalten und was wir bei Änderungen zusagen.

OpenAPI-Dokument (JSON) · v0.537.0-beta

Authentifizierung

Jede Anfrage trägt einen API-Schlüssel als Bearer-Token: Authorization: Bearer <Schlüssel>. Ein Admin Ihrer Organisation legt Schlüssel unter Integrationen an, jeweils mit einer ausdrücklichen Liste von Berechtigungen und optionalem Ablaufdatum. Ein Schlüssel sieht nur die Daten der Organisation, zu der er gehört; ein abgelaufener oder widerrufener Schlüssel erhält 401, ein Schlüssel ohne die Berechtigung der Operation 403.

Limits

Jeder Schlüssel hat ein eigenes Fenster von 120 Anfragen pro Minute, Schreibzugriffe ein engeres von 30 pro Minute. Jede Antwort trägt RateLimit-Limit, RateLimit-Remaining und RateLimit-Reset; ein 429 zusätzlich Retry-After.

Sandbox-Schlüssel

Testen Sie die API mit synthetischen Daten: Ein Sandbox-Schlüssel liest jede Ressource der öffentlichen Demo, hat alle Leseberechtigungen und keine Schreibberechtigung, läuft nach 24 Stunden ab und erlaubt 1000 Anfragen pro Tag.

Sandbox-Schlüssel gibt es auf der öffentlichen Demo, die nur synthetische Daten enthält. Entwicklerseite der Demo öffnen

Konventionen

  • Jede Liste antwortet mit { data, page: { nextCursor, hasMore } } und nimmt limit (Standard 50, höchstens 200), cursor und updatedSince. Die Reihenfolge ist aufsteigend nach letzter Änderung; ein Client dedupliziert über id.
  • Schreibzugriffe akzeptieren einen Idempotency-Key-Header: derselbe Schlüssel mit demselben Body liefert die erste Antwort erneut, mit anderem Body ist es ein 409. Ein ungültiger Body erhält 422 mit einem Eintrag pro Feld.
  • Jeder Fehler ist ein RFC-9457-Problem-Dokument (application/problem+json) mit stabilem type. Entscheiden Sie anhand von type, nie anhand von Titel oder Detailtext.

Endpunkte

MethodePfadBerechtigungWas er tut
GET/api/v1/candidatescandidates:readList candidates (mentees)
POST/api/v1/candidatescandidates:writeCreate a candidate
GET/api/v1/candidates/{id}candidates:readGet a candidate
PATCH/api/v1/candidates/{id}candidates:writeUpdate a candidate
PATCH/api/v1/relationships/{id}/stagerelationships:writeMove a relationship’s pipeline stage
GET/api/v1/me—Who am I (connector auth test)
GET/api/v1/hookshooks:writeList this key’s subscriptions
POST/api/v1/hookshooks:writeSubscribe (REST hook)
DELETE/api/v1/hooks/{id}hooks:writeUnsubscribe
POST/api/v1/exports—Export a whole resource (asynchronous)
GET/api/v1/exports/{id}—Get an export
POST/api/v1/imports/candidatescandidates:writeImport candidates in bulk (queued)
GET/api/v1/imports/{id}candidates:writeGet an import and its report
GET/api/v1/relationshipsrelationships:readList relationships
GET/api/v1/relationships/{id}relationships:readGet a relationship
GET/api/v1/interactionsinteractions:readList interactions
POST/api/v1/interactionsinteractions:writeLog an interaction
GET/api/v1/interactions/{id}interactions:readGet an interaction
GET/api/v1/meetingsmeetings:readList meetings
GET/api/v1/meetings/{id}meetings:readGet a meeting
GET/api/v1/companiescompanies:readList companies
GET/api/v1/companies/{id}companies:readGet a company
GET/api/v1/requisitionshiring:readList requisitions
GET/api/v1/requisitions/{id}hiring:readGet a requisition
GET/api/v1/offershiring:readList offers
GET/api/v1/offers/{id}hiring:readGet an offer
GET/api/v1/interview-requestshiring:readList interview requests
GET/api/v1/interview-requests/{id}hiring:readGet an interview request

Fehlertypen

typeHTTP-Status
invalid_api_key401
insufficient_scope403
org_unbound403
feature_locked403
invalid_link403
company_key_not_allowed403
not_found404
validation_failed400 / 422
idempotency_key_reused409
idempotency_in_progress409
limit_reached409
duplicate_candidate409
invalid_transition409
stage_conflict409
rate_limited429
quota_exceeded429

Webhooks

Ein Webhook ist ein POST von { event, data, sentAt } mit einem X-Signature-Header — dem hexadezimalen HMAC-SHA256 des exakten Request-Bodys unter dem Secret des Hooks — sowie X-Event und X-Delivery-Id. Prüfen Sie die Signatur am rohen Body, bevor Sie ihn parsen, und deduplizieren Sie über X-Delivery-Id: zugestellt wird mindestens einmal.

Eine Zustellung prüfen (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);
}

Ereignisse

application.created@1

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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

Schema von data

{
  "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
  }
}

Versionierung und Deprecation

Innerhalb von v1 sind Änderungen nur additiv: neue Endpunkte, neue optionale Parameter, neue Felder und neue Fehlertypen können jederzeit hinzukommen; ignorieren Sie, was Sie nicht kennen. Ein Feld, einen Parameter oder Endpunkt zu entfernen oder umzubenennen, einen Typ zu ändern oder die Validierung zu verschärfen, ist inkompatibel: Das wird mindestens 6 Monate vorher angekündigt und unten aufgeführt, und eine abgekündigte Operation antwortet mit Deprecation- und Sunset-Headern. Eine Änderung, die diese Zusage nicht halten kann, kommt als optionaler Parameter innerhalb von v1 oder als v2.

Angekündigte Abkündigungen

WasSeitEntfernt am
`candidates` key on `GET /api/v1/candidates` (alias of `data`)#19882027-01-31

Jede ausgelieferte Änderung, die API eingeschlossen, steht datiert in den Versionshinweisen. Versionshinweise