sdk-java-client-okhttp
Used in:
components
- OverviewOverview
- VersionsVersions
- DependentsDependents
- DependenciesDependencies
<dependency> <groupId>com.m3ter</groupId> <artifactId>sdk-java-client-okhttp</artifactId> <version>0.2.0-alpha</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- This module was also published with a richer model, Gradle metadata, --> <!-- which should be used instead. Do not delete the following line which --> <!-- is to indicate to Gradle or any Gradle module metadata file consumer --> <!-- that they should prefer consuming it instead. --> <!-- do_not_remove: published-with-gradle-metadata --> <modelVersion>4.0.0</modelVersion> <groupId>com.m3ter</groupId> <artifactId>sdk-java-client-okhttp</artifactId> <version>0.2.0-alpha</version> <name>m3ter API</name> <description>If you are using Postman, you can: - Use the **Download** button above to download the m3ter Open API spec JSON file and then import this file as the **m3ter API Collection** into your Workspace. See [Importing the m3ter Open API](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls#importing-the-m3ter-open-api) in our main user Documentation for details. - Copy this link: [m3ter-Template API Collection](https://www.datocms-assets.com/78893/1672846767-m3ter-template-api-collection-postman_collection.json) and use it to import the **m3ter-Template API Collection** into your Workspace. See [Importing the m3ter Template API Collection](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls#importing-the-m3ter-template-api-collection) in our main user Documentation for details. --- # Introduction The m3ter platform supports two HTTP-based REST APIs returning JSON encoded responses: - The **Ingest API**, which you can use for submitting raw data measurements. _(See the [Submit Measurements](https://www.m3ter.com/docs/api#tag/Measurements/operation/SubmitMeasurements) endpoint in these API Reference Docs.)_ - The **Config API**, which you can use for configuration and management. _(All other endpoints in these API Reference Docs.)_ ## Authentication and Authorization Our APIs use an industry-standard authorization protocol known as the OAuth 2.0 specification. OAuth2 supports several grant types, each designed for a specific use case. m3ter uses the following two grant types: - **Authorization Code**: Used for human login access via the m3ter Console. - **Client Credentials**: Used for machine-to-machine communication and API access. Complete the following flow for API access: 1. **Create a Service User and add Permissions**: Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. 2. **Generate Access Keys**: In the Console, open the _Overview_ page for the Service User by clicking on the name. Generate an **Access Key id** and **Api Secret**. Make sure you copy the **Api Secret** because it is only visible at the time of creation. See [Service Authentication](https://www.m3ter.com/docs/guides/authenticating-with-the-platform/service-authentication) for detailed instructions and an example. 3. **Obtain a Bearer Token using Basic Auth**: We implement the OAuth 2.0 Client Credentials Grant authentication flow for Service User Authentication. Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. _See examples below._ 4. **Bearer Token Usage**: Use the HTTP 'Authorization' header with the bearer token to authorise all subsequent API requests. > Warning: The Bearer Token is valid for 18,000 seconds or 5 hours. When the > token has expired, you must obtain a new bearer token. Below are two examples for obtaining a Bearer Token using Basic Auth: the first in cURL and the second as a Python script. ### cURL Example 1. Open your terminal or command prompt. 2. Use the following `cURL` command to obtain a Bearer Token: ```bash curl -X POST https://api.m3ter.com/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u your_access_key_id:your_api_secret \ -d 'grant_type=client_credentials' ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. 3. Run the command, and if successful, it will return a JSON response containing the Bearer Token. The response will look like this: ```json { "access_token": "your_bearer_token", "token_type": "Bearer", "expires_in": 18000 } ``` You can then use the Bearer Token _(the value of `"access_token"`)_ for subsequent API calls to m3ter. ### Python Example 1. Install the `requests` library if you haven't already: ```bash pip install requests ``` 2. Use the following Python script to obtain a Bearer Token: ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. 3. Run the script, and if successful, it will print the Bearer Token. You can then use this Bearer Token for subsequent API calls to m3ter. ## Submitting Personally Identifiable Information (PII) **IMPORTANT!** Under the [Data Processing Agreement](https://www.m3ter.com/docs/legal/dpa), the only fields permissible for use to submit any of your end-customer PII data in m3ter are the `name`, `address`, and `emailAddress` fields on the **Account** entity - see the details for [Create Account](https://www.m3ter.com/docs/api#operation/PostAccount). See also section 4.2 of the [Terms of Service](https://www.m3ter.com/docs/legal/terms-of-service). ## Error Codes The APIs return standard HTTP response codes to indicate request success or failure. - `200` code indicates success. - `4xx` codes are failures due to problems with the request _(client side errors)_. - `5xx` codes indicate valid API requests and the failure is on the server side. See [HTTP Error Codes](https://www.m3ter.com/docs/guides/m3ter-apis/http-error-codes) for examples and more information. ## Rate and Payload Limits ### Config API Request Rate Limits - **Source IP Address.** Individual host machines can send up to 20,000 requests over a rolling 5-minute period. _(An average of 66 requests per second)._ - **m3ter Organization** Each m3ter Organization can send a maximum of 50 requests per second from any number of source IP addresses. If you exceed either of these rate limits, requests are throttled and an HTTP 429 _(Too Many Requests)_ error response is returned: - **Source IP address rate limit** - 429 is returned until the total number of requests in the rolling 5-minute period drops below 20,000. - **m3ter Organization rate limit** - 429 is returned for the remainder of the second in which throttling has occurred. See [Config API Limits](https://www.m3ter.com/docs/guides/m3ter-apis/config-api-limits) for more information. ### Data Explorer API Request Rate Limits As part of the Config API, requests made to the Data Explorer are subject to tighter request rate limits: - **Generally** 1 request per second. - **Burst** 10 requests per second. If you exceed either of these rate limits, requests are throttled and an HTTP 429 (Too Many Requests) error response is returned. **Note: Burst limit for Data Explorer requests?** We allow short bursts of higher TPS to allow us to accommodate occasional spikes. For example, if the sustained rate is 50 TPS, we might set a bucket capacity (N) of 150. This means that you can do up to 150 TPS for 1s (and empty the bucket), but in the next second you'll only be able to do 50 TPS because that is all that has been refilled. If requests drop below 50 TPS for a period of time, the bucket will refill back up to full capacity allowing another spike. This is usually referred to as "burst capacity". ### Ingest API Request Rate and Payload Limits #### Request Rate Limits - **Source IP Address.** Individual host machines can send up to 5,000 requests over a rolling 5-minute period. _(An average of 16 requests per second)_. - **m3ter Organization.** Each m3ter Organization can send a maximum of 50 requests per second from any number of source IP addresses. If you exceed either of these rate limits, requests are throttled and an HTTP 429 _(Too Many Requests)_ error response is returned: - **Source IP address rate limit** - 429 is returned until the total number of requests in the rolling 5-minute period drops below 5,000. - **m3ter Organization rate limit** - 429 is returned for the remainder of the second in which throttling has occurred. #### Payload Limit For the Ingest API, the maximum request payload size allowed is 512KB. If you exceed this request payload limit, then you'll receive a 403 (Forbidden) error response. See [Ingest API Limits](https://www.m3ter.com/docs/guides/m3ter-apis/ingest-api-limits) for more information. ## Pagination **List Endpoints** API endpoints that have a List resources request support cursor-based pagination - for example, the `List Accounts` request. These List calls support pagination by taking the two parameters `pageSize` and `nextToken`. The response of a List API call is a single page list. If the `nextToken` parameter is not supplied, the first page returned contains the newest objects chronologically. Specify a `nextToken` to retrieve the page of older objects that occur immediately after the last object on the previous page. Use `pageSize` to limit the list results per page, typically this allows up to a maximum of 100 or 200 per page. **Search Endpoints** API endpoints that have a Search resources request support cursor-based pagination - for example, the `Search Accounts` request. These Search calls support pagination by taking the two parameters `pageSize` and `fromDocument`. The response of a Search API call is a single page list. If the `fromDocument` parameter is not supplied, the first page returned contains the newest objects chronologically. Specify a `fromDocument` to retrieve the page of older objects that occur immediately after the last object on the previous page. Use `pageSize` to limit the list results per page, typically this allows up to a maximum of 100 or 200 per page. Default is 10. ## Changelog Check out the latest API features, updates, and functionality by looking in the API Updates subsection of the [m3ter Changelog](https://www.m3ter.com/docs/changelog). --- API Quick Start This API Quick Start section provides an entry point to using the m3ter APIs. The example given takes you through the steps of first authenticating with the m3ter platform then going on to retrieve a list of Accounts for your Organization. Code examples are provided in Python, JavaScript, C++, and command line HTTP via `cURL`. See also [Getting Started with API Calls](https://www.m3ter.com/docs/guides/m3ter-apis/getting-started-with-api-calls) for more on using our API with examples. ## Step 1: Create a Service User and add Permissions Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. ## Step 2: Generate Access Keys In the Console, open the **Service Users Details** page for the Service User by clicking on the Service User **NAME**. Generate an **Access Key id** and **Api Secret**. Make sure to copy the **Api Secret** as it is only visible at the time of creation. For further guidance on these two steps, see [Creating and Configuring Service Users](https://www.m3ter.com/docs/guides/organization-and-access-management/managing-users/creating-and-configuring-service-users) in our main user Documentation. ## Step 3: Install Dependencies (if applicable) ### Python Install the `requests` library: ```bash pip install requests ``` ### JavaScript Install the `axios` library: ```bash npm install axios ``` ### C++ Install the `libcurl` and `jsoncpp` libraries. For Windows based systems with `vcpkg` package manager installed: ```bash vcpkg install curl[openssl] jsoncpp ``` For Debian based Linux operating systems: ```bash sudo apt-get install libcurl4-openssl-dev libjsoncpp-dev ``` ## Step 4: Obtain a Bearer Token using Basic Auth Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. ### cURL ```bash curl -X POST https://api.m3ter.com/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -u your_access_key_id:your_api_secret \ -d 'grant_type=client_credentials' ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the command, and if successful, it will return a JSON response containing the Bearer Token. ### Python ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ### JavaScript ```javascript const axios = require("axios"); const btoa = require("btoa"); const accessKeyId = "your_access_key_id"; const apiSecret = "your_api_secret"; const basicAuth = btoa(`${accessKeyId}:${apiSecret}`); const url = "https://api.m3ter.com/oauth/token"; const options = { method: "POST", url: url, headers: { Authorization: `Basic ${basicAuth}`, "Content-Type": "application/json", }, data: { grant_type: "client_credentials", }, }; axios(options) .then((response) => console.log("Access Token:", response.data.access_token)) .catch((error) => console.error("Error:", error)); ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ### C++ ```C++ #include <iostream> #include <string> #include <curl/curl.h> #include <json/json.h> #include <sstream> #include <cstdlib> #include <base64.h> size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { ((std::string *)userp)->append((char *)contents, size * nmemb); return size * nmemb; } int main() { // Replace these with your Access Key id and Api Secret std::string access_key_id = "your_access_key_id"; std::string api_secret = "your_api_secret"; // Encode the Access Key id and Api Secret in base64 format std::string credentials = base64_encode(reinterpret_cast<const unsigned char*>(access_key_id.append(":").append(api_secret).c_str()), access_key_id.length()); // Set the m3ter token endpoint URL std::string token_url = "https://api.m3ter.com/oauth/token"; // Initialize libcurl curl_global_init(CURL_GLOBAL_DEFAULT); CURL *curl = curl_easy_init(); if (curl) { // Set the headers for the request struct curl_slist *headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); std::string auth_header = "Authorization: Basic " + credentials; headers = curl_slist_append(headers, auth_header.c_str()); // Set the payload for the request std::string payload = "grant_type=client_credentials"; // Prepare the request curl_easy_setopt(curl, CURLOPT_URL, token_url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); // Send the request and store the response std::string response; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); // Check if the request was successful if (res != CURLE_OK || response_code != 200) { std::cerr << "Error: " << response_code << " - " << curl_easy_strerror(res) << std::endl; } else { // Parse the JSON response Json::Value json; std::istringstream(response) >> json; std::string bearer_token = json["access_token"].asString(); std::cout << "Bearer Token: " << bearer_token << std::endl; } // Cleanup curl_easy_cleanup(curl); curl_slist_free_all(headers); } curl_global_cleanup(); return 0; } ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the program, and if successful, it will print the Bearer Token. ## Step 5: Retrieve Organization ID Copy your Organization ID from the m3ter Console by going to **Settings**, **Organization**, then the **Configuration** tab. The Organization ID is displayed on the _Organization Details_ card and you can **Copy** it directly to your clipboard. ## Step 6: Retrieve Accounts List Make a call to the [List Accounts](https://www.m3ter.com/docs/api#tag/Account/operation/ListAccounts) API endpoint using the Organization ID copied in the previous step. Use the Bearer Token to authorize API calls in the HTTP 'Authorization' header. ### cURL ```bash curl -X GET "https://api.m3ter.com/organizations/{orgId}/accounts?pageSize={pageSize}&nextToken={nextToken}" \ -H "Authorization: Bearer {access_token}" ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### Python ```python import requests org_id = 'your_org_id' page_size = 'your_page_size' next_token = 'your_next_token' # Optional, use if needed access_token = 'your_bearer_token' url = f'https://api.m3ter.com/organizations/{org_id}/accounts?pageSize={page_size}&nextToken={next_token}' headers = { 'Authorization': f'Bearer {access_token}' } response = requests.get(url, headers=headers) if response.status_code == 200: accounts = response.json() print(accounts) else: print(f"Error: {response.status_code}") ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### JavaScript ```javascript const axios = require("axios"); const org_id = "your_org_id"; const page_size = "your_page_size"; const next_token = "your_next_token"; // Optional, use if needed const access_token = "your_bearer_token"; const url = `https://api.m3ter.com/organizations/${org_id}/accounts?pageSize=${page_size}&nextToken=${next_token}`; const headers = { Authorization: `Bearer ${access_token}`, }; axios .get(url, { headers }) .then((response) => { if (response.status === 200) { const accounts = response.data; console.log(accounts); } else { console.log(`Error: ${response.status}`); } }) .catch((error) => { console.error(`Error: ${error.response.status}`); }); ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. ### C++ ```C++ #include <iostream> #include <string> #include <sstream> #include <curl/curl.h> #include <json/json.h> size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; } int main() { std::string org_id = "your_org_id"; std::string page_size = "your_page_size"; std::string next_token = "your_next_token"; // Optional, use if needed std::string access_token = "your_bearer_token"; std::string url = "https://api.m3ter.com/organizations/" + org_id + "/accounts?pageSize=" + page_size + "&nextToken=" + next_token; std::string auth_header = "Authorization: Bearer " + access_token; std::string read_buffer; CURL* curl = curl_easy_init(); if(curl) { struct curl_slist* headers = NULL; headers = curl_slist_append(headers, auth_header.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); CURLcode res = curl_easy_perform(curl); if(res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); if (response_code == 200) { Json::Value jsonData; Json::CharReaderBuilder jsonReader; std::string errs; std::istringstream iss(read_buffer); if (Json::parseFromStream(jsonReader, iss, &jsonData, &errs)) { std::cout << jsonData << std::endl; } } else { std::cout << "Error: " << response_code << std::endl; } } curl_easy_cleanup(curl); curl_slist_free_all(headers); } return 0; } ``` Replace `{orgId}`, `{pageSize}`, `{nextToken}`, and `{access_token}` with your Organization ID, desired page size, next token _(if needed)_, and Bearer Token respectively. --- # Integrations Webhook API Example A major benefit of using m3ter is that it seamlessly integrates with your current technology stack. You can create webhook destinations to link you integrations using the API, or via the Console: - This section provides a worked example showing you how to set up a Webhook via the API. - See [Creating and Managing Destinations](https://www.m3ter.com/docs/guides/integrations/setting-up-native-integrations/creating-and-managing-destinations) in the m3ter documentation for instructions on using the Console. ## Step 1: Create a Service User and Generate Access Keys 1. **Create a Service User**: Log in to the m3ter Console, go to **Settings**, **Access** then **Service Users** tab, and create a Service User. To enable API calls, grant the user **Administrator** permissions. 2. **Generate Access Keys**: In the Console, open the **Service User Details** page for the Service User by clicking on the **NAME** hotlink text. Select **Generate Access Key** to generate an **Access Key id** and **Api Secret**. Make sure you copy the **Api Secret** because it is only visible at the time of creation. For further guidance on completing **Step 1**, see [Creating and Configuring Service Users](https://www.m3ter.com/docs/guides/organization-and-access-management/managing-users/creating-and-configuring-service-users) in our main user Documentation. ## Step 2: Obtain a Bearer Token using Basic Auth We implement the OAuth 2.0 Client Credentials Grant authentication flow for Service User Authentication. Submit a request to the m3ter OAuth Client Credentials authentication flow, using your concatenated **Access Key id** and **Api Secret** to obtain a Bearer Token for your Service User. Here's an example in Python code: ```python import requests import base64 # Replace these with your Access Key id and Api Secret access_key_id = 'your_access_key_id' api_secret = 'your_api_secret' # Encode the Access Key id and Api Secret in base64 format credentials = base64.b64encode(f'{access_key_id}:{api_secret}'.encode('utf-8')).decode('utf-8') # Set the m3ter token endpoint URL token_url = 'https://api.m3ter.com/oauth/token' # Set the headers for the request headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/x-www-form-urlencoded' } # Set the payload for the request payload = { 'grant_type': 'client_credentials' } # Send the request to obtain the Bearer Token response = requests.post(token_url, headers=headers, data=payload) # Check if the request was successful if response.status_code == 200: # Extract the Bearer Token from the response bearer_token = response.json()['access_token'] print(f'Bearer Token: {bearer_token}') else: print(f'Error: {response.status_code} - {response.text}') ``` Replace `your_access_key_id` and `your_api_secret` with your actual **Access Key id** and **Api Secret**. Run the script, and if successful, it will print the Bearer Token. ## Step 3: Create a Webhook (Destination) After obtaining the Bearer Token, you can use it to authorize your API calls. Here's a Python example of creating a webhook: ```python import requests import json # API endpoint url = "https://api.m3ter.com/organizations/{orgId}/integrationdestinations/webhooks" # replace {orgId} with your organization's UUID # Headers headers = { "Content-Type": "application/json", "Authorization": f"Bearer {bearer_token}" # replace with your actual Bearer Token } # Request body payload = { "url": "https://your-webhook-listener.com", # replace with your actual webhook listener URL "credentials": { "type": "M3TER_SIGNED_REQUEST", "apiKey": access_key_id, # replace with your actual API key "secret": api_secret # replace with your actual secret } } # Make the POST request response = requests.post(url, headers=headers, data=json.dumps(payload)) # Print the response print(response.json()) ``` ## Step 4: Validate Incoming Requests Once your webhook is set up, you'll want to validate incoming requests to ensure they're coming from m3ter. All requests we make to your webhook are signed by us. When you receive a request on your configured endpoint, validate the `X-m3ter-signature` header by preparing a payload string that you sign with your API secret. You must concatenate the following data using a pipe '|' separator to compute the payload: - url - query string - Currently, there's no support for passing in query parameters. For now, you can hard code to this string: '{}' - API Key - provided in the `X-m3ter-apikey` header. - timestamp - provided in the `X-m3ter-timestamp` header. - body - the request body. You can now set up and validate webhooks using the m3ter Console and API. Always refer to the latest [m3ter documentation](https://www.m3ter.com/docs) for accurate and up to date information. --- # Authentication <!-- ReDoc-Inject: <security-definitions> --></description> <url>https://www.m3ter.com</url> <licenses> <license> <name>Apache-2.0</name> </license> </licenses> <developers> <developer> <name>M3ter</name> <email>sdks@m3ter.com</email> </developer> </developers> <scm> <connection>scm:git:git://github.com/m3ter-com/m3ter-sdk-java.git</connection> <developerConnection>scm:git:git://github.com/m3ter-com/m3ter-sdk-java.git</developerConnection> <url>https://github.com/m3ter-com/m3ter-sdk-java</url> </scm> <dependencies> <dependency> <groupId>com.m3ter</groupId> <artifactId>sdk-java-core</artifactId> <version>0.2.0-alpha</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib-jdk8</artifactId> <version>1.8.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.12.0</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>logging-interceptor</artifactId> <version>4.12.0</version> <scope>runtime</scope> </dependency> </dependencies> </project>