# API authentication

___

Every request to the Infobip API needs two things: the Base URL of your account, and credentials in the `Authorization` header. Infobip supports four authentication methods: API keys, OAuth 2.0, IBSSO tokens, and HTTP Basic authentication. Use an API key unless your tech stack or security requirements call for another method.

Authentication proves who is calling. What the call is allowed to do depends on the scopes of your credentials: see [Authorization and scopes](https://www.infobip.com/docs/developer-resources/authentication-and-access/authorization-and-scopes). If a request fails with `401 Unauthorized`, see [Authentication errors](#authentication-errors).

___

## Base URL

Every API request must include the Base URL unique to your account, in the format `xxxxx.api.infobip.com`. To find yours, log in to your account. The Base URL is shown on your homepage and on the API keys page of the web interface, and the API docs display it in every endpoint example.

```text
Base URL: https://example.api.infobip.com
Base URL used in the Send SMS message endpoint: https://example.api.infobip.com/sms/3/messages
```

NOTE  
The Base URL routes your requests to the nearest data center at the DNS level. It optimizes performance and does not authorize access, so it is not a secret. An incorrect Base URL can degrade or interrupt the service.

___

## Choose an authentication method

Whichever method you use, send requests over an encrypted TLS connection. See [REST API traffic encryption](https://www.infobip.com/docs/developer-resources/security/rest-api-traffic-encryption).

The following table compares the methods, from most to least recommended, across security, complexity, session lifetime, and ideal use cases.

| Method | Security level | Setup complexity | Session lifetime | Best for |
| --- | --- | --- | --- | --- |
| API keys | High (scoped, revocable) | Low. Generate a key and use it directly. Rotate keys regularly. | Fixed expiry date you set. Through the API, 1 year by default. | Most integrations. Server-to-server calls where you want fine-grained scope control, revocable credentials, and long-lived access without token refresh. The only method the Java and C# [API client libraries](https://www.infobip.com/docs/developer-resources/developer-tools/sdks) support. |
| OAuth 2.0 | Highest | Medium. Request a token before each session. | Short-lived, expires in seconds (per response) | Integrations that need the most secure, industry-standard flow, or must work with systems that already speak OAuth. |
| IBSSO tokens | High (session-based) | Medium. Create a session, destroy it when needed. | 60 minutes by default. Destroy the session to end it sooner. | Single sign-on scenarios, or centralizing sensitive data handling across enterprise systems without distributing it. |
| HTTP Basic authentication | Low (easily decoded) | Lowest. No separate token step. | None, sent with every request | Only when no other method is available, for example to create your first API key through the API. Do not use in production. |

To troubleshoot authentication issues, see [Authentication errors](#authentication-errors) and [Handling errors](https://www.infobip.com/docs/developer-resources/api-fundamentals/handling-errors), or contact [Support](https://www.infobip.com/contact).

___

## API key authentication

An API key is an access token that your application provides when making API calls. It is a simple way to secure access, which makes it the most popular authentication method for REST APIs. Send the key as a request header, using the `App` prefix: `Authorization: App {your-api-key}`. Avoid sending it in the query string, where it can leak into server logs and browser history.

Self-signup accounts are automatically assigned an API key after you [create an account](https://www.infobip.com/docs/get-started/build-and-go-live/create-an-account). Managed accounts do not receive an API key automatically, so [generate one](#how-to-use-api-keys-api-key-authentication) before you make your first API call.

- You can revoke keys at any time, which is useful when separating API access rights across multiple applications or use cases.
- API keys expire on the date you set. If you create a key through the API without an expiry date, it expires 1 year after creation.
- Rotate API keys regularly, and immediately if a key is exposed. See [Security best practices](https://www.infobip.com/docs/developer-resources/security/security-best-practices#token-and-api-key-expiry-api-authentication-and-authorization).

NOTE  
Managing messaging for multiple businesses or brands: You can scope API keys to specific Applications and Entities. This isolates traffic per business, environment, or brand. See [Manage API keys](https://www.infobip.com/docs/cpaas-x/security/manage-api-keys) in the CPaaS X docs.

### How to use API keys [#how-to-use-api-keys-api-key-authentication]

1. Get an API key. A self-signup account comes with an API key. To create more, or on other accounts, generate one on the [Infobip API key management page](https://portal.infobip.com//dev/api-keys) (**Developer Tools** > **API Keys**). You can also use the [Create API key](https://www.infobip.com/docs/developer-resources/authentication-and-access/authorization-and-scopes#assign-scopes-when-creating-an-api-key) endpoint. The API key endpoints do not accept an API key, so authenticate those calls with [Basic authentication](#basic-authentication), [OAuth 2.0](#oauth-20-authentication), or an [IBSSO token](#ibsso-token-authentication).
2. Assign the scopes your integration needs to the key. See [Authorization and scopes](https://www.infobip.com/docs/developer-resources/authentication-and-access/authorization-and-scopes) for available scopes and how to assign them.
3. Include `App` and the key in the `Authorization` header on every API request: `Authorization: App {your-api-key}`.

### Send a request with an HTTP client [#use-http-client]

The following examples send an SMS message with the [Send SMS endpoint](https://www.infobip.com/docs/api/channels/sms/outbound-sms/send-message/send-sms-messages), authenticated with an API key. Replace `{baseUrl}` and `{apiKey}` with your own values.

```bash
curl -X POST 'https://{baseUrl}/sms/3/messages' \
    -H 'Authorization: App {apiKey}' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
        "messages": [
            {
                "sender": "InfoSMS",
                "destinations": [{ "to": "41793026727" }],
                "content": { "text": "This is a sample message" }
            }
        ]
    }'
```

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

String apiKey = "{apiKey}";
String body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://{baseUrl}/sms/3/messages"))
    .header("Authorization", "App " + apiKey)
    .header("Content-Type", "application/json")
    .header("Accept", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<string> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

```csharp
using System.Net.Http.Headers;
using System.Text;

var apiKey = "{apiKey}";
var body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

var client = new HttpClient { BaseAddress = new Uri("https://{baseUrl}") };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("App", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.PostAsync("/sms/3/messages", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### Send a request with an API client library [#use-an-api-client-library-api-key-authentication]

The [API client libraries](https://www.infobip.com/docs/developer-resources/developer-tools/sdks) support API key authentication. Provide your Base URL and API key when you create the client. The library adds the `App` prefix to the `Authorization` header for you.

```java
import com.infobip.ApiClient;
import com.infobip.ApiKey;
import com.infobip.BaseUrl;
import com.infobip.api.SmsApi;
import com.infobip.model.*;
import java.util.List;

ApiClient apiClient = ApiClient.forApiKey(ApiKey.from("{apiKey}"))
    .withBaseUrl(BaseUrl.from("https://{baseUrl}"))
    .build();

SmsApi smsApi = new SmsApi(apiClient);

SmsMessage message = new SmsMessage()
    .sender("InfoSMS")
    .addDestinationsItem(new SmsDestination().to("41793026727"))
    .content(new SmsTextContent().text("This is a sample message"));

SmsRequest smsRequest = new SmsRequest().messages(List.of(message));

SmsResponse smsResponse = smsApi.sendSmsMessages(smsRequest).execute();
```

```csharp
using Infobip.Api.Client;
using Infobip.Api.Client.Api;
using Infobip.Api.Client.Model;

var configuration = new Configuration()
{
    BasePath = "https://{baseUrl}",
    ApiKey = "{apiKey}"
};

var smsApi = new SmsApi(configuration);

var smsMessage = new SmsMessage(
    sender: "InfoSMS",
    destinations: new List<smsdestination> { new SmsDestination(to: "41793026727") },
    content: new SmsMessageContent(new SmsTextContent(text: "This is a sample message"))
);

var smsRequest = new SmsRequest(messages: new List<smsmessage> { smsMessage });

var smsResponse = smsApi.SendSmsMessages(smsRequest);
```

___

## OAuth 2.0 authentication

OAuth 2.0 is the most secure authentication option and an industry standard, defined in [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749). You get a short-lived access token from the Create OAuth2 token endpoint and send it with each request.

- The access token expires within the time limit provided in seconds in the response.
- Infobip acts as both a resource and an authorization server.
- You must create a new token after the token expires. There is no automatic token retrieval.

### How to use OAuth 2.0 authentication [#how-to-use-oauth-20-authentication-oauth-20-authentication]

1. Call [Create OAuth2 token](https://www.infobip.com/docs/api/platform/account-management/oauth/create-oauth2-token) to get the access token and its expiration time.
2. Include `Bearer` and the token in the `Authorization` header for all subsequent calls: `Authorization: Bearer {access_token}`.

### Get an OAuth 2.0 token [#get-an-oauth-20-token-oauth-20-authentication]

The following examples call the Create OAuth2 token endpoint and read the token from the response. Use your Infobip username as `client_id` and your password as `client_secret`. The `expires_in` field in the response contains the token lifetime in seconds.

```bash
curl -X POST 'https://{baseUrl}/auth/1/oauth2/token' \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    -H 'Accept: application/json' \
    --data-urlencode 'client_id={username}' \
    --data-urlencode 'client_secret={password}' \
    --data-urlencode 'grant_type=client_credentials'
```

```java
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.ObjectMapper;

String form = "client_id=" + URLEncoder.encode("{username}", StandardCharsets.UTF_8)
    + "&client_secret=" + URLEncoder.encode("{password}", StandardCharsets.UTF_8)
    + "&grant_type=client_credentials";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://{baseUrl}/auth/1/oauth2/token"))
    .header("Content-Type", "application/x-www-form-urlencoded")
    .header("Accept", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(form))
    .build();

HttpResponse<string> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());

String accessToken = new ObjectMapper().readTree(response.body()).get("access_token").asText();
```

```csharp
using System.Text.Json;

var client = new HttpClient { BaseAddress = new Uri("https://{baseUrl}") };

var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
    ["client_id"] = "{username}",
    ["client_secret"] = "{password}",
    ["grant_type"] = "client_credentials"
});

var response = await client.PostAsync("/auth/1/oauth2/token", form);
response.EnsureSuccessStatusCode();

using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var accessToken = json.RootElement.GetProperty("access_token").GetString();
```

### Send a request with an OAuth 2.0 token [#send-a-request-with-an-oauth-20-token-oauth-20-authentication]

The following examples assume you have completed step 1 and have an `accessToken` value. The request is the same as for API key authentication, but uses `Bearer` instead of `App` in the header.

```bash
curl -X POST 'https://{baseUrl}/sms/3/messages' \
    -H 'Authorization: Bearer {accessToken}' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
        "messages": [
            {
                "sender": "InfoSMS",
                "destinations": [{ "to": "41793026727" }],
                "content": { "text": "This is a sample message" }
            }
        ]
    }'
```

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

String body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://{baseUrl}/sms/3/messages"))
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "application/json")
    .header("Accept", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<string> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

```csharp
using System.Net.Http.Headers;
using System.Text;

var body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

var client = new HttpClient { BaseAddress = new Uri("https://{baseUrl}") };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.PostAsync("/sms/3/messages", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

NOTE  
The Java and C# [API client libraries](https://www.infobip.com/docs/developer-resources/developer-tools/sdks) support API key authentication only. To use OAuth 2.0, send requests with an HTTP client, as shown in the previous examples.

___

## IBSSO token authentication

IBSSO (Infobip single sign-on) tokens are session-based, meaning tokens expire after a short time. That makes this method more secure, but also requires more maintenance to keep authentication active. This method is typically used in single sign-on scenarios.

- All API requests are authenticated with a session token.
- By default, IBSSO tokens expire after roughly 60 minutes of inactivity.
- If you want to create a new token before the previous one expires, you must first destroy the session.
- To make a session shorter than 60 minutes, destroy it when you no longer need it.

### How to use IBSSO tokens [#how-to-use-ibsso-tokens-ibsso-token-authentication]

1. Call Create session and take the token from the response.
2. Include `IBSSO` and the token in the `Authorization` header: `Authorization: IBSSO {token}`.
3. (Optional) Call Destroy session to end the session before it expires.

### Get an IBSSO token [#get-an-ibsso-token-ibsso-token-authentication]

The following examples call the Create session endpoint and read the token from the response.

```bash
curl -X POST 'https://{baseUrl}/auth/1/session' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{ "username": "{username}", "password": "{password}" }'
```

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.fasterxml.jackson.databind.ObjectMapper;

String body = "{\"username\":\"{username}\",\"password\":\"{password}\"}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://{baseUrl}/auth/1/session"))
    .header("Content-Type", "application/json")
    .header("Accept", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<string> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());

String token = new ObjectMapper().readTree(response.body()).get("token").asText();
```

```csharp
using System.Net.Http.Json;
using System.Text.Json;

var client = new HttpClient { BaseAddress = new Uri("https://{baseUrl}") };

var response = await client.PostAsJsonAsync("/auth/1/session",
    new { username = "{username}", password = "{password}" });
response.EnsureSuccessStatusCode();

using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var token = json.RootElement.GetProperty("token").GetString();
```

### Send a request with an IBSSO token [#send-a-request-with-an-ibsso-token-ibsso-token-authentication]

This request is almost identical to API key authentication. Instead of `App`, you use `IBSSO` in the header.

```bash
curl -X POST 'https://{baseUrl}/sms/3/messages' \
    -H 'Authorization: IBSSO {token}' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
        "messages": [
            {
                "sender": "InfoSMS",
                "destinations": [{ "to": "41793026727" }],
                "content": { "text": "This is a sample message" }
            }
        ]
    }'
```

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

String body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://{baseUrl}/sms/3/messages"))
    .header("Authorization", "IBSSO " + token)
    .header("Content-Type", "application/json")
    .header("Accept", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<string> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

```csharp
using System.Net.Http.Headers;
using System.Text;

var body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

var client = new HttpClient { BaseAddress = new Uri("https://{baseUrl}") };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("IBSSO", token);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.PostAsync("/sms/3/messages", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

NOTE  
The Java and C# [API client libraries](https://www.infobip.com/docs/developer-resources/developer-tools/sdks) support API key authentication only. To use IBSSO tokens, send requests with an HTTP client, as shown in the previous examples.

___

## Basic authentication

Basic authentication works by sending a username and a password in every API request, Base64-encoded and passed with the `Basic` prefix: `Authorization: Basic {base64-encoded-credentials}`. Use it when an API key is not available. For example, the endpoints that create and manage API keys do not accept an API key.

- Built into the HTTP protocol itself. See [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication) on MDN.
- Credentials encoded in Base64 format and separated by a colon.
- Encoded credentials added to the header after `Basic`.

Unlike API keys, where you explicitly assign scopes during key creation, Basic authentication does not use scopes directly. Instead, the roles assigned to the user whose credentials you are using determine the scopes available to a Basic authentication request. For the role-to-scope mapping, see [User roles and API scopes](https://www.infobip.com/docs/developer-resources/authentication-and-access/api-scopes-reference#user-roles-and-api-scopes) in API scopes reference.

IMPORTANT  
Basic authentication is the least recommended method: Base64-encoded credentials are easily decoded back to their original values. For production integrations, use API keys or OAuth 2.0.

### How to use Basic authentication [#how-to-use-basic-authentication-basic-authentication]

Basic authentication **must be enabled** for your user. See [API access](https://www.infobip.com/docs/get-started/account-settings/manage-users#api-access) in Manage users.

1. Concatenate your username and password separated by a colon: `username:password`.
2. Encode the result in Base64.
3. Include `Basic` and the encoded string in the `Authorization` header: `Authorization: Basic {base64-encoded-credentials}`.

### Send a request with Basic authentication [#send-a-request-with-basic-authentication-basic-authentication]

The following examples encode the credentials and send them in the `Authorization` header. The curl example uses already-encoded credentials.

```bash
curl -X POST 'https://{baseUrl}/sms/3/messages' \
    -H 'Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -d '{
        "messages": [
            {
                "sender": "InfoSMS",
                "destinations": [{ "to": "41793026727" }],
                "content": { "text": "This is a sample message" }
            }
        ]
    }'
```

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

String credentials = "{username}" + ":" + "{password}";
String encoded = Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));

String body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://{baseUrl}/sms/3/messages"))
    .header("Authorization", "Basic " + encoded)
    .header("Content-Type", "application/json")
    .header("Accept", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<string> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```

```csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var credentials = "{username}" + ":" + "{password}";
var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));

var body = "{\"messages\":[{\"sender\":\"InfoSMS\",\"destinations\":[{\"to\":\"41793026727\"}],"
    + "\"content\":{\"text\":\"This is a sample message\"}}]}";

var client = new HttpClient { BaseAddress = new Uri("https://{baseUrl}") };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.PostAsync("/sms/3/messages", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

NOTE  
The [API client libraries](https://www.infobip.com/docs/developer-resources/developer-tools/sdks) support API key authentication only. Some libraries accept a username and password in their configuration, but do not send them with requests. To use Basic authentication, send requests with an HTTP client, as shown in the previous examples.

___

## Authentication errors

You receive the `401 Unauthorized` HTTP status code when credentials are missing or incorrect. This applies to all four authentication methods.

```json
{
  "errorCode": "E401",
  "description": "The request lacks valid authentication credentials for the requested resource.",
  "action": "Check the resources and adjust authentication credentials.",
  "violations": [],
  "resources": [
    {
      "name": "API Authentication",
      "url": "/docs/developer-resources/authentication-and-access/api-authentication"
    }
  ]
}
```

Some endpoints can return a previous version of the error:

```json
{
    "requestError": {
        "serviceException": {
            "messageId": "UNAUTHORIZED",
            "text": "Invalid login details"
        }
    }
}
```

### Library exceptions [#library-exceptions-authentication-errors]

When you use an API client library, an error response such as `401 Unauthorized` throws an `ApiException`. The following examples read the status code and response body from the exception. The `smsApi` and `smsRequest` objects come from Use an API client library.

```java
import com.infobip.ApiException;
import com.infobip.model.SmsResponse;

try {
    SmsResponse smsResponse = smsApi.sendSmsMessages(smsRequest).execute();
} catch (ApiException apiException) {
    int statusCode = apiException.responseStatusCode();
    String rawResponseBody = apiException.rawResponseBody();
    var details = apiException.details();
}
```

```csharp
using Infobip.Api.Client;

try
{
    var smsResponse = smsApi.SendSmsMessages(smsRequest);
}
catch (ApiException apiException)
{
    var errorCode = apiException.ErrorCode;
    var errorHeaders = apiException.Headers;
    var errorContent = apiException.ErrorContent;
}
```

___

Related pages

<strong>[Authorization and scopes](https://www.infobip.com/docs/developer-resources/authentication-and-access/authorization-and-scopes)</strong>  
Understand API scopes and how to assign or update them on API keys and user roles.

<strong>[Security best practices](https://www.infobip.com/docs/developer-resources/security/security-best-practices)</strong>  
Guidelines for securing API integrations: authentication, traffic encryption, credential storage, and AIT prevention.

<strong>[API requests and responses](https://www.infobip.com/docs/developer-resources/api-fundamentals/api-requests-and-responses)</strong>  
Conventions, content types, pagination, and bad request handling across the REST API.