Error codes
A refused request usually answers with a JSON body carrying a human-readable error and a machine-readable code:
{ "error": "This access token is not scoped to this dataroom", "code": "PAT_DATAROOM_SCOPE" }Branch on code when it is present, not on error, because the message is written for people and may be reworded. Some refusals carry no code at all, such as certain 404 responses, so fall back to the HTTP status. Some errors add fields, such as fieldErrors on a validation failure. The HTTP status column lists the statuses the code is known to arrive with. Varies means the status is set by the endpoint.
The list below is generated from the platform's route tree. It is the known minimum, not an exhaustive list: it includes the codes the authentication layer and the scanned gate helpers produce and the codes written directly in handlers. Codes returned by other helpers a handler calls do not appear here. Each endpoint on the endpoints page lists its own known codes. Handle an unlisted code by its HTTP status.
| Code | HTTP status | Meaning |
|---|---|---|
ADDON_NOT_PURCHASED | Varies | The endpoint needs an add-on the organisation has not purchased, such as portfolio monitoring. |
AI_BUDGET_UNAVAILABLE | 503 | AI spend accounting is temporarily unavailable, so the request was refused rather than run unmetered. Retry shortly. |
AI_DAILY_BUDGET_EXCEEDED | 429 | The organisation's daily AI spend cap has been reached. Retry after the daily budget resets. |
ai_disabled | 403 | AI features are turned off for this organisation. |
BAD_REQUEST | 400 | The request was malformed. The usual causes are an unknown query parameter on an endpoint that rejects them, or an invalid value. |
CHECK_VIOLATION | Varies | The submitted row breaks a data invariant, such as an amount outside its allowed range. fieldErrors names the field. |
COMMIT_FAILED | Varies | The import could not be committed in its current state. Check its status before retrying. |
CONFLICT | Varies | The request conflicts with the resource's current state. A typical cause is creating something that already exists. |
FILE_NOT_FOUND | Varies | No such file, or none the caller can see. |
FORBIDDEN | 403 | The caller is authenticated but lacks the role, or the data room access, that this endpoint requires. See Required role on the endpoint. |
GRANTEE_NOT_FOUND | Varies | The user or group the grant names does not exist in this organisation. |
GRANTEE_NOT_IN_DATAROOM | Varies | The grantee has no access to this data room, so a file-level grant inside it would have no effect. |
ID_CONFLICT | Varies | A record with this caller-supplied id already exists. Ids are chosen by the caller and must be unique. |
IDEMPOTENCY_CONFLICT | Varies | This idempotency key was already used with a different request. Reuse a key only to retry the identical request. |
IDEMPOTENCY_KEY_REUSED | Varies | This idempotency key already started an import. The response's importId identifies it, so poll that import instead of starting another. |
INVALID_BODY | Varies | The request body is missing, is not valid JSON, or does not match the expected shape. |
INVALID_STATUS_TRANSITION | Varies | The requested status change is not allowed from the record's current status. |
IP_BLOCKED | 403 | The organisation has an IP allowlist, and the request came from an address outside it. |
MFA_CHALLENGE_REQUIRED | 403 | The organisation enforces two-factor authentication and this session has not completed a challenge. |
MFA_SETUP_REQUIRED | 403 | The organisation enforces two-factor authentication and the user has not enrolled. |
NOT_FOUND | Varies | No such resource, or none the caller can see. |
ORG_NOT_FOUND | Varies | The caller's organisation could not be found. |
ORGANIZATION_REQUIRED | Varies | The credential is not attached to an organisation, so an organisation-scoped read has nothing to answer about. |
PAID_PLAN_REQUIRED | 402 | The organisation's plan does not include this capability. |
PAT_DATAROOM_SCOPE | 403 | The token is restricted to specific data rooms. Either this data room is not one of them, or the endpoint is organisation-wide and cannot be called with a data-room-restricted token. |
PAT_ROLE_CEILING | 403 | The token carries a role ceiling below the role this endpoint requires. The effective role is the lower of the user's live role and the token's ceiling. |
PAT_SCOPE_INSUFFICIENT | 403 | The token's scope is below what the endpoint needs. A read token cannot call a write endpoint, for example. Issue a token with a higher scope. |
PORTFOLIO_NOT_FOUND | Varies | The referenced portfolio does not exist in this organisation. |
RATE_LIMITED | 429 | Too many requests from this identity. Back off and retry. The endpoint's per-minute ceiling is listed where it declares one. |
REFERENCED_ENTITY_NOT_FOUND | Varies | The body references another record, such as a loan or borrower, by an id that does not exist in this organisation. |
SESSION_EXPIRED | 401 | A browser session timed out under the organisation's session policy. Sign in again. |
UNAUTHORIZED | 401, 403, 404, 429, 503 | The request could not be authenticated or admitted. At 401 the token is missing, unknown, expired or revoked. At 403 or 404 the resource is outside what the caller can reach; an id in another organisation is treated as not found, so a response does not confirm another tenant's data. At 429 or 503 authentication itself is throttled or temporarily unavailable, so retry with backoff. |
UNKNOWN_EXPORT_TYPE | Varies | The export type requested is not one this endpoint produces. |
UNKNOWN_KIND | Varies | The import kind is not one this endpoint accepts. The response's allowed lists the valid values. |
VALIDATION_FAILED | Varies | One or more fields failed validation. The response's fieldErrors names each field and the reason. |
Endpoints
Every endpoint of the Waafir /v1 Platform API: method, path, the role and token scope it needs, accepted query parameters, rate limit and the error codes known to be reachable. Generated from the platform's route tree.
Investor permissioning, roles, and lifecycle
How investors get into a Waafir data room, what they can do once in, and how access is granted, scoped, extended, and revoked. Covers the IAM v2 role model, dataroom-level permissions, the share-link and guest-access flow, NDA gating, and the full invite-to-revoke lifecycle.