Error Reference
Standard error response format and error codes for the apptor flow API.
Error Response Format
All API errors return a consistent JSON structure:
{
"status": 400,
"message": "Validation failed: 'name' is required",
"path": "/process/create",
"timestamp": "2026-02-20T10:00:00Z"
}
| Field | Type | Description |
|---|---|---|
status | integer | HTTP status code |
message | string | Human-readable error description |
path | string | The request path that caused the error |
timestamp | string | ISO 8601 timestamp of the error |
Some endpoints return additional fields for validation errors:
{
"status": 422,
"message": "Validation failed",
"errors": [
{ "field": "name", "message": "must not be blank" },
{ "field": "processId", "message": "must not be null" }
],
"path": "/process/create",
"timestamp": "2026-02-20T10:00:00Z"
}
HTTP Status Codes
200 OK
Request succeeded. Response body contains the result.
201 Created
Resource was successfully created. Response body contains the new resource.
400 Bad Request
The request was malformed or contained invalid data.
Common causes:
- Missing required fields in the request body
- Invalid field types or formats
- Workflow JSON is not valid (when creating/updating a workflow definition)
{
"status": 400,
"message": "Invalid processText: JSON parse error at line 5",
"path": "/process/create"
}
401 Unauthorized
Authentication failed or no credentials were provided.
Common causes:
- Missing
Authorizationheader - Expired JWT token
- Invalid or revoked API key
- Suspended API key
{
"status": 401,
"message": "Unauthorized: invalid or expired API key",
"path": "/process/exec"
}
Fix: Re-authenticate (get a fresh JWT) or verify your API key is active and correctly formatted as apk_{keyId}_{secret} in the X-API-Key header.
403 Forbidden
The authenticated user/key exists but lacks the required permission.
Common causes:
- JWT user does not have the required permission (e.g.,
WORKFLOW_CREATE) - API key does not have the required role/permission
- Attempting to access another organization's resources
{
"status": 403,
"message": "Forbidden: missing permission WORKFLOW_CREATE",
"path": "/process/create"
}
Fix: Check which permissions are required for the endpoint. Assign the appropriate role to the user or API key.
404 Not Found
The requested resource does not exist, or you do not have access to it.
Common causes:
- Invalid
processId,processInstanceId,userId, etc. - Resource belongs to a different organization
- Resource was deleted
{
"status": 404,
"message": "Workflow proc_abc123 not found",
"path": "/process/proc_abc123"
}
409 Conflict
The request conflicts with existing state.
Common causes:
- Creating a resource with a name that already exists
- Attempting to activate an already-active resource
{
"status": 409,
"message": "A secret with name 'OPENAI_API_KEY' already exists",
"path": "/secrets"
}
422 Unprocessable Entity
The request body is syntactically valid but semantically invalid.
Common causes:
- Field-level validation failures
- Business rule violations
{
"status": 422,
"message": "Validation failed",
"errors": [
{ "field": "email", "message": "must be a valid email address" }
],
"path": "/users"
}
429 Too Many Requests
The API key's rate limit has been exceeded.
Headers included:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1708430460
Retry-After: 32
{
"status": 429,
"message": "Rate limit exceeded: 60 requests per minute",
"path": "/process/exec"
}
Fix: Wait for the Retry-After duration before retrying. Consider increasing the rate limit on the API key or distributing load across multiple keys.
500 Internal Server Error
An unexpected error occurred on the server.
{
"status": 500,
"message": "An internal error occurred. Reference: err_20260220_abc123",
"path": "/process/exec"
}
Fix: Note the error reference and contact support. Do not retry immediately — log the reference for investigation.
503 Service Unavailable
The server is temporarily unavailable (maintenance, overload).
Execution-Specific Errors
When a workflow execution fails, the stateCd on the process instance is set to 2 (Failed). The execution detail endpoint returns the failed node's information:
{
"processInstanceId": "inst_xyz789",
"stateCd": 2,
"nodeInstances": [
{
"nodeId": "rest-call-1",
"nodeName": "Call Payment API",
"nodeType": "serviceTask",
"statusCd": 3,
"variables": {
"_error": "Connection refused: https://api.payments.com/charge",
"_errorCode": "CONNECTION_ERROR"
}
}
]
}
Execution Error Codes
_errorCode | Meaning |
|---|---|
CONNECTION_ERROR | Service task could not connect to the remote endpoint |
HTTP_ERROR_{status} | Service task received an HTTP error response (e.g., HTTP_ERROR_500) |
TIMEOUT | Node exceeded its configured timeout |
SCRIPT_ERROR | Script task threw an uncaught exception |
AI_ERROR | AI task encountered an error from the LLM provider |
VARIABLE_NOT_FOUND | A required variable was null or undefined at execution time |
CONDITION_ERROR | If/Else condition expression could not be evaluated |
SUBPROCESS_ERROR | A called subprocess or call process failed |
CANCELLED | Node was cancelled by an admin or boundary event |
Authentication Error Details
| Scenario | Status | Message |
|---|---|---|
No Authorization header | 401 | Unauthorized: no credentials provided |
| Invalid JWT signature | 401 | Unauthorized: invalid token |
| Expired JWT | 401 | Unauthorized: token expired |
| Unknown API key ID | 401 | Unauthorized: invalid or expired API key |
| Revoked API key | 401 | Unauthorized: API key has been revoked |
| Suspended API key | 401 | Unauthorized: API key is suspended |
| Expired API key | 401 | Unauthorized: API key has expired |
| Wrong organization | 403 | Forbidden: resource not in your organization |
| Missing permission | 403 | Forbidden: missing permission {PERMISSION_KEY} |
Handling Errors in Code
JavaScript / TypeScript
async function executeWorkflow(processId, data, apiKey) {
const response = await fetch('/process/exec', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({ processId, data })
});
if (!response.ok) {
const error = await response.json();
switch (response.status) {
case 401:
throw new Error(`Authentication failed: ${error.message}`);
case 403:
throw new Error(`Permission denied: ${error.message}`);
case 404:
throw new Error(`Workflow not found: ${processId}`);
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new RateLimitError(`Rate limit exceeded`, parseInt(retryAfter));
default:
throw new Error(`API error ${response.status}: ${error.message}`);
}
}
return response.json();
}
Java
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
if (response.statusCode() >= 400) {
var error = objectMapper.readValue(response.body(), ApiError.class);
switch (response.statusCode()) {
case 401 -> throw new AuthenticationException(error.getMessage());
case 403 -> throw new PermissionException(error.getMessage());
case 404 -> throw new ResourceNotFoundException(error.getMessage());
case 429 -> throw new RateLimitException(error.getMessage());
default -> throw new ApiException(response.statusCode(), error.getMessage());
}
}
Rate Limit Headers
Every API response includes current rate limit state (when using API key auth):
X-RateLimit-Limit-Minute: 60
X-RateLimit-Remaining-Minute: 45
X-RateLimit-Limit-Hour: 1000
X-RateLimit-Remaining-Hour: 872
Monitor these headers to avoid hitting 429 errors proactively.