Skip to main content

Requests, responses and errors

Base URL​

All endpoints live under

https://api.deepersignals.com/api/external

Paths in this documentation are shown relative to that base, so GET /users/{user_id} means GET https://api.deepersignals.com/api/external/users/{user_id}.

JSON​

  • Send request bodies as application/json with Content-Type: application/json, except the CSV upload endpoint which takes multipart/form-data.
  • Responses are JSON, except PDF downloads which stream application/pdf.
  • Identifiers (id, user, team, campaign, library ids) are integers.
  • Booleans are real JSON booleans. Omitted optional fields are left unchanged on update endpoints (PATCH/PUT) and take their default on create.
  • Timestamps are returned as YYYY-MM-DD HH:MM:SS in UTC on the older user and team endpoints, and as ISO 8601 with offset (2026-10-01T09:12:00+00:00) on the campaign, assessment and report endpoints added in 2026.

Status codes​

CodeMeaning
200Success.
201Created, or a state switched on (for example a report made visible).
202Accepted; work continues in the background (for example invitation e-mails are being sent).
204Success with no body (deletes).
400The request is not valid for this account: duplicate e-mail (exception.email.taken) or employee id (exception.user.employeeIdTaken, data.field: employee_id), invalid table query.
401Missing or wrong API token.
403The resource belongs to another account, or a feature is not enabled on yours.
404Unknown resource.
409The action conflicts with the current state (for example a PDF of a report whose assessments are not completed).
422Validation failed; message names the first failing rule.
429Rate limit exceeded, see Rate limits.
5xxSomething went wrong on our side. Retry with backoff and contact support if it persists.

Error envelope​

Errors are JSON objects with a code (same as the HTTP status) and a human-readable message:

{ "code": 403, "message": "Not allowed, insufficient permissions." }

Some errors carry more detail:

  • trans_code — a stable machine-readable key (for example exception.report.notReady). Match on this, not on message.
  • data — context for the error, such as pending_assessment_library_ids for a report that is not ready.
  • details — for invalid table queries, the constraints that were violated.

Validation errors (422) report the first rule that failed in message:

{ "code": 422, "message": "assigned_user_report is required." }

Pagination​

List endpoints are table queries: a POST with a JSON body naming columns, filters, sort, pagination (limit up to 500, page from 1) and an optional search term q. They answer with items, total and pages:

{ "items": [ ... ], "total": 243, "pages": 3 }

This applies to users (/users/table), teams (/team/table, /team/{team_id}/members/table), campaigns (/campaigns/table) and campaign participants (/campaigns/{campaign_id}/users/table). Every page carries total and pages; team members also have a /count variant, and each table has a columns endpoint that lists what can be selected. See Table queries.

Catalog endpoints (/assessment_libraries, /reports, /playbook) and per-user lists (/users/{user_id}/assessments, /users/{user_id}/reports) return plain JSON arrays without pagination.

Locales​

Reports and share links can be rendered in the user's language. Pass the locale as the {locale} path segment; en is the default. The same codes are accepted as locale when creating or updating a user.

GET /locales returns the locales currently enabled on the platform (code, name, right_to_left); use it rather than hard-coding the list. At the time of writing:

LocaleLanguage
enEnglish
deGerman
frFrench
itItalian
es-ESSpanish (Spain)
es-419Spanish (Latin America)
pt-BRPortuguese (Brazil)
bgBulgarian

Not every report exists in every language. A locale the report does not support falls back to English.

Idempotency and retries​

GET and DELETE are safe to retry. PUT on a participant's assessment or report is idempotent (200 when nothing changed, 201 when it switched on). POST endpoints that create users, teams, campaigns or send invitations are not idempotent; retry them only after checking the state with the matching GET.