M360 Customer API documentation
Customer API

API integration (v2)

To access the M360 Customer API you have to first activate it by logging in to your dashboard and setting the API status to Testing or Live. If you wish to disable your API access later, you can set the API status on your dashboard to Disabled. To enable and use your M360 Customer API account you will need a valid and active M360 licence.

Testing mode

Calling any API endpoint in Testing mode will never cause any data changes. Also, responses in this mode will be randomly generated but syntactically correct data structures. You can use this mode to safely experiment with the M360 Customer API and test your integration. Once you have tested your system and feel confident you can switch to Live mode.

Most endpoints can be called in testing mode even if your API is live, by providing the optional testing request parameter and setting its value to true. This will result in exactly the same behaviour and response as if your API was in Testing mode.

Request structure

To call any M360 Customer API endpoint just issue an HTTP POST request with an application/json content type to the URL of the endpoint. The body of the request should be a simple JSON object containing the input parameters shown at the endpoint's documentation.

Authentication

With every /v2 API request you must provide the correct authentication information which is different from your M360 login username and password. You need to use an Authorization header, with a bearer token. Your bearer token is simply your authCode and authToken, concatenated with a - (dash) character:

POST https://m360soft.com/api/customer/v2/getHistory

User-Agent: curl/7.54.1
Authorization: Bearer a167b9ae-948d-490c-9995-932984fbb223-f3e1016b87d4d11d7994d39050ac5d05ef475bc422131b0916337f0c0a424be3

{
    "limit": 100
}

The authCode parameter is the unique identifier of your M360 Customer API account and the authToken is the secret key of it. You can access both of them on your dashboard at the API information section. For safety reasons the authToken can only be viewed or regenerated after providing your M360 password (the one you use to log in to your dashboard).

Response structure

Every M360 Customer API response will be a JSON object containing two properties: data and meta.

The data object will be populated with the specific information that the called API endpoint provides, so its structure and content varies between endpoints. For example a successful but empty /v2/getHistory response will be like this:

{
    "data": {
        "records": [],
        "hasMore": false
    },
    "meta": {
        "success": true
    }
}

The meta object has a more rigid structure and always contains the boolean status property success, and in case of any error the errors object. The errors object has 3 properties: code, title and details. The code is the ID of the error, while the title is a human-readable description of it. If you would like to handle specific errors, always build your logic on the code error property instead of the title.

Example error response:

{
    "data": [],
    "meta": {
        "success": false,
        "errors": {
            "code": "auth:forbidden",
            "title": "Access forbidden with the given credentials",
            "details": []
        }
    }
}

Rate limiting

There is a limit on the number of requests you can make to any Customer API endpoints, which is based on your active licences and upgrades. You can make 1 request / second / workstations. So if you have a Professional Licence with 2 additional workstation upgrades then you are limited to a total of 5 requests / second. If you encounter a rate limit error, you will receive a 429 Too Many Requests HTTP status code, and a JSON error response containing the effective rate limit of your account:

{
    "data": [],
    "meta": {
        "success": false,
        "errors": {
            "code": "customer_api:too_many_requests",
            "title": "Too many requests",
            "details": {
                "maximumRequestsPerSecond": 5
            }
        }
    }
}

Versioning and backward compatibility

The M360 Customer API is a versioned API. The current version is v2. We will support the previous versions for a reasonable time, but we encourage you to always use the latest version of the API. We will announce the deprecation of a version at least 6 months before the end of support.

We introduce new versions of the API when we make breaking changes to the existing endpoints or the API in general. Between versions, we may introduce non-breaking changes, such as new endpoints or new properties in the response objects. We will document these changes in the changelog.

Breaking changes

A breaking change is a change that can cause existing integrations to stop working and may require changes to the client code.

Examples of breaking changes include:

  • Removing, renaming or changing the type of a request parameter or response property.
  • Removing functionality from an endpoint.
  • Adding stricter validation for a field.
  • Global changes like requiring a new authentication method.

Non-breaking changes

A non-breaking change is a change that does not require changes to the client code.

Examples of non-breaking changes include:

  • Adding a new endpoint.
  • Adding a new property to a response object.
  • Adding a new optional request parameter.
  • Adding a new error code.
  • Adding a new value to an existing enumeration.
  • Changing the order of properties in a response object.

Migrating from v1 API

Migrating from the v1 to the v2 version of the M360 Customer API should be straightforward, but there are some major changes you need to be aware of.

Authentication changes

The v2 API uses a different authentication method. You need to use an Authorization header with a bearer token instead of the authCode and authToken request parameters. The bearer token is simply your authCode and authToken, concatenated with a - (dash) character.

getHistory endpoint changes

The /getHistory endpoint has been significantly changed, both in the request and response structure.

Input parameters:

  • Formerly, in the v1 API, the imei filter accepted a serial number too. In the v2 API, there is a separate serial filter for this purpose. The imei filter now only accepts IMEI numbers.
  • The imei filter is now an array instead of a single string. You can provide and search for multiple IMEI numbers in a single request.
  • The m360id filter is now an array instead of a single string. You can provide and search for multiple M360 IDs in a single request.
  • There is a new customId filter which allows you to search for devices using the custom ID you have saved as sticky data for the device.
  • The marketingName filter was renamed to friendlyName to reflect the name change of the relevant property in the response object.
  • Now you can provide the timeZone parameter to get the timestamps in the response in the specified time zone. The default is UTC.
  • There is a calculateTotalCount parameter which allows you to request the calculation of the number of matching rows. The default value is false.

Response data:

  • The totalCount property is not populated in the response object by default. You can use the hasMore property to check if there are more records available or if you need this value you can set the calculateTotalCount request parameter to true. But keep in mind that even if you request the calculation of the number of matching rows, the total count will never be more than 10000. If you have more records, please use filtering to get a smaller result set.

DeviceSession object:

  • The marketingName and alternativeMarketingNames properties were renamed to friendlyName and alternativeFriendlyNames respectively in the response object. However, there is a new marketingName property, which is different from the friendlyName. The marketingName property contains the original marketing name of the device, without color or storage size information. At the moment this value is only available for Apple devices.
  • The imei1 property was renamed to imei.
  • The imei3 property was removed.
  • The batteryHealth property was removed.
  • The historicalStickyData property was renamed to stickyData.
  • The blacklistChecks property was removed. Instead of this, there is a new blacklistCheckResult property which contains the result of the last IMEI blacklist check at the time of the session.
  • The reports property was renamed to diagnosticsReports.
  • Multiple other new properties were added to the DeviceSession response object: brandAccounts, simLock, soc, brand, ecid, internalStorage, iosSalesRegion, MDMState, batteryCycles, batteryDesignCapacity, fullChargeCapacity, rooted, secureLocked, memoryCard, iosRegulatoryModel, deviceColor, iosJailbreak, encryptionState, encryptionType, deviceExpense, gradingPhotos, simLockCheckResult.

Device object:

  • The id property was removed. Instead you can use the m360id property to identify the device.
  • Multiple new properties were added to the Device response object: actualGradingResult, actualGradingPhotos, actualDeviceExpense.

StickyData object:

  • The customerInfo property was removed.
  • Instead of the customerInfo there is a new client property. The client object is either a Company or a Person object, depending on the type of the client. You can use the type property to determine the type of the client.

DiagnosticsResult object:

  • The clientTime property was renamed to finishTime.
  • All TestResult type properties were removed. Instead, there is a new tests property which contains the test results in an array.
  • The individual tests are now DiagnosticsResultTest objects, instead of TestResult objects.

DiagnosticsResultTest object:

  • This object corresponds to the former TestResult objects, but there are some differences.
  • The new testId property now holds the ID of the test, instead of the former approach where the test ID was the key of the object.
  • The new result property is similar to the former status property, but the possible values are different. The new possible values NA, Passed, Failed, and Skipped.
  • The new details property is a list of DiagnosticsResultDetail objects, which hold details of test results.

DiagnosticsResultDetail object:

  • The purpose of this new object is similar to the details property of the TestResult object of the v1 API, but its structure is different. It holds a single, additional detail of a diagnostics test. For example the battery test can provide details about the original capacity of the battery, temperature, voltage, etc. In the v1 API these were all different keys of the details object, now these are provided as individual details objects. For example:

    v1 API:

      "batteryHealth": {
          "status": "passed",
          "details": {
              "cycles": "254",
              "designCapacityCapacity": "4395 mAh"
            }
      }

    v2 API:

      {
          "testId": "Battery",
          "result": "Passed",
          "details": [
              {
                  "context": "BatteryOriginalCapacity",
                  "title": "Original Capacity",
                  "result": "NA"
                  "value": "4395 mAh"
              },
              {
                  "context": "BatteryCycles",
                  "title": "Battery Cycles",
                  "result": "NA"
                  "value": "254"
              }
          ]
      }
  • The following table provides a mapping between the old details keys and the new context IDs:

Test Old key New context ID
Battery temperature BatteryTemperature
Battery voltage BatteryVoltage
Battery technology BatteryTechnology
Battery designCapacity BatteryOriginalCapacity
Battery fullCapacity BatteryCurrentCapacity
Battery cycles BatteryCycles
Battery batteryDrainPercent BatteryDrainPercentLost
Storage total StorageTotal
Storage free StorageFree
Storage used StorageUsed

OemCheckResult object:

  • This object has a new isAuthentic flag that tells whether the device is authentic or not.
  • The check results of the individual device parts are now provided as a list of OemCheckResultPart objects in the result.
  • You can use the id property of the OemCheckResultPart object to identify the part, instead of the old method of using the key of the object.
  • Also, a name property was added to the object to provide a human-readable name of the part.

GradingResult object:

  • The clientTime property was renamed to modificationTimestamp.
  • The case property was renamed to phoneCase.
  • The cover property was renamed to back.

BlacklistCheckResult object:

  • This object replaces the BlacklistCheck object of the v1 API. It contains the result of the last IMEI blacklist check at the time of the session. Only finished blacklist checks are included in the response. Because of this, the status property was removed.