> ## Documentation Index
> Fetch the complete documentation index at: https://developers.mioesim.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Java integration guide for the MIOeSIM API

> Authenticate with MIOeSIM, compute HMAC-MD5 request signatures, and make API calls from Java using Apache Commons Codec and the Jodd HTTP client.

This guide walks you through adding the required dependencies, computing the request signature, logging in to obtain a session token, and making authenticated API calls — all in Java.

## Dependencies

Add the following dependencies to your `pom.xml`:

```xml pom.xml theme={null}
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

<dependency>
    <groupId>org.jodd</groupId>
    <artifactId>jodd-http</artifactId>
    <version>6.0.9</version>
</dependency>
```

* **Apache Commons Codec** provides the `DigestUtils.md5()` and `Hex.encodeHexString()` utilities used to compute the signature.
* **Jodd HTTP** is a lightweight HTTP client used to send form-encoded `POST` requests.

## Computing the signature

Every request to the MIOeSIM API requires a `sign` parameter. Compute it with the `createSign` method below.

```java Sign.java theme={null}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

public static String createSign(Map<String, Object> map) throws Exception {
    final String sign_key = "1234567890qwertyuiopasdfghjklzxc";

    // Remove "sign" if already present — it must not be part of the input
    map.remove("sign");

    // Format each parameter as "key=value"
    List<String> arrayList = new ArrayList<String>();
    for (String item : map.keySet()) {
        arrayList.add(item + "=" + map.get(item));
    }

    // Sort alphabetically and concatenate
    Collections.sort(arrayList);
    StringBuffer buffer = new StringBuffer();
    for (String string : arrayList) {
        buffer.append(string);
    }

    // Append the secret key, then MD5-hash the UTF-8 bytes
    String content = buffer + sign_key;
    byte[] data = content.getBytes("UTF-8");
    return Hex.encodeHexString(DigestUtils.md5(data));
}
```

The method:

1. Removes `sign` from the parameter map so it is never included in the input string.
2. Formats each remaining parameter as `key=value` and sorts them alphabetically.
3. Concatenates the sorted strings, appends your secret key, and returns the lowercase MD5 hex digest.

<Warning>
  Never include your secret key in client-side code, public repositories, or logs. Treat it like a password.
</Warning>

## Logging in

Call `POST /api_order/login` to exchange your phone number and password for a session token. The login request itself must include a valid `sign`.

```java Login.java theme={null}
import java.util.HashMap;
import java.util.Map;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import net.sf.json.JSONObject;

public static String testLogin() throws Exception {
    Map<String, Object> paramMap = new HashMap<String, Object>();
    paramMap.put("phonenumber", "YOUR_PHONE_NUMBER");
    paramMap.put("password", "YOUR_PASSWORD");

    // Compute the signature before adding it to the map
    String sign = createSign(paramMap);
    paramMap.put("sign", sign);

    HttpResponse responseData = HttpRequest
        .post("https://bpm.mioesim.com/api_order/login")
        .form(paramMap)
        .send();

    String postData = responseData.bodyText();
    JSONObject parseObject = JSONObject.fromObject(postData);
    String token = JSONObject.fromObject(parseObject.get("data"))
        .get("token")
        .toString();

    return token;
}
```

A successful response returns a token in the `data` field:

```json theme={null}
{
  "code": 1,
  "message": "Successful",
  "data": {
    "token": "29281-9EFE5E410BEF5300DD15E3830BD65601"
  }
}
```

Pass the returned token to every subsequent API call.

## Making authenticated API calls

After login, include both `token` and `sign` on every request. The example below calls `GET /api_esim/getSkus` to retrieve available eSIM packages.

```java GetSkus.java theme={null}
import java.util.HashMap;
import java.util.Map;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;

public static String getSkus(String token) throws Exception {
    Map<String, Object> paramMap = new HashMap<String, Object>();
    paramMap.put("token", token);

    String sign = createSign(paramMap);
    paramMap.put("sign", sign);

    HttpResponse response = HttpRequest
        .get("https://bpm.mioesim.com/api_esim/getSkus")
        .query(paramMap)
        .send();

    return response.bodyText();
}
```

Build the parameter map with `token` first, compute `sign` from that map, then add `sign` to the map before sending the request.

<Note>
  Tokens are valid for **2 hours**. Store the token and its issue time, then re-authenticate before the token expires rather than calling login on every request. A refresh interval of 90 minutes works well in practice.
</Note>

<Tip>
  Replace `"YOUR_PHONE_NUMBER"` and `"YOUR_PASSWORD"` with your actual MIOeSIM account credentials before running the code.
</Tip>
