Best practices for API error handling and troubleshooting
Published: October 8, 2024
OAuth 2.0 defines an authorization protocol for securing application access to protected resources provided by Orange APIs. OAuth 2.0 relies on access tokens to authorize this access. These tokens must be obtained before the client application can access these resources.
For each API, rate-limiting policies are enforced in order to:
- protect the API against severe traffic spikes and denial of service attacks,
- limit the number of API calls applications can make to the API over a specific fixed or rolling time frame (e.g. minute, hour, day, week or month).
This document provides:
- details about error cases to be managed by your application,
- the error codes and explanations to refer to when troubleshooting errors,
- details on the request ID returned to your application for any successful or failed requests to protected resources, which may be used to report issues to our support team.
At server level, Orange APIs handle errors by aborting the request and immediately returning an error response to your application.
- Requests that result in errors because of wrong client behavior can be re-attempted after fixing the underlying fault or after a given delay (for instance when being rate limited).
- Requests that fail because of server-side failures are indicated in the response.
The list below provides details about the main error cases that your application can meet:
HTTP status
Error code
Root cause
Recommended action
401
40
Missing credentials: e.g. missing Authorization header, missing token, missing Bearer prefix…
Verify Authorization header is present, with valid Bearer token
401
41
Invalid credentials: e.g. invalid client_id and/or client_secret, pending or revoked client_id…
Check your app’s credentials on the ‘Application details’ page of our developer portal. You may have renewed your credentials
401
42
Expired credentials: e.g. expired OAuth 2.0 token.
Generate a new token (i.e. POST /token) for your application. See tab Tips & Tricks
403
50
Access denied: e.g. not subscribed API, pending or revoked API subscription
Check your app’s subscriptions on the ‘Application details’ page of our developer portal
403
53
Too many requests: e.g. abnormal peak load on our Orange API, application quota defined by our API offer is exceeded (e.g. max. 1500 request/month/app)
See tab Tips & Tricks
503
5
Unavailable Orange API: e.g. bottleneck in the network, server is too busy or there is an undergoing maintenance
Check the API status if available (GET /status). If the problem persists, contact our support team or refer to tab Troubleshooting
Orange APIs use common HTTP response status codes to indicate whether a specific HTTP request has been successfully completed or not. Only two classes of error codes are defined by HTTP/1.1 protocol:
- client errors (4xx)
- servers errors (5xx)
The list below provides the main HTTP status codes that can be returned by our Orange APIs, focusing on the 401, 403 and 503 codes:
400
the request entity sent by your application could not be understood by the server due to malformed syntax (e.g. invalid payload, data type mismatch)
401
there is a problem with the credentials provided by your application. This code indicates that your application tried to operate on a protected resource without providing the proper authorization. It may have provided the wrong credentials or none at all
403
your application is not authorized to access the requested resource, or when your application is being rate-limited
404
the resource requested by your application does not exist
405
the HTTP method used by your application is not allowed for the resource
406
the resource requested by your application is not capable of generating response entities that are compliant with the Accept headers sent
408
your application did not produce a request within the time that the server was prepared to wait
409
the request sent by your application could not be completed due to a conflict with the current state of the resource
415
the request entity sent by your application is in a format not supported by the requested resource for the requested method
429
your application has made too many calls and has exceeded the rate limit for this service
500
the server encountered an unexpected condition which prevented it from fulfilling the request sent by your application
502
the server encountered an unexpected condition which prevented it from fulfilling the request sent by your application
503
the server is currently unable to handle the request sent by your application due to a temporary overloading or maintenance of the server
504
the server, while acting as a gateway or proxy, did not get a response in time from the upstream server that it needed in order to complete the API call
Error response messages provide additional information about the underlying fault, that you can use to debug the error as well as providing user friendly feedback in your application. The error reporting is designed to make the APIs usable – easy to implement and debug.
The body of the response contains more details about the error. The body is JSON-formatted like regular responses. Errors are guaranteed to remain unchanged when using a specific API version.
Error response entities for errors have an HTTP status code (e.g. 401 Unauthorized) and up to four attributes – two mandatory and two optional as shown below:
- code – integer: An integer coding the error type
- message – string: A short localized string that describes the error
- description – string: (optional) A long localized error description if needed. It can contain precise information about which parameter is missing, or what are the acceptable values
- infoURL – URL: (optional) A URL to online documentation that provides more information about the error
For instance:
json HTTP/1.1 401 Unauthorized Content-Type: application/json { "code": 41, "message": "Invalid credentials", "description": "The requested service needs credentials, but the ones provided were invalid." }
Caching the OAuth 2.0 token
When requesting an OAuth access token using the POST /token operation, your application uses the ‘expire_in’ field that provides the period of validity for the access token, expressed in seconds (e.g. 7776000 -> 90 days, or 3600 -> 1 hour). Your application should cache this token and not request a new access token until receiving an error indicating that the access token has expired.
json HTTP/1.1 200 OK Content-Type: application/json { "token_type": "Bearer", "access_token": "i6m2iIcY0SodWSe...L3ojAXXrH", "expires_in": "7776000" }
Rate-limited application
Two types of quota could make your application rate-limited, depending on our Orange APIs configuration:
- Rate-limiting quota is set for all our APIs.
- Application quota is optional.
- Rate-limiting quota
To protect Orange APIs against abnormal peaks of traffic, we configured a maximum number of allowed requests per second, for all inbound traffic made by applications – i.e. max. 25 requests per second. When a new request comes in, the server determines if the rate limit is exceeded for the current window of time (i.e. second). If so, the request is rejected on error, until the quota counter resets.The following error message is returned to your application:json HTTP/1.1 403 Forbidden Content-Type: application/json { "code": 53, "message": "Too Many Requests", "description": "The application has made too many calls and has exceeded the spike arrest limit for this service." }
When rate-limited, your application should wait a short delay (in the range of second) before retrying to send the request. Below an example in Java:
java TimeUnit.SECONDS.sleep(1); OR Thread.sleep(1000);
- Application quota. Let’s consider the two following examples:
1. for a given API, we configured the maximum number of allowed requests per fixed window – i.e. max. 2500 requests per month. When a new request comes in, the server determines if the quota has been exceeded for your application during the time window. If so, the request is rejected on error, until the quota counter resets, at midnight GMT of the last day of the month.
2. for another API, we configured the maximum number of allowed requests per rolling window – i.e. max. 600 requests per minute. When a new request comes in, the server determines if the quota has been exceeded for your application during the past time window. If so, the request is rejected on error. The counter never resets, but is recalculated on each request.In both cases, the following error message is returned to your application. Please note that , compared to rate-limiting quota, the error code and message are the same, but the description message changed (‘global quota limit’ instead of ‘spike arrest limit’).json HTTP/1.1 403 Forbidden Content-Type: application/json { "code": 53, "message": "Too Many Requests", "description": "The application has made too many calls and has exceeded the global quota limit for this service." }
At client level, your application must process the response entity to extract the information about the error that occurred (i.e. HTTP status code, error code, error message, error description (optional)).
In practice, frameworks will help you. A good example is Spring MVC’s RestTemplate. By default, the RestTemplate throws an exception for any response in the 4xx or 5xx ranges. You can customize this by providing your own implementation of ResponseErrorHandler. The default error handling behavior often makes sense, as it prevents you from checking the status code after each request. You can let an exception interrupt the execution flow, as usual.
In distributed service/resource-oriented architecture, request IDs are a way of grouping all the information associated with a given request to a protected resource; the main benefits are two-fold:
- Provides a tagging mechanism for events that are produced, so that a full report of what occurred and timing in every component touched can be generated for troubleshooting purpose
- Exposes an identifier to developers, which can be used to track down specific issues that they’re running into. If a request is consistently failing and the developer has verified that the request is properly formulated, the request ID may be used to report a problem to the support team.
Every request made against Orange APIs returns a response header named `X-OAPI-Request-Id`. This header contains an opaque value that uniquely identifies the request.
_As an example_:
```json HTTP/1.1 503 Internal Server Error Date: Thu, 14 Sep 2017 06:49:12 GMT Content-Type: application/json Content-Length: 184 X-OAPI-Request-Id: opopecballrt02-31151-13125058-1
{ "code": 5, "message": "The service is temporarily unavailable", "description": "The service in charge of the requested endpoint is temporarily unavailable or unreachable." } ```
If a request constantly fails and you have verified that the request is properly formulated, you may use this value to report the error to Orange as explained below.
- Go to Contact us page
- In the Request type drop-down list, select Technical, then I have a technical problem with an API used by my application
- Select the API
- Fill in the request details. Make sure to add:
- information about the type of operation that the request attempted (e.g. POST https/api.orange/com/cloud/v1/folders -> create a new folder into Orange customer’s personal cloud),
- the value of X-OAPI-Request-Id header
- the approximate time that the request was made (e.g. Thu, 14 Sep 2024 06:49:12 GMT).