Skip to main content

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"
}
FieldTypeDescription
statusintegerHTTP status code
messagestringHuman-readable error description
pathstringThe request path that caused the error
timestampstringISO 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 Authorization header
  • 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

_errorCodeMeaning
CONNECTION_ERRORService task could not connect to the remote endpoint
HTTP_ERROR_{status}Service task received an HTTP error response (e.g., HTTP_ERROR_500)
TIMEOUTNode exceeded its configured timeout
SCRIPT_ERRORScript task threw an uncaught exception
AI_ERRORAI task encountered an error from the LLM provider
VARIABLE_NOT_FOUNDA required variable was null or undefined at execution time
CONDITION_ERRORIf/Else condition expression could not be evaluated
SUBPROCESS_ERRORA called subprocess or call process failed
CANCELLEDNode was cancelled by an admin or boundary event

Authentication Error Details

ScenarioStatusMessage
No Authorization header401Unauthorized: no credentials provided
Invalid JWT signature401Unauthorized: invalid token
Expired JWT401Unauthorized: token expired
Unknown API key ID401Unauthorized: invalid or expired API key
Revoked API key401Unauthorized: API key has been revoked
Suspended API key401Unauthorized: API key is suspended
Expired API key401Unauthorized: API key has expired
Wrong organization403Forbidden: resource not in your organization
Missing permission403Forbidden: 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.