Errors
This page is for integrators (developers integrating with the Subnoto API or using the TypeScript/Python SDKs). It describes the error response format and how to handle each error type in your application.
Response shape
Section titled “Response shape”All error responses are JSON with this shape:
| Field | Type | Description |
|---|---|---|
| statusCode | number | HTTP status (400, 401, 403, 500). |
| error | object | Error payload (see below). |
| requestId | string | Unique request id. Send this to support when reporting an issue. |
| timestamp | string | ISO 8601 time of the response. |
| path | string | Request path that failed. |
The error object:
| Field | Type | Description |
|---|---|---|
| code | string | Machine-readable code (e.g. INVALID_REQUEST_FORMAT, WORKSPACE_NOT_FOUND). |
| message | string | Short human-readable message. |
| suggestion | string | Recommended action. |
| documentationUrl | string | Link to this documentation. |
| details | array (optional) | Present only for validation errors; see below. |
Example (business error, no details):
{ "statusCode": 400, "error": { "code": "WORKSPACE_NOT_FOUND", "message": "Workspace not found", "suggestion": "Please refer to the documentation for more details.", "documentationUrl": "https://subnoto.com/documentation" }, "requestId": "6bec230f-cdb9-4ee2-9c47-ebc027f8184d", "timestamp": "2026-03-12T12:14:59.065Z", "path": "/workspace/delete"}What to do in your integration
Section titled “What to do in your integration”- Use
statusCodeto distinguish client errors (4xx) from server errors (5xx). - Branch on
error.codeto decide messaging or retry (e.g.WORKSPACE_NOT_FOUNDvsINVALID_REQUEST_FORMAT). - Show
error.messageanderror.suggestionto the user or in logs. - If
error.detailsis present, use it to show per-field validation errors (see Validation errors). - Keep or log
requestIdso support can trace the request.
Validation errors (400, INVALID_REQUEST_FORMAT)
Section titled “Validation errors (400, INVALID_REQUEST_FORMAT)”When the request body fails schema validation (wrong type, missing required field, invalid format), the API returns
400 with code INVALID_REQUEST_FORMAT and an error.details array.
Each element of details has:
| Field | Type | Description |
|---|---|---|
| path | string[] | Path segments to the invalid field (e.g. ["input"], ["recipients"]). |
| message | string | Validation message for that field. |
Use path to map errors to form fields (e.g. the last segment is often the field name). Use message as the inline error text.
Example:
{ "statusCode": 400, "error": { "code": "INVALID_REQUEST_FORMAT", "message": "The request format is invalid.", "suggestion": "Please check the request and try again.", "documentationUrl": "https://subnoto.com/documentation", "details": [ { "path": ["input"], "message": "Invalid input: expected string, received number" } ] }, "requestId": "...", "timestamp": "...", "path": "/tests/noneAuthentication"}Business errors (400)
Section titled “Business errors (400)”Endpoints return 400 with other codes for domain rules (e.g. WORKSPACE_NOT_FOUND, ENVELOPE_NOT_FOUND).
These responses do not include details. Use error.code and error.message for user-facing messages.
Request format and tunnel (400, 401)
Section titled “Request format and tunnel (400, 401)”- UNSUPPORTED_CONTENT_TYPE (400): Decrypted body is not valid JSON but the endpoint expects JSON. Send valid JSON.
- AUTHENTICATION_ERROR (401): Invalid or missing credentials. Have the user sign in again or check API keys.
- TUNNEL_SESSION_NOT_FOUND (401): The tunnel session is missing or expired. Create a new tunnel session and retry once.
- TUNNEL_ERROR (401): A generic tunnel failure. Create a new tunnel session and retry.
The TypeScript and Python SDKs create a new tunnel session and retry on TUNNEL_SESSION_NOT_FOUND and TUNNEL_ERROR.
If you use raw HTTP, create a new session yourself after these codes.
Authorization and plan (403)
Section titled “Authorization and plan (403)”- AUTHORIZATION_ERROR: Credentials are valid but not allowed to access the resource.
- FEATURE_NOT_IN_CURRENT_PLAN: The action is not available on the current plan. Use
error.suggestionanddocumentationUrlto guide the user (e.g. upgrade).
Server errors (500)
Section titled “Server errors (500)”INTERNAL_SERVER_ERROR indicates a problem on Subnoto’s side. Show a generic error message, suggest retrying later, and ask the user to provide requestId if they contact support.
The TypeScript and Python SDKs return the same error shape. On failure, the error or result includes the full
API response (statusCode, error.code, error.message, error.details, etc.). The SDKs handle tunnel refresh and
retry on tunnel errors, so you do not need to manage tunnel lifecycle unless you use raw HTTP.