# Soracom API Usage Guide

Integrate Soracom services and features into your IoT application.

## Overview

The Soracom API lets you easily integrate Soracom management features and services into your IoT application using conventional HTTP requests.

### Account and Resource Structure

The Soracom API uses SIM-based operations to manage your IoT SIMs and their associated resources. A Soracom account (Operator) may administer multiple SIMs, while each SIM belongs to only one Soracom account.

> [!WARNING]
>
> Depending on your organizational requirements, you may have multiple Soracom accounts. However, there are [restrictions](https://docs.soracom.io/en/services/air/transfer#conditions-and-limitations) with transferring SIMs between Soracom accounts.

In addition, multiple SIMs can be managed together by adding them to a **Group**. Groups can then be used to configure settings for multiple SIMs at the same time. There is no limit to the number of Groups you can create, however a SIM can only belong to one Group at a time, and both the SIM and Group must be administered by the same Soracom account (in other words, you cannot assign a SIM to another Soracom account's group).

## Generating an API Key and Token

When using the Soracom API, authorization is provided by an **API Key** and **Token**. Except for the [Auth:auth](https://docs.soracom.io/en/api#/Auth/auth) API method (used to generate an API Key and Token) and [Auth:issuePasswordResetToken](https://docs.soracom.io/en/api#/Auth/issuePasswordResetToken) (used to reset a Soracom account password), all API methods require an API Key and Token.

API Key and Token pairs are generated when you authenticate as a [Root user or SAM user](https://docs.soracom.io/en/services/account/users-and-roles). Soracom provides the following authentication methods:

- [ID and Password](https://docs.soracom.io/en/developers/soracom-api/#generating-an-api-key-and-token-with-an-id-and-password)
- [AuthKey ID and AuthKey Secret](https://docs.soracom.io/en/developers/soracom-api/#generating-an-api-key-and-token-with-an-authkey-id-and-authkey-secret)

The API Key and Token will allow programmatic API access to your Root user and SAM users.

> [!NOTE]
>
> Handle API Keys and Tokens securely. Never expose them in logs, public repositories, or client-side applications.

## Generating an API Key and Token with an ID and Password

To access the Soracom API, users must authenticate using an API Key and Token. One authentication method is to use an ID and Password, which allows Root users and SAM users to obtain credentials for API access.

This method involves sending a request to the [Auth:auth](https://docs.soracom.io/en/api#/Auth/auth) API endpoint with the required credentials. If Multi-Factor Authentication (MFA) is enabled on your Soracom account, an additional one-time password (OTP) will be required. Upon successful authentication, the API returns an API Key and Token, which can then be used to make further API requests.

This section provides step-by-step instructions on generating an API Key and Token using an ID and Password for both Root users and SAM users.

### For a Root User

Requirements:

- Email address
- Password

> [!WARNING]
>
> An OTP value is also required if the MFA feature is enabled for the Root User.
>
> See [Multi-Factor Authentication](https://docs.soracom.io/en/services/account/mfa) for more information on MFA.

To generate an API Key and Token, call the `Auth:auth` API using one of the following methods. For further details on this API endpoint, see the [Auth:auth](https://docs.soracom.io/en/api#/Auth/auth) API documentation.

```bash
curl -X POST https://g.api.soracom.io/v1/auth \
  -H 'Content-Type: application/json' \
  -d '{
        "email": "sora@soracom.io",
        "password": "my$ecretP@ssw0rd"
      }'
```

Example of a successful response:

```json
{
  "operatorId": "OP0012345678",
  "apiKey": "<MY-API-KEY>",
  "token": "<MY-TOKEN>"
}
```

To generate an API Key and Token with an OTP:

```bash
curl -X POST https://g.api.soracom.io/v1/auth \
  -H 'Content-Type: application/json' \
  -d '{
        "email": "sora@soracom.io",
        "password": "my$ecretP@ssw0rd",
        "mfaOTPCode": "XXXXXX"
      }'
```

You can then use `<MY-API-KEY>` and `<MY-TOKEN>` to call other parts of the Soracom API, ensuring that both are stored in volatile, access-restricted memory so that they remain protected.

See the [Examples](https://docs.soracom.io/en/developers/soracom-api/#examples) section for a reference on calling APIs using an API Key and Token.

### For a SAM User

A SAM (Soracom Access Management) user is a user account that allows organizations to grant controlled access to their Soracom account without sharing the credentials of the Root user. SAM users are created and managed under [Users & Roles](https://docs.soracom.io/en/services/account/users-and-roles) in the Soracom User Console.

Requirements:

- Operator ID
- Username
- Password

To create a password for the SAM user, refer to [Authentication Methods](https://docs.soracom.io/en/services/account/users-and-roles#authentication-methods) for more information.

Note that you can add [Inline Permissions](https://docs.soracom.io/en/services/account/users-and-roles#configuring-inline-permissions) to grant the SAM user access to specific APIs.

> [!WARNING]
>
> An OTP value is required if the [MFA feature](https://docs.soracom.io/en/services/account/users-and-roles#authentication-methods) is enabled for the SAM user.

To generate an API Key and Token:

```bash
curl -X POST https://g.api.soracom.io/v1/auth \
  -H 'Content-Type: application/json' \
  -d '{
        "operatorId": "OPXXXXXXXXXX",
        "userName": "my-sam-user",
        "password": "my$ecretP@ssw0rd"
      }'
```

Example of a successful response:

```json
{
  "operatorId": "OP0012345678",
  "userName": "<MY-SAM-USERNAME>",
  "apiKey": "<MY-API-KEY>",
  "token": "<MY-TOKEN>"
}
```

To generate an API Key and Token with an OTP:

```bash
curl -X POST https://g.api.soracom.io/v1/auth \
  -H 'Content-Type: application/json' \
  -d '{
        "operatorId": "OPXXXXXXXXXX",
        "userName": "my-sam-user",
        "password": "my$ecretP@ssw0rd",
        "mfaOTPCode": "XXXXXX"
      }'
```

You can then use `<MY-API-KEY>` and `<MY-TOKEN>` to call other parts of the Soracom API, ensuring that both are stored in volatile, access-restricted memory so that they remain protected.

See the [Examples](https://docs.soracom.io/en/developers/soracom-api/#examples) section for a reference on calling APIs using an API Key and Token.

## Generating an API Key and Token with an AuthKey ID and AuthKey Secret

Use an AuthKey ID and AuthKey Secret for API authentication without an email or password. Generate them in the User Console, then use them to obtain an API Key and Token for secure API access.

Requirements:

- AuthKey ID
- AuthKey Secret

To generate an API Key and Token:

1. Generate the AuthKey ID and AuthKey Secret from the User Console.

   - For instructions on generating the values for a Root user, please see [Root User AuthKeys](https://docs.soracom.io/en/services/authentication/authkeys#root-user-authkeys).
   - For instructions on generating the values for a SAM user, please see [SAM User AuthKeys](https://docs.soracom.io/en/services/authentication/authkeys#sam-user-authkeys).

2. Generate an API Key and Token.

   ```bash
   curl -X POST https://g.api.soracom.io/v1/auth \
     -H 'Content-Type: application/json' \
     -d '{
           "authKeyId": "keyId-XXXXXXXXXXXXXXXXXXXXXXXXX",
           "authKey": "secret-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
         }'
   ```

> [!NOTE]
>
> Note that `authKeyId` refers to the AuthKey ID and `authKey` refers to the AuthKey Secret.

Example of a successful response:

```json
{
  "operatorId": "OP0012345678",
  "apiKey": "keyId-XXXXXXXXXXXXXXXXXXXXXXXXX",
  "token": "<MY-TOKEN>"
}
```

You can now use `<MY-API-KEY>` and `<MY-TOKEN>` to call other parts of the Soracom API, ensuring that both are stored in volatile, access-restricted memory so that they remain protected.

See the [Examples](https://docs.soracom.io/en/developers/soracom-api/#examples) section for a reference on calling APIs using an API Key and Token.

## Token Timeout

To reduce any potential security risk, each API Key and Token pair is effective for only a temporary period, known as its TTL. After an API Key and Token pair expires, it cannot be used again. Once an API Key and Token pair expire, simply call the _auth_ API method again to receive a new pair.

> [!WARNING]
>
> By default, the TTL of an API Key and Token pair is 86,400 seconds (24 hours).

When implementing the Soracom API into your application, we recommend specifying a TTL that matches your application requirements. For example, for applications where a device only needs to send a small amount of data, a TTL of a few minutes is typically adequate. In other applications where human interaction or input is required, a longer TTL of 30-60 minutes may be appropriate. Setting an API Key and Token pair TTL that matches your application requirements will further reduce any security risk.

When generating an API Key and Token pair, a minimum of 180 seconds (3 minutes) and a maximum of 172,800 seconds (48 hours) can be set for the TTL.

## Coverage Types and API Endpoints

Just as Soracom IoT SIMs differ primarily by **Global** or **Japan**-only coverage, Soracom API access is also split into two corresponding API endpoints:

| <br>Coverage Type | Global | Japan |
| - | - | - |
| <br>SIM Type | plan01s plan01s - LDV plan-US plan-US-max plan-US-NA planP1 planM1 planV1 planX1 planX2 planX3 planX3-EU planNT1 | plan-D plan-DU plan-K plan-K2 plan-KM1 |
| <br>API Endpoint | `https://g.api.soracom.io` | `https://api.soracom.io` or `https://jp.api.soracom.io` |

Regardless of your IoT SIM's region, you can authenticate your Soracom account to obtain an API Key and Token from any API endpoint. In addition, an authorized API Key and Token can be used with any API endpoint, regardless of which endpoint was used to generate the pair.

For all other API methods, ensure that you use the endpoint appropriate for your Soracom account's coverage type or IoT SIM's coverage area.

> [!NOTE]
>
> To call the Soracom API, the API endpoint must be reachable by the device. Therefore, to call the API from a SIM located inside a Virtual Private Gateway, the VPG's Internet Gateway must be enabled and the Outbound Filter must be disabled.

### Checking Coverage Types

In some cases, it may be useful to programmatically check the coverage types (Global and/or Japan) that are available for your Operator account.

When generating an API Key and Token, the Token itself is a JSON Web Token (JWT) which contains information about the coverage types available to your account.

To retrieve the coverage types, parse and decode the Token to get its payload. The payload contains an `operator.coverageTypes` key, which is an array containing the coverage types available to your Soracom account (Operator).

The following JavaScript code retrieves the coverage types array:

```js
// "token" contains the string content of the API Token returned from /v1/auth
var parts = token.split('.');
var claims = JSON.parse(atob(unescape(encodeURIComponent(parts[1]))));
console.log(claims.operator.coverageTypes); // ["jp", "g"]
```

- `"g"` indicates that the Global coverage type is enabled for the account
- `"jp"` indicates that the Japan coverage type is enabled for the account

> [!NOTE]
>
> When parsing the API Token, make sure to verify its signature to ensure the Token has not been compromised.

## Dates and Timestamps

All dates and times used in the Soracom API are based on UTC (Coordinated Universal Time) +00:00.

In some instances, Unix epoch time (seconds elapsed since January 1, 1970) or a date format such as `YYYYMMDD` are used. These timestamps are also based on UTC +00:00.

When calling an API that requires a date or time input, or when parsing an API response that includes a date or time value, ensure that you convert from your local timestamp to UTC +00:00 (and vice versa).

## Rate Limits

The Soracom API sets a maximum number of requests per minute, or a "rate limit", for calls made to the same relational API group.

When you call the API, the following HTTP response headers will be included that provide more information about rate limiting:

| HTTP Response Header | Explanation |
| - | - |
| `x-soracom-ratelimit-limit` | The maximum number of times per minute that APIs in the called API's group can be called. The same value will be returned regardless of the number of calls made to this group. |
| `x-soracom-ratelimit-remaining` | The remaining number of times that APIs in the called API's group can be called this minute. When the maximum number of requests is reached, the value becomes `0` and an `HTTP 429 Too Many Requests` error will be returned. |
| `x-soracom-ratelimit-seconds-before-refresh` | The number of seconds remaining until the one minute period elapses and the rate limit is refreshed. |

For example, the following APIs belong to the `Sim` group, and therefore share a rate limit:

- `Sim:getSim`
- `Sim:listSims`
- `Sim:listSimStatusHistory`

Therefore, if the rate limit is exceeded when calling `Sim:getSim` and an `HTTP 429 Too Many Requests` error is returned, additional calls to `Sim:listSims` or `Sim:listSimStatusHistory` APIs will also be rate-limited and return the same HTTP `429 Too Many Requests` error. It is recommended to implement an exponential backoff strategy or delay subsequent API calls to avoid further rate limiting.

For ease of use, Soracom's [API Reference page](https://docs.soracom.io/en/api) organizes API calls by these relational groups.

> [!NOTE]
>
> While most APIs are limited by group, the following API calls are limited by caller IP address:
>
> Auth
>
> - `Auth:auth`
> - `Auth:issuePasswordResetToken`
> - `Auth:verifyPasswordResetToken`
>
> Device
>
> - `https://api.soracom.io/v1/devices/{device_id}/publish`
>
> Operator
>
> - `Operator:issueMFARevokingToken`
> - `Operator:verifyMFARevokingToken`
>
> Email
>
> - `Email:verifyAddEmailToken`

> [!WARNING]
>
> The rate limit is set at a level that is considered acceptable for normal use. If you need a higher rate limit, please [contact Soracom Support](https://docs.soracom.io/en/services/account/support#creating-a-support-request) and provide the following information:
>
> - The API call you would like to increase the limit of.
> - The estimated number of requests per minute required.
> - Details about your use case and why it requires a higher limit.
>
> Our engineering team will then evaluate the possibility of a rate limit increase.

## Handling Pagination

Some list API responses are limited to a certain number of returned items. When more items are available, the response may include pagination information in the `link` header and/or the `x-soracom-next-key` header. The `last_evaluated_key` value identifies where the next request should continue.

Some list APIs support a `limit` parameter that controls the maximum number of items returned in a single response.

> [!WARNING]
>
> The [Soracom CLI](https://docs.soracom.io/en/developers/soracom-cli) can use the `--fetch-all` flag to perform pagination automatically and retrieve all results for supported commands. For example, to retrieve all SIMs:
>
> ```bash
> soracom sims list --fetch-all
> ```
>
> For more information, see [Getting a List of SIMs](https://docs.soracom.io/en/developers/soracom-cli#getting-a-list-of-sims).

To retrieve a list of SIMs, use the [listSims](https://docs.soracom.io/en/api#!/Sim/listSims) API:

```bash
curl -i -X GET \
  -H "X-Soracom-API-Key: $X_SORACOM_API_KEY" \
  -H "X-Soracom-Token: $X_SORACOM_TOKEN" \
  https://g.api.soracom.io/v1/sims
```

The response includes the following headers before the response body.

```json
{
  "date": "Tue, 06 Jun 2023 07:04:19 GMT",
  "content-type": "application/json",
  "cache-control": "no-cache",
  "link": "</v1/sims?last_evaluated_key=1234567890123456780>; rel=next",
  "vary": "Accept-Encoding",
  "x-soracom-next-key": "1234567890123456780",
  "x-soracom-ratelimit-limit": "1000",
  "x-soracom-ratelimit-remaining": "999",
  "x-soracom-ratelimit-seconds-before-refresh": "60"
}
```

In this example, the `x-soracom-next-key` header contains the key value that can be passed as the `last_evaluated_key` query parameter in the next request. The `link` header also includes a URI reference for the next request. In this example, the URI reference contains the path and query string. The following request uses `1234567890123456780` from `x-soracom-next-key` as the `last_evaluated_key` value to retrieve the next page of results:

```bash
curl -i -X GET \
  -H "X-Soracom-API-Key: $X_SORACOM_API_KEY" \
  -H "X-Soracom-Token: $X_SORACOM_TOKEN" \
  https://g.api.soracom.io/v1/sims?last_evaluated_key=1234567890123456780
```

This returns additional data. If another page exists, the response includes pagination information in the `x-soracom-next-key` header, the `link` header, or both.

```json
{
  "date": "Tue, 06 Jun 2023 07:11:25 GMT",
  "content-type": "application/json",
  "cache-control": "no-cache",
  "link": "</v1/sims?last_evaluated_key=1234567890123456781>; rel=next",
  "vary": "Accept-Encoding",
  "x-soracom-next-key": "1234567890123456781",
  "x-soracom-ratelimit-limit": "1000",
  "x-soracom-ratelimit-remaining": "998",
  "x-soracom-ratelimit-seconds-before-refresh": "46"
}
```

Repeat the same process until neither the `link` header nor the `x-soracom-next-key` header is returned. When neither header is returned, you have retrieved the last page.

## Error Messages

When an error occurs, the API will return an error message in a unified format.

```json
{
  "code": "ABC1234",
  "message": "Description of the error"
}
```

> [!NOTE]
>
> If an error occurs during an API call prior to the request reaching the API server, an error message may not be returned.

When contacting Soracom Support in order to troubleshoot API usage, please provide the error **code** if available.

By default, the **message** body will appear in English. However, the locale can be controlled by specifying an `X-Soracom-Lang` header in the API call. Currently the supported error message locales are:

- `X-Soracom-Lang: en` - English
- `X-Soracom-Lang: ja` - Japanese

## Examples

### Retrieve a List of SIMs

Use the [listSims](https://docs.soracom.io/en/api#!/Sim/listSims) API to retrieve the list of SIMs in the account:

**Global**

```bash
curl -X GET \
  -H "X-Soracom-API-Key: <MY-API-KEY>" \
  -H "X-Soracom-Token: <MY-TOKEN>" \
  https://g.api.soracom.io/v1/sims
```

**Japan**

```bash
curl -X GET \
  -H "X-Soracom-API-Key: <MY-API-KEY>" \
  -H "X-Soracom-Token: <MY-TOKEN>" \
  https://api.soracom.io/v1/sims
```

Response (200 OK):

```json
[
  {
    "simId": "8942310000012345678",
    "imsi": "295050012345678",
    //...
  },
  {
    "simId": "8942310000012345679",
    "imsi": "295050012345679",
    //...
  },
  //...
]
```

### Update a SIM's Speed Class

To update a SIM's speed class, use the [updateSimSpeedClass](https://docs.soracom.io/en/api#!/Sim/updateSimSpeedClass) API with the SIM ID:

**Global**

```bash
curl -X POST https://g.api.soracom.io/v1/sims/<SIM-ID>/update_speed_class \
  -H "X-Soracom-API-Key: <MY-API-KEY>" \
  -H "X-Soracom-Token: <MY-TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{
        "speedClass": "s1.fast"
      }'
```

**Japan**

```bash
curl -X POST https://api.soracom.io/v1/sims/<SIM-ID>/update_speed_class \
  -H "X-Soracom-API-Key: <MY-API-KEY>" \
  -H "X-Soracom-Token: <MY-TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{
        "speedClass": "s1.fast"
      }'
```

Response (200 OK):

```json
{
  "imsi": "295050012345678",
  "speedClass": "s1.fast",
  //...
}
```

For a complete list of API methods available, please refer to the [API Reference](https://docs.soracom.io/en/api).
