# Integration best practices

For maximum compatibility and durability of your integration application, we recommended you follow the best practices listed on this page. Not all of the notes apply to every integration. For example, parsing JSON is not relevant for applications requesting API responses in XML format. However, it is a good practice to keep the points below in mind.

## Backward compatibility

Infobip API evolves over time. We work hard to add new functionalities and improve existing ones with new features. By doing so, we will maintain backward compatibility in accordance with a couple of rules. Abiding by those rules will ensure that your integration continues to work properly with any future API improvements and benefit from those new features.

### Adding new fields to existing resources [#adding-new-fields-to-existing-resources-backward-compatibility]

One of the ways that we will use to introduce new features to the existing API endpoints is by adding new properties to the existing request and/or response models. For example:

```json showLineNumbers copy filename="json"
    Original response model:
    {
        "status": "OK",
        "statusId": 1
    }
    
    Extended response model:
    {
        "status": "OK",
        "statusId": 1,
        "statusDescription": "All went well, no additional actions required"
    }
```

When adding properties to request models we will always ensure that the field is optional so that all of the existing integrations continue to work without problems.

Regarding the properties in response models, however, you should ensure that your parsing implementation does not break when it encounters unspecified properties. That way you will not have to update your code every time a new feature is added to the API. At the same time, if you choose to use the new feature, updating your code will be simplified as you will only need to parse one new property.

### JSON property order [#json-property-order-backward-compatibility]

[JSON specification](http://www.json.org/) does not guarantee the order of name/value pairs in objects, so your JSON parsing implementation should not depend on it either. In practice this means that the following JSON objects are considered to be identical:

```json showLineNumbers copy filename="json"
    Example object:
    {
        "status": "OK",
        "statusId": 1
    }
    
    Equivalent object:
    {
        "statusId": 1,
        "status": "OK"
    }
```

API implementation may interchangeably return any of the above example objects and they should be treated identically by the client code. Fortunately, if `json` parsing is delegated to your language’s native functionality or one of the established parsing libraries, this should have been handled properly by those implementations.

### Date formats [#date-formats-backward-compatibility]

API will generally return dates in a predefined and uniform format. Consult the dedicated documentation page for details on a specific endpoint. The format used by default:

`yyyy-MM-dd'T'HH:mm:ss.SSSZ`

Note that the format encodes, and requires a time zone information. This means that the two seemingly different date-time strings actually represent the same point in time:

`2017-07-20T06:47:45.777+0000 `

`2017-07-20T07:47:45.777+0100`

When parsing dates received from API, you should take the time zone into account. The best practice is to convert the string received from API into your language’s native representation of the moment in time; then it can be processed and the time zone and format of your choice will be displayed to your users.

Note
Do not expect that the date and time returned from API will always be in a predefined time zone. Instead, you should use the returned time zone information.

### Preventing errors [#preventing-errors-backward-compatibility]

Besides ensuring that your application continues to be compatible with the future developments on the API, it is also important to keep it free of bugs. To help you with that, here are a couple of common problems that should be taken into account.

### Request body content types [#request-body-content-types-backward-compatibility]

Every request that contains message body data should contain a Content-Type header. Supported content types are `application/json` and `application/xml`. In each case, the body data that you send in your request should match the supplied Content-Type header and be valid.

### JSON content [#json-content-backward-compatibility]

If you choose to use JSON, make sure that you serialize your data into [valid JSON objects](https://www.json.org/json-en.html). Specifically, watch out for string values. They should not contain double-quote characters `(")` as including them would mark an end of a string. If double-quotes are needed, make sure they are escaped with a backslash `(\)`. Furthermore, make sure that name/value pairs in your JSON objects are separated by commas `(,)`. If you opt to use some of the standard serialization libraries this should all be implemented already.

```json showLineNumbers copy
    {
      "stringProperty": "properly \"quoted\" string value",
      "numberProperty": 47,
      "booleanProperty": true,
      "nullProperty": null
    }
```

```json showLineNumbers copy
    {
      "stringProperty": "properly "quoted" string value"
      "numberProperty": 47
      "booleanProperty": true
      nullProperty: null
    }
```

### XML content [#xmlcontent-backward-compatibility]

If you are using `XML`, make sure that your objects are properly serialized into valid `XML`. Specifically, check that you are closing all of your tags and that you are doing so in the correct order. Also, note that the tags are case sensitive. Again, a well-established `XML` serialization library or native language function should take care of all of this.

```xml showLineNumbers copy filename="xml"
    <request>
<outerproperty>
<nestedproperty>Some Value</nestedproperty>
</outerproperty>
<flatproperty>47</flatproperty>
<emptyproperty></emptyproperty>
</request>
```

## Deprecated standards

The industry standards can become deprecated with time. The prime example of this is the usage of the SHA-1 hashing function in SSL certificates. As noted in the [security and authorization documentation section](https://www.infobip.com/docs/api/section/Authentication), it is strongly recommended to connect to our API using the HTTPS protocol. Since SHA-1 has been deprecated and support for it is being removed from modern technology stacks and applications, our API is signed by certificates created using newer algorithms. In order to recognize it, your stack should use them as well.

## Handling errors

Even in a normal integration operation, it is expected to encounter some error responses from the API. In cases when an error occurs, we will attempt to fill the API response with a recognizable and self-explanatory message. In such scenarios, it is advisable to have your code analyze the API response and react to them in an appropriate manner.

### HTTP response codes [#http-response-codes-handling-errors]

You should get familiar with the list of all [HTTP response codes and their meaning](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). We will strive to return the appropriate status code to every request. Examining the returned status code is the first thing you can do to determine how to react to an API response.

Generally, any status in the `200s` range (from `200` up to `299`) is considered to be successful and no additional reaction is needed.

Responses with a status code in the 400s range (400 to 499) indicate that there was something wrong with your request. Immediately sending the exact same request again will result in the same error, so it is not advisable. Instead, you can analyze the specific status returned and adapt accordingly. If, for example, the status 400 (Bad request) is returned, you should double-check your Content-Type header, check that your request body data is properly serialized and that the data sent to the API corresponds to the specified request model from the dedicated API endpoint documentation page. On the other hand, receiving the status 404 (Not found) means that either the requested API endpoint or the exact resource does not exist. In this case, double-check the API endpoint path defined on the dedicated documentation page.

Status codes in the 500s range (500 to 599) signal that the request is valid but an error occurred on the API side. Depending on the specific status, the error might be temporary so retrying the same request may yield different results.

### Throttling [#throttling-handling-errors]

One of the specific errors that can occur with your requests is a throttling error. It will generally be denoted by an HTTP status code [429 (`TOO_MANY_REQUESTS`)](https://www.infobip.com/docs/essentials/api-essentials/response-status-and-error-codes#429-too-many-requests-people-api-error-codes), and it happens when you make too many requests to a specific endpoint within the configured rate limits.

Infobip API uses token-based rate limiting to control request rates. Different endpoints may have different throttling configurations, and you should consult the specific API documentation for each endpoint to understand the applicable limits.

#### Rate limit types

API endpoints may be protected by one or both of the following rate limit mechanisms:

1. **Time-based rate limit**: Limits the number of requests within a fixed time window. Example: 100 requests per 10 seconds
2. **Token-based rate limit**: Uses a token bucket algorithm that allows bursts while maintaining a steady refill rate. Example: Burst capacity of 5 requests with a refill rate of 1 request per second

#### Handling throttled requests

In case one of your API requests ends up being throttled, you should implement exponential backoff and retry logic. Wait for a short period before retrying, and increase the wait time with each subsequent throttled response. However, be mindful of retrying too many times, as excessive retries can cause even more requests to be throttled.

When implementing retry logic, make sure to:

- Include a limit on the number of retries
- Implement exponential backoff between retries
- Monitor the overall number of throttled requests
- Check the `Retry-After` header in the 429 response, if present, to know when to retry

If too many of your requests end up being throttled consistently, you might be using the API in an unsupported way or need to optimize your request patterns.

## Coding practices

Here is a best practice when coding and using our examples in development while using our API.

### Query parameters and URL encoding [#query-parameters-and-url-encoding-coding-practices]

Query parameter examples and code examples on the [Infobip API Developer Hub](https://www.infobip.com/docs/api) (for example, [Get SMS Logs](https://www.infobip.com/docs/api/channels/sms/logs-and-status-reports/get-outbound-sms-message-logs-v3)) are not URL encoded.

There are a couple of reasons for this. First, we want the code examples to be human-readable. Second, many languages and libraries that make HTTP calls do not require explicit URL encoding for query parameters - it happens "under the hood".

If you use a system/library/language that requires explicit URL encoding, you will need to do it yourself. Fortunately, there is ample support in virtually every language for that.
