MentPass API reference
Mentees, questionnaires, tasks, decisions and webhooks for your workspace.
- Version
- 1.0.0 (OpenAPI 3.1.0)
- Base URL
- https://app.mentpass.com
- Scopes
- decisions:read, decisions:write, mentees:read, mentees:write, questionnaires:read, assignments:write, tasks:read, tasks:write, webhooks:write, workflows:read, workflows:run
Guides
Authentication and scopes
Send an API key created in API & integrations as Authorization: Bearer mpk_…. Mentors and mentees can create keys when the workspace plan includes API access. Cookies are never used. Keys expire, can be rotated with a grace period, and can be revoked; a revoked or expired key fails the next request with 401 invalid_credentials.
Each operation needs the scope shown next to it. A key without it gets 403 insufficient_scope. Mentor keys act inside the issuer’s workspace. Mentee keys are permanently bound to their own profile: collection reads automatically contain only their data, and another person’s profile, decision, task or meeting ID returns 404, even within the same workspace.
Personal keys allow mentees:read, decisions:read, decisions:write, tasks:read and tasks:write only. They cannot create mentees, assign questionnaires, discover or run workflows, or manage webhooks. Only the owning mentee can list, rotate or revoke a personal key. Account deactivation, a locked profile or a changed role invalidates it.
Private fields
Some fields are private, for example mentor notes, recording summaries, transcripts and routing emails. They are included only when the key was created with private access, and are omitted (not set to null) otherwise. Recording content is also withheld for recordings captured through another mentor's provider connection.
Mentee keys cannot request private access. Mentor notes, decision review/source provenance and routing emails remain omitted. An authenticated mentee may read summaries, recordings and paginated transcripts of their own meetings, as in the web app, without a mentor private-access grant.
Errors
Errors use one envelope: {"error": {"code", "message", "requestId"}} plus fieldErrors (validation_failed), resetAt (quota_exhausted) or conflict (mentee conflicts). Branch on code, not on message. The table below lists every code the API returns and its status. 410 Gone is not used.
New error codes may be added within v1; treat an unknown code by its HTTP status.
Pagination
List responses are {"data": [...], "nextCursor": string|null}. Pass nextCursor as cursor to get the next page; null means the last page. Cursors are opaque and only valid with the filters they were issued for (otherwise 422 validation_failed). Page sizes are set with limit within each operation's maximum.
Meeting transcripts page separately with transcriptCursor; if the transcript changed meanwhile the response is 409 revision_conflict and you restart without a cursor.
Rate limits and metering
Requests are limited per minute and per month for the workspace's plan. Successful and error responses after authentication carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds). Above the minute limit the response is 429 rate_limited; when the monthly allowance is used it is 429 quota_exhausted with resetAt. Both carry Retry-After.
Requests are counted after authentication, scope and rate checks, including 4xx responses. 5xx responses, idempotent replays and webhook delivery replays are not counted, and neither are 429 responses.
Idempotency
Every write (POST, PATCH, DELETE) needs an Idempotency-Key header (16 to 128 letters, digits, - or _); without it the response is 400 idempotency_key_required. Retrying with the same key and the same request returns the stored result with Idempotent-Replayed: true and changes nothing. Reusing a key for a different request is 409 idempotency_conflict. Keys are kept for 30 days per API key lineage.
Concurrency (If-Match)
PATCH /api/v1/tasks/{taskId} needs If-Match with the revision you read (for example "3"). If the task changed in the meantime, on the web or by another integration, the response is 409 revision_conflict and nothing is written. Fetch the task again and retry.
Webhooks
Webhooks follow Standard Webhooks. Each POST carries webhook-id, webhook-timestamp and webhook-signature. Verify the signature over the raw body before parsing, reject timestamps more than 5 minutes old, and deduplicate on webhook-id: delivery is at least once and unordered (order by data.revision).
Payloads contain identifiers and non-private fields only, built when each attempt is sent with the endpoint key's current scopes and private access. origin carries the channel and the operationId/correlationId returned in your write receipts (never a credential id); skip events whose origin.operationId is one of your own writes. A decision event whose decision is no longer visible to the key is cancelled with EVENT_NOT_VISIBLE and not sent.
Failed deliveries are retried with exponential backoff and jitter, up to 8 attempts. An endpoint that keeps failing is disabled after at least 15 consecutive failures over 24 hours. If the workspace loses API access, deliveries wait and expire after the normal retry window (about 64 minutes). Replay any logged delivery with the same webhook-id.
Versioning and deprecation
The major version is in the path (/api/v1). Within v1, changes are additive only: new operations, new optional request fields, new response fields, new event types, new enum values and new error codes. Build clients that ignore unknown fields and handle unknown enum values.
Breaking changes ship only in a new major version. No v1 operation is deprecated today, and Deprecation and Sunset headers are not sent.
Workflow runs
Starting a run needs two scopes: workflows:run and mentees:read. Reading a run needs workflows:read and mentees:read. A key holding only one of the pair gets 403 insufficient_scope, and that refusal is not counted against the request allowance.
Send an Idempotency-Key. The same key with the same body returns the stored result: 200 with Idempotent-Replayed for an admitted request, or the same 409 workflow_not_admitted for one that admitted nobody. The same key with a different body is 409 idempotency_conflict. Invalid requests (422) are never stored, so you may correct and retry them under the same key. Repeated mentee ids in one request are refused rather than merged, and the list is sorted before it is compared, so [b, a] and [a, b] are the same request.
A request that is valid but admits nobody - the workflow is paused, the selection is over the fan-out limit, or the workflow run allowance is used up - returns 409 workflow_not_admitted with the reason and the recorded invocationId. No mentee ids, counts, caps or allowance figures are returned.
Runs execute under the authority of the mentor who turned the workflow on. Revoking or rotating the key does not cancel a run that was already admitted; cancel it in the app. Run status never returns names, message text, condition operands, fact names or the ids of the people who authored or authorised the workflow.
Error codes
| Code | HTTP status |
|---|---|
| idempotency_key_required | 400 |
| invalid_credentials | 401 |
| client_limit_reached | 403 |
| feature_unavailable | 403 |
| forbidden | 403 |
| insufficient_scope | 403 |
| plan_required | 403 |
| not_found | 404 |
| conflict | 409 |
| idempotency_conflict | 409 |
| revision_conflict | 409 |
| workflow_not_admitted | 409 |
| validation_failed | 422 |
| precondition_required | 428 |
| quota_exhausted | 429 |
| rate_limited | 429 |
| internal_error | 500 |
| retry_later | 503 |
Mentees
Find or list mentees
get/api/v1/mentees
Find a mentee by externalId or email (not both), or page the workspace's mentees, newest first.
- Operation
- mentee.list
- Scope
- mentees:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| externalId | query | string | No | Exact external id. Length 0 to 128. |
| query | string | No | Case-insensitive email. Length 0 to 320. | |
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 100 (default 25). Range 1 to 100. Default 25. |
Response 200
Schema: MenteePage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of MenteeSummary | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
Errors
Create a mentee
post/api/v1/mentees
Creates a mentee (client), optionally assigns published questionnaires and, with sendInvite, queues one invitation. An existing externalId or email is a 409 conflict, never an update.
- Operation
- mentee.create
- Scope
- mentees:write
- Also needs
- assignments:write when questionnaires non-empty
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: MenteeCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | Yes | Length 1 to 200. |
| string (email) | Yes | ||
| company | string or null | No | Length 0 to 200. |
| website | string or null | No | Length 0 to 2000. |
| phone | string or null | No | Length 0 to 100. |
| tidycalBookingUrl | string or null | No | Length 0 to 2000. |
| timeZone | string | No | Default "UTC". |
| sendInvite | boolean | Yes | Required. true queues one invitation email to the mentee. |
| questionnaires | array of QuestionnaireSelection | Yes | Non-empty needs assignments:write as well. Items 0 to 20. |
| externalId | string | No | Your system's id (for example a CRM contact id). Unique per workspace. Pattern ^[A-Za-z0-9._:@|/-]{1,128}$. |
Response 201
Schema: MenteeCreateReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | MenteeCreateReceipt | Yes |
Errors
- 403 client_limit_reached
- 409 conflict
- 403 feature_unavailable
- 403 forbidden
- 409 idempotency_conflict
- 400 idempotency_key_required
- 403 insufficient_scope
- 500 internal_error
- 401 invalid_credentials
- 404 not_found
- 403 plan_required
- 429 quota_exhausted
- 429 rate_limited
- 503 retry_later
- 409 revision_conflict
- 422 validation_failed
Get a mentee
get/api/v1/mentees/{menteeProfileId}
One mentee. privateNotes needs private access.
- Operation
- mentee.get
- Scope
- mentees:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| menteeProfileId | path | string | Yes | Mentee (client) profile id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
Response 200
Schema: MenteeResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | MenteeDetail | Yes |
Errors
List a mentee's meetings
get/api/v1/mentees/{menteeProfileId}/meetings
Meetings of one mentee, newest first. Recording fields need private access and are withheld for another mentor's recordings. Mentee keys can read their own meeting content without a private-access grant.
- Operation
- mentee.meeting.list
- Scope
- mentees:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| menteeProfileId | path | string | Yes | Mentee (client) profile id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 50 (default 20). Range 1 to 50. Default 20. |
Response 200
Schema: MeetingPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of Meeting | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
Errors
Get a meeting
get/api/v1/mentees/{menteeProfileId}/meetings/{meetingId}
One meeting with (private access) its summary on the first page and one bounded transcript page. Mentee keys can read their own meeting content without a private-access grant.
- Operation
- mentee.meeting.get
- Scope
- mentees:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| menteeProfileId | path | string | Yes | Mentee (client) profile id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| meetingId | path | string | Yes | Meeting id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| transcriptCursor | query | string | No | transcript.nextCursor from the previous page. Length 0 to 1024. |
| transcriptLimit | query | integer | No | Segments per page, 1 to 500 (default 200). Range 1 to 500. Default 200. |
Response 200
Schema: MeetingResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | MeetingDetail | Yes |
Errors
Questionnaires
Assign questionnaires
post/api/v1/mentees/{menteeProfileId}/questionnaire-assignments
Assigns published questionnaire versions to a mentee. An already open assignment is reported in reusedAssignmentIds, not duplicated.
- Operation
- assignment.create
- Scope
- assignments:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| menteeProfileId | path | string | Yes | Mentee (client) profile id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: AssignmentRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| questionnaires | array of QuestionnaireSelection | Yes | Items 1 to 20. |
Response 201
Schema: AssignmentReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | AssignmentReceipt | Yes |
Errors
List published questionnaires
get/api/v1/questionnaires
Currently published questionnaires with the version ids to assign.
- Operation
- questionnaire.list
- Scope
- questionnaires:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 100 (default 50). Range 1 to 100. Default 50. |
Response 200
Schema: QuestionnairePage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of PublishedQuestionnaire | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
Errors
Tasks
List tasks
get/api/v1/tasks
Tasks (action items) of the workspace's mentees, newest first, every status by default.
- Operation
- task.list
- Scope
- tasks:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| menteeProfileId | query | string | No | Only this mentee's tasks. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| status | query | string | No | Only this status. One of: SUGGESTED, ACTIVE, ARCHIVED, DISMISSED. |
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 100 (default 25). Range 1 to 100. Default 25. |
Response 200
Schema: TaskPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of Task | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
Errors
Create a task
post/api/v1/tasks
Creates an ACTIVE manual task for a mentee, as on the web.
- Operation
- task.create
- Scope
- tasks:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: TaskCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,128}$. |
| title | string | Yes | Length 1 to 1000. |
| details | string or null | No | At most 10,000 characters after trimming. |
| assigneeTarget | string | No | One of: MENTEE, MENTOR, UNASSIGNED. Default "UNASSIGNED". |
| deadline | string or null | No | YYYY-MM-DD or an ISO 8601 date-time with a time zone. Length 0 to 40. |
| meetingId | string or null | No | |
| isFocus | boolean | No | Default false. |
Response 201
Schema: TaskReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | TaskReceipt | Yes |
Errors
Get a task
get/api/v1/tasks/{taskId}
One task. assigneeEmail needs private access.
- Operation
- task.get
- Scope
- tasks:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| taskId | path | string | Yes | Task id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
Response 200
Schema: TaskResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | Task | Yes |
Errors
Update a task
patch/api/v1/tasks/{taskId}
Changes a task only if it is still at the revision named in If-Match (else 409 revision_conflict, nothing written).
- Operation
- task.update
- Scope
- tasks:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| taskId | path | string | Yes | Task id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
| If-Match | header | string | Yes | The task revision you last read, as a quoted entity tag, for example "3". Missing: 428 precondition_required; malformed: 422. Pattern ^"[1-9][0-9]{0,8}"$. |
Request body
Schema: TaskUpdateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| title | string | No | Length 1 to 1000. |
| details | string or null | No | |
| assigneeTarget | string | No | One of: MENTEE, MENTOR, UNASSIGNED. |
| deadline | string or null | No | YYYY-MM-DD or an ISO 8601 date-time with a time zone. Length 0 to 40. |
| isFocus | boolean | No | |
| isCompleted | boolean | No | |
| status | string | No | One of: SUGGESTED, ACTIVE, ARCHIVED, DISMISSED. |
Response 200
Schema: TaskReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | TaskReceipt | Yes |
Errors
Decisions
List decisions
get/api/v1/decisions
Active decisions of the workspace, newest first. Private fields need private access.
- Operation
- decision.list
- Scope
- decisions:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| menteeProfileId | query | string | No | Only this mentee's decisions. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 100 (default 25). Range 1 to 100. Default 25. |
Response 200
Schema: DecisionPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of Decision | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
Errors
Create a decision
post/api/v1/decisions
Records an agreed decision. The issuing account is the author; a mentee key may create decisions only for its own profile.
- Operation
- decision.create
- Scope
- decisions:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: DecisionCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,128}$. |
| title | string | Yes | Length 1 to 200. |
| body | string | Yes | Length 0 to 10000. |
| agreedOn | string (date) | Yes |
Response 201
Schema: DecisionReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | DecisionReceipt | Yes |
Errors
Get a decision
get/api/v1/decisions/{decisionId}
One decision. With private access: review state, sources and (for recordings not bound to another mentor) passages and provider links.
- Operation
- decision.get
- Scope
- decisions:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| decisionId | path | string | Yes | Decision id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
Response 200
Schema: DecisionResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | Decision | Yes |
Errors
Webhooks
List webhook endpoints
get/api/v1/webhooks
Endpoints created by this key's lineage (the key and its rotated successors).
- Operation
- webhook.list
- Scope
- webhooks:write
- Idempotency-Key
- Not used
Response 200
Schema: WebhookEndpointList
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of WebhookEndpoint | Yes |
Errors
Create a webhook endpoint
post/api/v1/webhooks
Subscribes a public https URL to event types. Each event type needs its read scope. The signing secret is returned once.
- Operation
- webhook.create
- Scope
- webhooks:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: WebhookEndpointCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| url | string | Yes | Public https URL; no credentials, fragment, private host or private IP. Length 0 to 2048. |
| eventTypes | array of WebhookEventType | Yes | Each type needs its read scope on the key. Items 1 to 7. |
| description | string or null | No | Length 0 to 200. |
Response 201
Schema: WebhookEndpointReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpointReceipt | Yes |
Errors
Get a webhook endpoint
get/api/v1/webhooks/{endpointId}
One endpoint of this key's lineage.
- Operation
- webhook.get
- Scope
- webhooks:write
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| endpointId | path | string | Yes | Webhook endpoint id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
Response 200
Schema: WebhookEndpointResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpoint | Yes |
Errors
Update a webhook endpoint
patch/api/v1/webhooks/{endpointId}
Changes url, eventTypes or description, or disables/re-enables the endpoint.
- Operation
- webhook.update
- Scope
- webhooks:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| endpointId | path | string | Yes | Webhook endpoint id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: WebhookEndpointUpdateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| url | string | No | Length 0 to 2048. |
| eventTypes | array of WebhookEventType | No | Items 1 to 7. |
| description | string or null | No | Length 0 to 200. |
| enabled | boolean | No | false disables (MANUAL); true re-enables MANUAL or FAILURES and clears the failure streak. |
Response 200
Schema: WebhookEndpointReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpointReceipt | Yes |
Errors
Delete a webhook endpoint
delete/api/v1/webhooks/{endpointId}
Deletes the endpoint, its secrets and its pending deliveries. Finished delivery logs are kept until retention removes them (30 days).
- Operation
- webhook.delete
- Scope
- webhooks:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| endpointId | path | string | Yes | Webhook endpoint id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Response 200
Schema: WebhookEndpointReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpointReceipt | Yes |
Errors
Rotate the signing secret
post/api/v1/webhooks/{endpointId}/rotate-secret
Issues a new secret (returned once). Older secrets stay valid for overlapHours; during the overlap every delivery is signed with each.
- Operation
- webhook.secret.rotate
- Scope
- webhooks:write
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| endpointId | path | string | Yes | Webhook endpoint id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body (optional)
Schema: WebhookRotateSecretRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| overlapHours | integer | No | Range 0 to 24. Default 24. |
Response 200
Schema: WebhookEndpointReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpointReceipt | Yes |
Errors
List deliveries
get/api/v1/webhooks/{endpointId}/deliveries
Delivery log, newest first: state, attempts, status code, latency and error class only (never payloads).
- Operation
- webhook.delivery.list
- Scope
- webhooks:write
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| endpointId | path | string | Yes | Webhook endpoint id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| state | query | string | No | Only this state. One of: PENDING, LEASED, SUCCEEDED, FAILED, CANCELLED, EXPIRED. |
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 100 (default 25). Range 1 to 100. Default 25. |
Response 200
Schema: WebhookDeliveryPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of WebhookDelivery | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
Errors
Replay a delivery
post/api/v1/webhooks/{endpointId}/deliveries/{deliveryId}/replay
Sends a logged delivery again with the same webhook-id. Free. A delivery that is already scheduled is not scheduled twice.
- Operation
- webhook.delivery.replay
- Scope
- webhooks:write
- Idempotency-Key
- Required
- Metering
- Free (not counted)
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| endpointId | path | string | Yes | Webhook endpoint id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| deliveryId | path | string | Yes | Delivery id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Response 202
Schema: WebhookReplayReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookReplayReceipt | Yes |
Errors
Workflows
List workflows
get/api/v1/workflows
Workflows this key can start runs of, most recently changed first: not archived, metered, and whose active version has a manual trigger. No mentee data is returned, so workflows:read alone is enough.
- Operation
- workflow.list
- Scope
- workflows:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| cursor | query | string | No | nextCursor from the previous page. Opaque; only valid with the same filters. Length 0 to 512. |
| limit | query | integer | No | Page size, 1 to 100 (default 25). Range 1 to 100. Default 25. |
Response 200
Schema: WorkflowPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of WorkflowSummary | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to this operation. |
Errors
Start a workflow run
post/api/v1/workflows/{workflowId}/runs
Starts the workflow's manual run for the chosen mentees, exactly as a mentor does in the app. The workflow must be on, metered and set to start manually; the run executes under the authority of the mentor who turned it on, so revoking this key later does not cancel a run it already started. Each run counts against the workspace's workflow run allowance. Admission is all or none.
- Operation
- workflow.run.start
- Scope
- workflows:run, mentees:read
- Idempotency-Key
- Required
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| workflowId | path | string | Yes | Workflow id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| Idempotency-Key | header | string | Yes | Unique per logical write. Retrying with the same key and body returns the original result; the same key with a different body is 409 idempotency_conflict. Keys are scoped to the API key lineage and kept for 30 days. Pattern ^[A-Za-z0-9_-]{16,128}$. |
Request body
Schema: WorkflowRunStartRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileIds | array of string | Yes | The mentees to start a run for. Between 1 and 100 DIFFERENT ids: a repeated id is refused with 422 validation_failed (INVALID_SELECTION), never de-duplicated. Order does not matter - the list is sorted before it is hashed, so [b, a] and [a, b] are the same request under one Idempotency-Key. Items 1 to 100. |
Response 200
Schema: WorkflowRunReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WorkflowRunReceipt | Yes |
Errors
Get a workflow run
get/api/v1/workflows/{workflowId}/runs/{runId}
One run of the workflow, whatever started it. A run of a workflow that reads questionnaire answers, or that is started by a questionnaire event, is returned in the redacted shape unless the key has private access.
- Operation
- workflow.run.get
- Scope
- workflows:read, mentees:read
- Idempotency-Key
- Not used
Parameters
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
| workflowId | path | string | Yes | Workflow id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
| runId | path | string | Yes | Run id. Pattern ^[A-Za-z0-9_-]{1,128}$. |
Response 200
Schema: WorkflowRunResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WorkflowRun | Yes |
Errors
Webhook events
Each event is a POST to your endpoint with the WebhookEvent body and these headers.
- decision.created
- decision.updated
- mentee.created
- questionnaire.assignment.created
- questionnaire.assignment.submitted
- task.created
- task.updated
- workflow.run.ended
| Header | Notes |
|---|---|
| webhook-id | Event id. Identical across retries and replays: deduplicate on it. |
| webhook-timestamp | Unix seconds when this attempt was signed. Reject if more than 5 minutes from your clock. |
| webhook-signature | Space-separated v1,<base64 HMAC-SHA256> values, one per active secret, over webhook-id.webhook-timestamp.body with the base64-decoded part of whsec_… |
Schemas
ErrorCode
Stable machine-readable error code. See x-error-catalog for the HTTP status of each code.
string One of: client_limit_reached, conflict, feature_unavailable, forbidden, idempotency_conflict, idempotency_key_required, insufficient_scope, internal_error, invalid_credentials, not_found, plan_required, precondition_required, quota_exhausted, rate_limited, retry_later, revision_conflict, validation_failed, workflow_not_admitted.
Error
| Field | Type | Required | Notes |
|---|---|---|---|
| error | object | Yes |
DecisionReview
| Field | Type | Required | Notes |
|---|---|---|---|
| status | string | Yes | One of: NOT_REVIEWED, REVIEWED. |
| reviewedContentRevision | integer or null | Yes | |
| reviewedAt | string (date-time) or null | Yes | |
| reviewerUserId | string or null | Yes |
DecisionPassage
| Field | Type | Required | Notes |
|---|---|---|---|
| segmentIndex | integer | Yes | |
| startOffset | integer | Yes | |
| endOffset | integer | Yes | |
| quote | string | Yes | |
| speaker | string or null | Yes | |
| startSeconds | number or null | Yes |
DecisionSource
| Field | Type | Required | Notes |
|---|---|---|---|
| role | string | Yes | One of: ORIGIN, CORROBORATION. |
| provider | string | Yes | |
| meetingTitle | string | Yes | |
| sourceDate | string or null | Yes | |
| sourceDateKind | string or null | Yes | |
| linkedAt | string (date-time) | Yes | |
| sourceUrl | string or null | No | Private.Private field: present only when the API key has private access, on the detail read only, and never for a recording bound to another mentor's connection. |
| passages | array of DecisionPassage | No | Private.Private field: present only when the API key has private access, on the detail read only, and never for a recording bound to another mentor's connection. |
Decision
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| menteeProfileId | string | Yes | |
| title | string | Yes | |
| body | string | Yes | |
| agreedOn | string (date) or null | Yes | |
| sourceKind | string | Yes | One of: MANUAL, AI_EXTRACTED. |
| revision | integer | Yes | Range 1 to any. |
| chronologyDate | string (date) | No | Private.Present when the date is the agreed date; a date derived from an imported source is private. |
| chronologyBasis | string | No | Private.Omitted together with chronologyDate. One of: AGREED_ON, SOURCE_DATE, IMPORTED_DATE. |
| addedAt | string (date-time) | Yes | |
| updatedAt | string (date-time) | Yes | |
| createdByUserId | string | Yes | |
| review | DecisionReview or any or null | No | Private.Private field: present only when the API key has private access. |
| sources | array of DecisionSource | No | Private.Private field: present only when the API key has private access. |
DecisionCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,128}$. |
| title | string | Yes | Length 1 to 200. |
| body | string | Yes | Length 0 to 10000. |
| agreedOn | string (date) | Yes |
DecisionReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| menteeProfileId | string | Yes | |
| revision | integer | Yes | |
| status | string | Yes | One of: ACTIVE. |
| operationId | string | Yes | |
| createdAt | string (date-time) | Yes |
DecisionPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of Decision | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
DecisionResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | Decision | Yes |
DecisionReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | DecisionReceipt | Yes |
MenteeSummary
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| externalId | string or null | Yes | |
| name | string | Yes | |
| string | Yes | ||
| status | string | Yes | One of: ACTIVE, PAUSED, ARCHIVED, LOCKED. |
| company | string or null | Yes | |
| website | string or null | Yes | |
| phone | string or null | Yes | |
| timeZone | string or null | Yes | |
| engagementStart | string (date-time) or null | Yes | |
| accountActive | boolean | Yes | |
| accountSetUp | boolean | Yes | |
| createdAt | string (date-time) | Yes |
MenteeDetail
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| externalId | string or null | Yes | |
| name | string | Yes | |
| string | Yes | ||
| status | string | Yes | One of: ACTIVE, PAUSED, ARCHIVED, LOCKED. |
| company | string or null | Yes | |
| website | string or null | Yes | |
| phone | string or null | Yes | |
| timeZone | string or null | Yes | |
| engagementStart | string (date-time) or null | Yes | |
| accountActive | boolean | Yes | |
| accountSetUp | boolean | Yes | |
| createdAt | string (date-time) | Yes | |
| tidycalBookingUrl | string or null | Yes | |
| nextCallDate | string (date-time) or null | Yes | |
| invitedAt | string (date-time) or null | Yes | |
| sharedGoal | object | Yes | |
| privateNotes | string or null | No | Private.Private field: present only when the API key has private access (mentor notes). |
QuestionnaireSelection
| Field | Type | Required | Notes |
|---|---|---|---|
| templateId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,128}$. |
| publishedVersionId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,128}$. |
| due | object or any or null | No | Default null. |
| expiresAt | string (date-time) or null | No | Default null. |
| message | string or null | No | Length 0 to 10000. Default null. |
MenteeCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | Yes | Length 1 to 200. |
| string (email) | Yes | ||
| company | string or null | No | Length 0 to 200. |
| website | string or null | No | Length 0 to 2000. |
| phone | string or null | No | Length 0 to 100. |
| tidycalBookingUrl | string or null | No | Length 0 to 2000. |
| timeZone | string | No | Default "UTC". |
| sendInvite | boolean | Yes | Required. true queues one invitation email to the mentee. |
| questionnaires | array of QuestionnaireSelection | Yes | Non-empty needs assignments:write as well. Items 0 to 20. |
| externalId | string | No | Your system's id (for example a CRM contact id). Unique per workspace. Pattern ^[A-Za-z0-9._:@|/-]{1,128}$. |
MenteeCreateReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileId | string | Yes | |
| externalId | string or null | Yes | |
| assignmentIds | array of string | Yes | |
| issuedAssignmentIds | array of string | Yes | |
| reusedAssignmentIds | array of string | Yes | |
| invitation | object or any or null | Yes | |
| operationId | string | Yes | |
| createdAt | string (date-time) | Yes |
MenteePage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of MenteeSummary | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
MenteeResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | MenteeDetail | Yes |
MenteeCreateReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | MenteeCreateReceipt | Yes |
TranscriptSegment
| Field | Type | Required | Notes |
|---|---|---|---|
| index | integer | Yes | |
| speaker | string or null | Yes | Length 0 to 256. |
| timestamp | string or null | Yes | Length 0 to 64. |
| startTime | number or null | Yes | |
| textOffset | integer | Yes | UTF-16 offset of text within the segment. |
| text | string | Yes | |
| continues | boolean | Yes | More text of this segment follows on the next page. |
TranscriptPage
| Field | Type | Required | Notes |
|---|---|---|---|
| segments | array of TranscriptSegment | Yes | |
| nextCursor | string or null | Yes | Pass as transcriptCursor. |
Meeting
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| menteeProfileId | string | Yes | |
| title | string | Yes | |
| date | string (date-time) | Yes | |
| duration | integer or null | Yes | |
| provider | string or null | Yes | |
| summaryOneLiner | string or null | No | Private.Private field: present only when the API key has private access, never for another mentor's recording. Also available to a mentee key for that mentee’s own meetings. |
| recordingUrl | string or null | No | Private.Private field: present only when the API key has private access, never for another mentor's recording. Also available to a mentee key for that mentee’s own meetings. |
MeetingDetail
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| menteeProfileId | string | Yes | |
| title | string | Yes | |
| date | string (date-time) | Yes | |
| duration | integer or null | Yes | |
| provider | string or null | Yes | |
| summaryOneLiner | string or null | No | Private.Private field: present only when the API key has private access, never for another mentor's recording. Also available to a mentee key for that mentee’s own meetings. |
| recordingUrl | string or null | No | Private.Private field: present only when the API key has private access, never for another mentor's recording. Also available to a mentee key for that mentee’s own meetings. |
| summary | string or null | No | Private.Private field: present only when the API key has private access. First page only (no transcriptCursor); at most 16,000 UTF-8 bytes. Also available to a mentee key for that mentee’s own meetings. |
| summaryTruncated | boolean | No | Private.Private field: present only when the API key has private access. First page only. Also available to a mentee key for that mentee’s own meetings. |
| transcript | TranscriptPage or any or null | No | Private.Private field: present only when the API key has private access. One bounded page (segments at most 64,000 UTF-8 bytes including the summary). Also available to a mentee key for that mentee’s own meetings. |
MeetingPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of Meeting | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
MeetingResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | MeetingDetail | Yes |
PublishedQuestionnaire
| Field | Type | Required | Notes |
|---|---|---|---|
| templateId | string | Yes | |
| publishedVersionId | string | Yes | |
| title | string | Yes | |
| version | integer | Yes | |
| publishedAt | string (date-time) | Yes | |
| onboardingDefault | boolean | Yes |
QuestionnairePage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of PublishedQuestionnaire | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
AssignmentRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| questionnaires | array of QuestionnaireSelection | Yes | Items 1 to 20. |
AssignmentReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileId | string | Yes | |
| assignmentIds | array of string | Yes | |
| issuedAssignmentIds | array of string | Yes | |
| reusedAssignmentIds | array of string | Yes | Already open ordinary assignments; nothing duplicated. |
| operationId | string | Yes | |
| createdAt | string (date-time) | Yes |
AssignmentReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | AssignmentReceipt | Yes |
Task
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| menteeProfileId | string | Yes | |
| title | string | Yes | |
| details | string or null | Yes | |
| assignee | string or null | Yes | |
| status | string | Yes | One of: SUGGESTED, ACTIVE, ARCHIVED, DISMISSED. |
| isCompleted | boolean | Yes | |
| completedAt | string (date-time) or null | Yes | |
| deadline | string (date-time) or null | Yes | |
| isFocus | boolean | Yes | |
| source | string | Yes | |
| meeting | object or any or null | Yes | |
| archivedAt | string (date-time) or null | Yes | |
| revision | integer | Yes | Range 1 to any. |
| createdAt | string (date-time) | Yes | |
| updatedAt | string (date-time) | Yes | |
| assigneeEmail | string or null | No | Private.Private field: present only when the API key has private access; withheld for a task imported from another mentor's recording. |
TaskCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileId | string | Yes | Pattern ^[A-Za-z0-9_-]{1,128}$. |
| title | string | Yes | Length 1 to 1000. |
| details | string or null | No | At most 10,000 characters after trimming. |
| assigneeTarget | string | No | One of: MENTEE, MENTOR, UNASSIGNED. Default "UNASSIGNED". |
| deadline | string or null | No | YYYY-MM-DD or an ISO 8601 date-time with a time zone. Length 0 to 40. |
| meetingId | string or null | No | |
| isFocus | boolean | No | Default false. |
TaskUpdateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| title | string | No | Length 1 to 1000. |
| details | string or null | No | |
| assigneeTarget | string | No | One of: MENTEE, MENTOR, UNASSIGNED. |
| deadline | string or null | No | YYYY-MM-DD or an ISO 8601 date-time with a time zone. Length 0 to 40. |
| isFocus | boolean | No | |
| isCompleted | boolean | No | |
| status | string | No | One of: SUGGESTED, ACTIVE, ARCHIVED, DISMISSED. |
TaskReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| menteeProfileId | string | Yes | |
| revision | integer | Yes | |
| status | string | Yes | One of: SUGGESTED, ACTIVE, ARCHIVED, DISMISSED. |
| operationId | string | Yes | |
| completedAt | string (date-time) or null | Yes |
TaskPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of Task | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
TaskResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | Task | Yes |
TaskReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | TaskReceipt | Yes |
WebhookEventType
string One of: decision.created, decision.updated, mentee.created, questionnaire.assignment.created, questionnaire.assignment.submitted, task.created, task.updated, workflow.run.ended.
WebhookEndpoint
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| url | string (uri) | Yes | |
| description | string or null | Yes | |
| eventTypes | array of WebhookEventType | Yes | |
| status | string | Yes | One of: ACTIVE, DISABLED. |
| disabledReason | string or null | Yes | One of: MANUAL, CREDENTIAL_REVOKED, CREDENTIAL_EXPIRED, FAILURES, null. |
| disabledAt | string (date-time) or null | Yes | |
| consecutiveFailures | integer | Yes | |
| revision | integer | Yes | |
| createdAt | string (date-time) | Yes | |
| updatedAt | string (date-time) | Yes | |
| secrets | array of object | Yes | Unexpired signing secrets (metadata only; never the secret). |
WebhookEndpointCreateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| url | string | Yes | Public https URL; no credentials, fragment, private host or private IP. Length 0 to 2048. |
| eventTypes | array of WebhookEventType | Yes | Each type needs its read scope on the key. Items 1 to 7. |
| description | string or null | No | Length 0 to 200. |
WebhookEndpointUpdateRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| url | string | No | Length 0 to 2048. |
| eventTypes | array of WebhookEventType | No | Items 1 to 7. |
| description | string or null | No | Length 0 to 200. |
| enabled | boolean | No | false disables (MANUAL); true re-enables MANUAL or FAILURES and clears the failure streak. |
WebhookRotateSecretRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| overlapHours | integer | No | Range 0 to 24. Default 24. |
WebhookEndpointReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| status | string | Yes | One of: ACTIVE, UPDATED, ROTATED, DELETED. |
| revision | integer | Yes | |
| operationId | string | Yes | |
| secret | string or null | No | create and rotate-secret only: the whsec_ signing secret, shown once; null on an idempotent replay. |
WebhookDelivery
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | |
| webhookId | string | Yes | The webhook-id header value (the event id); stable across retries and replays. |
| eventType | WebhookEventType | Yes | |
| state | string | Yes | One of: PENDING, LEASED, SUCCEEDED, FAILED, CANCELLED, EXPIRED. |
| attempts | integer | Yes | |
| replayCount | integer | Yes | |
| lastStatusCode | integer or null | Yes | |
| lastErrorClass | string or null | Yes | |
| lastLatencyMs | integer or null | Yes | |
| deliveredAt | string (date-time) or null | Yes | |
| nextAttemptAt | string (date-time) or null | Yes | |
| createdAt | string (date-time) | Yes | |
| log | array of object | Yes | Items 0 to 20. |
WebhookReplayReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| deliveryId | string | Yes | |
| webhookId | string | Yes | |
| state | string | Yes | One of: PENDING, LEASED, SUCCEEDED, FAILED, CANCELLED, EXPIRED. |
| replayCount | integer | Yes | |
| operationId | string | Yes |
WebhookEndpointList
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of WebhookEndpoint | Yes |
WebhookEndpointResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpoint | Yes |
WebhookEndpointReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookEndpointReceipt | Yes |
WebhookDeliveryPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of WebhookDelivery | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to the filters it was issued with. |
WebhookReplayReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WebhookReplayReceipt | Yes |
WebhookEvent
Webhook request body (POSTed to your endpoint). Not an API response.
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | Equals the webhook-id header. |
| type | WebhookEventType | Yes | |
| timestamp | string (date-time) | Yes | |
| workspaceId | string | Yes | |
| routine | boolean | Yes | false when the event comes from checking a client's past calls (historical extraction), true for live work. Non-routine events never trigger workflows. |
| data | object | Yes | |
| origin | object | Yes |
WorkflowRunStartRequest
Unknown fields are refused with 422 validation_failed.
| Field | Type | Required | Notes |
|---|---|---|---|
| menteeProfileIds | array of string | Yes | The mentees to start a run for. Between 1 and 100 DIFFERENT ids: a repeated id is refused with 422 validation_failed (INVALID_SELECTION), never de-duplicated. Order does not matter - the list is sorted before it is hashed, so [b, a] and [a, b] are the same request under one Idempotency-Key. Items 1 to 100. |
WorkflowRunReceipt
| Field | Type | Required | Notes |
|---|---|---|---|
| invocationId | string | Yes | The recorded trigger instance for this request. |
| workflowId | string | Yes | The workflow that was started. |
| outcome | string | Yes | Admission is all or none. A request that admitted nobody is 409 workflow_not_admitted, not a receipt. One of: ADMITTED. |
| admittedCount | integer | Yes | Number of runs created (equal to the number of ids sent). |
| runs | array of object | Yes |
WorkflowRunReceiptResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WorkflowRunReceipt | Yes |
WorkflowRunState
Run state. Treat an unlisted value as a new state rather than an error.
string One of: ADMITTED, ACTIVE, PAUSED_REAUTHORIZE, SUCCEEDED, SKIPPED, FAILED, CANCELLED, NOT_STARTED.
WorkflowRunRedactedState
Redacted run state. ADMITTED, ACTIVE and PAUSED_REAUTHORIZE all read IN_PROGRESS; every ended run reads ENDED.
string One of: IN_PROGRESS, ENDED.
WorkflowRunStep
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | Step execution id. |
| position | integer | Yes | Position in the workflow (the start step is -1). |
| kind | string | Yes | One of: start, condition, delay, action. |
| actionType | string or null | Yes | Action steps only. Never the action's settings, message text or referenced record. |
| state | string | Yes | Step state. |
| outcomeCode | string or null | Yes | Stable outcome code. Never a condition operand, fact name or value. |
| wakeAt | string (date-time) or null | Yes | |
| completedAt | string (date-time) or null | Yes | |
| retryCount | integer | Yes | |
| suspended | boolean | Yes |
WorkflowRunFull
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | Run id. |
| workflowId | string | Yes | The workflow this run belongs to. |
| invocationId | string | Yes | The trigger instance that admitted this run. |
| menteeProfileId | string | Yes | The mentee this run is for. |
| state | WorkflowRunState | Yes | |
| outcomeCode | string or null | Yes | Stable outcome code for an ended run. |
| versionNumber | integer or null | Yes | The workflow version this run is pinned to. |
| startedVia | string or null | Yes | How this run was started. Null only if the originating trigger instance no longer exists. One of: WEB, BACKGROUND, EXTERNAL, null. |
| createdAt | string (date-time) | Yes | |
| startedAt | string (date-time) or null | Yes | |
| endedAt | string (date-time) or null | Yes | |
| revision | integer | Yes | |
| steps | array of WorkflowRunStep | Yes |
WorkflowRunRedacted
Returned for a run whose workflow reads questionnaire answers, to a key without private access.
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | Run id. |
| workflowId | string | Yes | The workflow this run belongs to. |
| invocationId | string | Yes | The trigger instance that admitted this run. |
| menteeProfileId | string | Yes | The mentee this run is for. |
| state | WorkflowRunRedactedState | Yes | |
| startedVia | string or null | Yes | How this run was started. Null only if the originating trigger instance no longer exists. One of: WEB, BACKGROUND, EXTERNAL, null. |
| createdAt | string (date-time) | Yes |
WorkflowRun
Full or redacted, decided per request. A run is redacted when the workflow version it is pinned to either uses a questionnaire condition (questionnaire status, submitted, score or a readable answer) or is started by a questionnaire event, AND the key does not have private access. Tell them apart by the state value: a redacted run reports only IN_PROGRESS or ENDED.
WorkflowRunResponse
| Field | Type | Required | Notes |
|---|---|---|---|
| data | WorkflowRun | Yes |
WorkflowSummary
A workflow this API key can start runs of: not archived, metered, and with a manual-trigger active version.
| Field | Type | Required | Notes |
|---|---|---|---|
| id | string | Yes | Workflow id. |
| name | string | Yes | The workflow name as the mentor wrote it. |
| state | string | Yes | ACTIVE accepts run requests; PAUSED is listed but refuses them with 409 workflow_not_admitted. One of: ACTIVE, PAUSED. |
| manualRunAvailable | boolean | Yes | True when POST /api/v1/workflows/{workflowId}/runs can admit a run right now. |
| fanOutCap | integer | Yes | Maximum number of mentees one run request may select on this plan. |
| updatedAt | string (date-time) | Yes | When the workflow was last changed. |
WorkflowPage
| Field | Type | Required | Notes |
|---|---|---|---|
| data | array of WorkflowSummary | Yes | |
| nextCursor | string or null | Yes | Opaque cursor for the next page, or null on the last page. Bound to this operation. |
WorkflowRunEvent
| Field | Type | Required | Notes |
|---|---|---|---|
| workflowId | string | Yes | |
| invocationId | string | Yes | |
| state | string | Yes | |
| outcomeCode | string or null | Yes | |
| startedVia | string or null | Yes | One of: WEB, BACKGROUND, EXTERNAL, null. |
| createdAt | string (date-time) | Yes | |
| startedAt | string (date-time) or null | Yes | |
| endedAt | string (date-time) or null | Yes |