Error Handling
All error responses use a uniform JSON format.
json
{
"error": "error_code",
"error_description": "Description of the error"
}HTTP status codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | validation_error | Invalid request data (missing fields, wrong format) |
| 400 | invalid_request | The access token was not sent in the Authorization header, or was sent through more than one method at once |
| 401 | invalid_client | Invalid or missing access token |
| 403 | client_revoked | OAuth client has been revoked |
| 403 | access_denied | The endpoint is only available to Offisy Connect devices |
| 403 | insufficient_scope | The client does not have the required permission |
| 404 | not_found | Resource not found |
| 429 | rate_limit_exceeded | Too many requests. Wait and try again. |
Note: For
429, the response includes aRetry-Afterheader with the wait time in seconds. The response body also includesplanandlimit— this combination tells you whether the per-minute or the per-day limit applied. See Rate Limits for details and the full limit table.
At the token endpoint (POST /api/oauth/v2/token), a 429 response also includes a reason field with the values company_minute, client_attempts, or ip.
Handling errors
JavaScript
javascript
const response = await fetch('https://my.offisy.at/api/oauth/v2/resource/appointments', {
headers: { 'Authorization': 'Bearer {access_token}' }
});
// These three headers are present on every response, including successful ones
const limit = response.headers.get('X-RateLimit-Limit');
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
if (!response.ok) {
const error = await response.json();
console.error(`${error.error}: ${error.error_description}`);
if (response.status === 429) {
console.log(`Plan: ${error.plan}, Limit: ${error.limit}`);
const retryAfter = response.headers.get('Retry-After');
console.log(`Retry after ${retryAfter} seconds`);
}
}