API documentation
Errors
One shape { code, message, details } and stable codes, to test in your code rather than the messages.
Shape of an error
Every error returns the same object: a stable code, a message translated for a human, and details specific to the code (the invalid fields for a validation error).
{
"code": "validation.failed",
"message": "Some fields are invalid.",
"details": {
"errors": {
"name": [
"The name field is required."
]
}
}
}
HTTP statuses
| Status | Meaning |
|---|---|
401 | Missing, unknown, revoked or expired token, or an account that is no longer a member of the workspace (the WWW-Authenticate header restarts OAuth discovery). |
403 | The role, a workspace rule or the token scope does not allow the operation. |
404 | Unknown resource, or one from another workspace. |
409 | The resource is not in a state that allows the operation (engagement already launched, published version…). |
422 | Invalid data: details.errors lists the fields and their messages. |
429 | Rate limit reached: retry after Retry-After. |
500 | Unexpected platform error: retry later. |
Error codes
The complete list, by module, with the English message. The parameters of a message (prefixed with a colon) are replaced with their value in the response.
Generic
| Code | Message |
|---|---|
auth.unauthenticated | You must be signed in. |
auth.forbidden | You are not allowed to do this. |
auth.two_factor_required | A two-factor code is required. |
auth.csrf_mismatch | The page has expired. Please reload and try again. |
resource.not_found | The resource does not exist. |
resource.conflict | The resource is in a conflicting state. |
validation.failed | Some fields are invalid. |
rate.limited | Too many requests. Please try again later. |
http.error | The request could not be processed. |
internal.error | An unexpected error occurred. |
AI
| Code | Message |
|---|---|
ai.provider_error | The AI provider returned an error. Try again in a moment. |
ai.provider_quota | The AI provider quota or credit is exhausted. |
ai.budget_cap_reached | The budget cap for this session or engagement has been reached. |
ai.platform_credential_missing | No usable API key for this AI usage: add a key in AI connections or choose another profile. |
ai.schema_violation | The AI answer did not follow the expected format. |
ai.driver_unsupported_for_usage | This provider cannot be used for this usage. |
ai.model_unsupported_for_usage | This model cannot be used for this usage. |
ai.credential_invalid | The provider rejected this key. |
ai.credential_in_use | This key is used by :count AI profile(s): change them first. |
ai.credential_driver_mismatch | This key belongs to another provider. |
ai.base_url_required | This provider needs a base URL. |
ai.base_url_not_allowed | This base URL is not allowed: use https and a public address (only an OpenAI-compatible key or profile can carry one). |
ai.base_url_mismatch | A key is only sent to the address it was saved for: this base URL does not match the key. |
ai.prompt_not_found | An AI prompt is missing from this installation. |
ai.voice_lab_engagement_not_ready | The voice lab plays the interview of an engagement that has at least one population. Create an engagement (or add a population to this one), then start the trial again. |
ai.profile_scope_invalid | This method or engagement does not exist in the workspace. |
ai.catalog_model_exists | This provider already lists a model with this identifier. |
ai.catalog_provider_exists | A provider with this identifier already exists. |
ai.catalog_usage_not_supported_by_driver | This provider's driver cannot serve the usage “:usage”. |
ai.catalog_realtime_requires_voice | A realtime model only serves the voice usage. |
ai.catalog_dimensions_required | An embedding model needs its native dimension. |
ai.catalog_native_provider_locked | A native provider has no base URL: add an OpenAI-compatible provider instead. |
ai.catalog_compatible_requires_base_url | An OpenAI-compatible provider needs a base URL. |
ai.catalog_default_cannot_be_hidden | This model is the default for “:usage”: choose another default first. |
ai.catalog_provider_holds_default | This provider holds the default model of: :usages. Choose other defaults first. |
ai.catalog_default_model_unavailable | This model cannot be the default for “:usage”: it must be visible and serve this usage. |
ai.catalog_default_architecture_mismatch | Direct voice needs a realtime model; cascade needs a text model. |
Analysis
| Code | Message |
|---|---|
analysis.run_in_progress | An analysis is already queued or running for this engagement. |
analysis.run_not_cancellable | This analysis run is already finished. |
analysis.evidence_required | A finding needs at least one piece of evidence. |
analysis.last_evidence | This is the last evidence of a validated finding: it cannot be removed. |
analysis.evidence_source_not_found | The cited source does not exist in this engagement. |
analysis.follow_up_not_editable | A follow-up can only be edited while it is proposed. |
analysis.follow_up_targets_required | A follow-up targets at least one participant of the engagement. |
analysis.change_proposal_decided | This change proposal has already been decided. |
analysis.contradiction_resolved | This contradiction has already been settled. |
analysis.merge_same_process | A process cannot be merged into itself. |
analysis.steps_not_in_process | Some steps do not belong to this process. |
analysis.category_unknown | This category is not in the deliverable schema of the method. |
analysis.not_found | This object does not belong to the engagement. |
analysis.flow_steps_mismatch | A flow links two steps of the same process. |
Audit chat
| Code | Message |
|---|---|
chat.version_required | The deliverable is not published yet: the chat opens with the first version. |
chat.answer_in_progress | An answer is being written: wait for it before asking another question. |
chat.policy.not_owner | This conversation is not yours. |
Deliverable
| Code | Message |
|---|---|
deliverable.documents_not_ready | An included document is not ready: generate it or remove it from the publication. |
deliverable.nothing_to_publish | Nothing to publish yet: validate at least one process or one finding with a publishable evidence. |
deliverable.publish_in_progress | A publication is already in progress for this engagement. |
deliverable.suggestion_in_progress | A suggestion is already being written for this draft. |
deliverable.version_not_published | This version has no published content. |
deliverable.naming_not_allowed | Some participants cannot be named: the engagement must allow it and each participant must have accepted it. |
deliverable.policy.not_allowed | You cannot access this deliverable. |
deliverable.policy.not_member | You are not assigned to this engagement. |
deliverable.policy.not_draft | Only the draft can be changed. |
deliverable.policy.not_sponsor | You are not a sponsor of this engagement. |
export.document_kind_required | Say which document to export. |
export.format_unsupported | This format does not exist for this document. |
export.kind_not_allowed | This format is not available in the client space: choose a document or the full report. |
export.not_ready | This export is not available for download. |
export.process_required | A BPMN export targets one process: choose it. |
export.version_required | This export reads a published version: publish the deliverable first. |
sponsor_comment.closed | This comment is closed. |
sponsor_comment.not_root | Reply to the comment itself, not to a reply. |
deliverable_document.generation_in_progress | A generation is already in progress for this document. |
deliverable_document.conflict | This document changed in the meantime: reload it before saving. |
deliverable_document.not_enough_material | Not enough material yet: at least one validated chapter and :min findings with evidence are needed. |
deliverable_document.ref_unknown | A block cites an item that does not exist in the engagement. |
deliverable_document.person_named | An owner role cannot name a participant: give a role. |
deliverable_document.data_ref_invalid | This block points to data that does not belong to this document. |
deliverable_document.all_blocks_rejected | No generated text passed the evidence checks: run the generation again or write the text yourself. |
deliverable_document.job_failed | The generation failed. |
Engagements
| Code | Message |
|---|---|
engagement.not_launchable | This engagement cannot be launched yet: fix the blocking points of the launch checklist. |
engagement.not_draft | This is only possible while the engagement is a draft. |
engagement.locale_unavailable | This language is not enabled for the workspace, or the default language is not among the engagement languages. |
engagement.method_version_not_published | This method version is not published. |
engagement.method_not_published | This method has no published version yet. Publish it before starting an engagement. |
engagement.archived | This engagement is archived: reopen it to change its configuration. |
engagement.member_invalid | This person is not a member of the workspace. |
engagement.policy.not_member | You are not assigned to this engagement. |
engagement.policy.not_admin | Only an administrator can do this. |
engagement.policy.not_sponsor | You are not a sponsor of this engagement. |
state.invalid_transition | This change of status is not possible from the current status. |
client_company.in_use | An engagement audits this company: it cannot be deleted. |
population.not_empty | This population still has participants. Move or remove them first. |
participant.email_taken | A participant of this engagement already uses this email address. |
participant.interview_started | The interview has started: the participant cannot be deleted. Use a deletion request instead. |
participant.revoked | This participant’s access is revoked. |
participant.link_invalid | This link is not valid. |
participant.link_expired | This link has expired. |
participant.link_revoked | This link has been revoked. |
participant.email_code_required | Enter the code sent to you by email to continue. |
participant.email_code_invalid | This code is not valid. Check the last email you received. |
participant.email_code_locked | Too many attempts. Ask for a new code. |
participant.import_invalid | The file could not be read as CSV with the expected columns. |
plan.topic_unknown | The plan refers to topics that are not in the guide. |
plan.proposal_not_found | This plan proposal does not exist or has expired. |
message_template.variable_unknown | The message uses an unknown variable. |
message_template.link_missing | This message must contain the {link} variable, or the participant cannot open the interview. |
sponsor.is_member | This person is a member of the firm and already sees the engagement. |
Integrations
| Code | Message |
|---|---|
integrations.token_invalid | This API token is invalid, revoked or expired, or its account is no longer a member of this workspace. |
integrations.scope_insufficient | This token is read-only: it cannot modify anything. |
integrations.session_required | This operation is only available from the web app, not with an API token. |
integrations.token_limit_reached | You already have :max active tokens in this workspace: revoke one first. |
integrations.oauth_not_member | Only a member of this workspace can authorize an application. |
integrations.oauth_two_factor_required | Turn on two-step verification on your account before authorizing an application. |
integrations.operator_token_invalid | This token is invalid, revoked or expired, was issued for a workspace, or its account is no longer a platform operator. |
integrations.operator_token_limit_reached | You already have :max active back-office tokens: revoke one first. |
integrations.oauth_not_operator | Only a platform operator can authorize an application on the back-office. |
Interviews
| Code | Message |
|---|---|
interview.guide_not_frozen | The interview has not started yet: the participant has not accepted the welcome screen. |
interview.consent_already_given | Consent was already recorded for this interview. |
interview.not_ready | The interview cannot start a session before consent is given. |
interview.completed | This interview is complete: no new session can start. |
interview.voice_sample_unavailable | The interviewer's voice cannot be played right now. |
interview.preview_requires_engagement | An interview preview is played inside an engagement: choose one. |
session.invalid_transition | This session cannot change to that state. |
session.not_live | This action needs a live session. |
session.mode_unavailable | This session mode is not available here. |
session.limit_reached | The engagement budget is reached: no new session can start. |
tool.unknown | This interviewer tool does not exist. |
tool.arguments_invalid | The tool arguments do not match the expected schema. |
vision.rate_limited | Too many screen images per minute. |
chapter.not_in_progress | This chapter is not in progress. |
chapter.not_covered | This chapter has not been covered yet: nothing to validate. |
chapter.reopen_not_allowed | This chapter cannot be reopened. |
recap.already_validated | This recap is validated and can no longer be edited. |
recap.not_found | There is no recap for this chapter yet. |
redaction.invalid_range | The time range to remove is invalid. |
recording.not_ready | This recording is not ready to be played. |
simulation.persona_not_found | This simulation persona does not exist. |
simulation.failed | The simulation stopped on a model error. |
Methods
| Code | Message |
|---|---|
method.consultant_cannot_edit | Only an administrator can change a method. |
method.version_published | This version is published and can no longer change. Create a new draft to edit it. |
method.welcome_block_missing | The welcome screen is missing a mandatory block. |
method.welcome_variable_unknown | The welcome screen uses an unknown variable. |
method.draft_exists | A draft version already exists for this method. |
method.in_use | An engagement uses this method: it cannot be deleted. |
method.template_not_found | This method template does not exist. |
method.priority_rule_invalid | A priority rule is not written correctly. |
guide.category_unknown | This deliverable category does not exist in the method. |
guide.level_unavailable | This guide level is not available yet. |
guide.override_not_allowed | Only an inherited topic can be overridden, from an engagement, a population or a participant. |
guide.topic_key_taken | Another topic already uses this key. |
guide.topic_limit_reached | This level has reached the maximum number of topics. |
guide.reorder_mismatch | The new order must list exactly the topics of this level. |
guide.proposal_not_found | This proposal does not exist or has expired. |
method_template.key_taken | Another method template already uses the key “:key”. |
method_template.key_locked | This template has been published: its key can no longer change, firms’ methods refer to it. |
method_template.version_frozen | This template version is published and can no longer change. Open a new draft to edit it. |
method_template.draft_exists | This template already has a draft version. |
method_template.not_publishable | This version cannot be published yet: fix the points listed. |
method_template.locale_exists | This language already exists in this version. |
method_template.locale_missing | This version has no content in this language. |
method_template.last_locale | A template keeps at least one language. |
Platform
| Code | Message |
|---|---|
platform.already_operator | This account is already a platform operator. |
platform.last_owner | The platform must keep at least one owner. |
platform.grant_too_long | A support access lasts at most :hours hours. |
Privacy
| Code | Message |
|---|---|
privacy.invalid_custom_pattern | The custom pattern ":label" is invalid: it must be a valid expression of at most 200 characters, with a label, that never matches empty text. |
privacy.image_unreadable | The image could not be read. Nothing was stored. |
privacy.video_processing_failed | Blurring the recording failed. The recording stays unavailable until it is processed again. |
privacy.engagement_not_found | This engagement does not exist in this workspace. |
privacy.engagement_forbidden | You are not assigned to this engagement. |
privacy.deletion_request_not_open | This request has already been handled or is being handled. |
privacy.deletion_request_exists | A request is already open for this participant. |
privacy.participant_not_found | This participant does not exist in this engagement. |
privacy.compliance_document_missing | The file of this document no longer exists: generate it again. |
privacy.support_operator_not_found | This operator does not exist or is no longer an operator. |
Sources
| Code | Message |
|---|---|
artifact.unsupported_type | This file type is not accepted. |
artifact.not_ready | This document has not been extracted yet. |
source.schema_invalid | The file does not follow the external source exchange format. |
source.version_unsupported | This exchange format version is not supported. |
source.file_unreadable | The file is neither a JSON export nor a readable text. |
Workspace and account
| Code | Message |
|---|---|
workspace.context_missing | No workspace context for this operation. |
workspace.not_found | This workspace does not exist. |
workspace.suspended | This workspace is suspended. |
workspace.last_admin | A workspace must keep at least one administrator. |
workspace.invitation_invalid | This invitation is invalid or has expired. |
workspace.invitation_email_mismatch | This invitation was sent to another email address. |
workspace.already_member | This person is already a member of the workspace. |
workspace.slug_reserved | The subdomain ":slug" is not allowed. |
workspace.slug_taken | The subdomain ":slug" is already used. |
workspace.locale_not_enabled | The language ":locale" is not available. |
auth.magic_link_invalid | This sign-in link is invalid or has expired. |
auth.two_factor_setup_required | Two-factor authentication must be enabled on your account. |