.wpb_animate_when_almost_visible { opacity: 1; }

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

  • HTTP status codes are normative, but the status messages are not. This means that servers are free to use application-specific error message strings.
  • A response with an HTTP error code or a connection time-out does not imply that the request message has not been handled by the server.

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.
  1. 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);
  2. 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.

  1. Go to Contact us page
  2. In the Request type drop-down list, select Technical, then I have a technical problem with an API used by my application
  3. Select the API
  4. 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).