Bob’s Public APIs follow standard HTTP conventions to report success or failure.
Each response includes an HTTP status code, and when an error occurs, a structured JSON payload explains what went wrong.
While the general structure of error messages is similar across modules, the exact fields may vary slightly.
For example, the Goals API includes a more detailed statusCode and timestamp, while other APIs return a simpler key and error pair.
Expected status codes and error formats
The following table lists common status codes you can expect from Bob’s APIs, with examples of typical error payloads.
| Type | Status | Description |
|---|---|---|
| Sucess statuses | ||
| 200 – OK | The request was successful, and the response may include data | |
| 201 – Created | The resource was created successfully (e.g., creating a project or goal). Response includes the ID of the created object. | |
| 204 – No Content | The operation succeeded, but there is no response body (e.g., archive or delete). | |
| Errors/Warnings | ||
| 304 – Not Modified | The submitted data matches the current record. No changes were applied. | |
| 400 – Bad Request | The request is invalid, missing fields or results in a duplicate record in case of create. Often returned for field validation errors, a duplicate record, or malformed JSON. It may also include a more detailed description of the specific problem. Do not handle with retry. | |
| 401 – Unauthorized | The request could not be authenticated. Check your service user credentials or OAuth token. | |
| 403 – Forbidden | The service user does not have permission to access this resource, or the scope access is missing. You should check your permissions settings, amend the permissions, and try again. | |
| 404 – Not Found | The requested resource was not found usually means you are a resource that is not available for your organization. Some APIs require purchasing and activating the equivalend module, e.g., 'Time and Attendance' or 'Bob Hiring'. | |
| 429 – Too Many Requests | You’ve reached the request rate limit. Check the response headers for retry details. See rate limit errors. | |
| 500 – Internal Server Error | Something went wrong on Bob’s side. Retry later or contact support. |
Best practices
- Always check the HTTP status code before parsing the response body.
- Use the
errorormessagefield to display or log issues. - Handle 429 and 500 errors with retries and backoff logic.
- Do not handle 400 errors with retry logic. This error indicates a validation issue rather than a temporary failure. Retrying the same request will produce the same result unless errors are corrected.
- Refer to each module’s API reference for specific examples of structures and errors.
Error response structure
The structure of error messages may differ slightly across modules:
Common error message formats
//Error 400
{
"key": "Unknown field ID: /work/site",
"error": "Unknown field ID: /work/site",
"args": [
"Unknown field ID: /work/site"
]
}
// Error 400
{
"error": "BAD_REQUEST",
"message": "Invalid input provided",
"statusCode": 400,
"timestamp": "2025-01-01T12:00:00Z"
}
//Error 404
{
"key": "exception.attendance.project.notfound",
"error": "project not found",
"args": [
"232323232"
]
}Tip: Always check the “Error responses” section in the endpoint reference for the exact structure and field names.
Rate limit errors
When a 429 Too Many Requests error occurs, the response includes rate-limit headers to help you determine when to retry:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
Retry-After: 30
For details, see Rate limiting.
Filtering errors
When using filters in search endpoints, the filter structure follows the structure:
"filters": [
{
"fieldId": "/position/status",
"operator": "equals",
"values": [
"vacant"
]
}
When one of the fiter fields is missing (e.g. no fieldId exists in the payload), the error strucure is:
Missing required field: obj[0].fieldId -> Missing required filter field id
Where obj[0] reflects the filters array in the backend.
When you see such errors, make sure you filter is structured correctly and try again.
