Skip to content

Error Handling ​

All error responses use a uniform JSON format.

json
{
  "error": "error_code",
  "error_description": "Description of the error"
}

HTTP status codes ​

HTTP StatusError CodeDescription
400validation_errorInvalid request data (missing fields, wrong format)
400invalid_requestThe access token was not sent in the Authorization header, or was sent through more than one method at once
401invalid_clientInvalid or missing access token
403client_revokedOAuth client has been revoked
403access_deniedThe endpoint is only available to Offisy Connect devices
403insufficient_scopeThe client does not have the required permission
404not_foundResource not found
429rate_limit_exceededToo many requests. Wait and try again.

Note: For 429, the response includes a Retry-After header with the wait time in seconds. The response body also includes plan and limit — 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`);
  }
}

Offisy GmbH