Teste de autenticação
Visão Geral
Esta documentação detalha o processo de assinatura e encriptação de cabeçalhos para autenticação segura em requisições à nossa API. O processo garante que as requisições sejam confiáveis e seguras, prevenindo acessos não autorizados e garantindo a integridade dos dados.
Atenção!
O hash md5 de requisições dos métodos GET e DELETE deve ser gerado com o payload vazio
- Python
- PHP
- Node.js
- Java
- C#
#Aqui, importamos as bibliotecas necessárias ao longo do processo de autenticação.
from jose import jwt
import json
from datetime import datetime
from hashlib import md5
import requests
def get_auth_header(endpoint, method, CLIENT_PRIVATE_KEY, API_KEY, request_body=None):
if request_body is None:
request_body = {}
#O objeto de data e hora informado deve estar em UTC e deve seguir o padrão da norma internacional ISO 8601 ("2023-06-26T19:48:32.759844Z")
timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
#Definimos o algoritmo de codificação JWT
jwt_header = {
"typ": "JWT",
"alg": "ES512"
}
#Construir hash em MD5 para assinatura no cabeçalho (header) utilizando o payload
json_body = json.dumps(request_body)
md5_hash = md5(json_body.encode()).hexdigest()
#Essas são as infromações necessárias para assinatura do cabeçalho
jwt_body = {
"payload_md5": md5_hash,
"timestamp": timestamp,
"method": method,
"uri": endpoint
}
#Realizar criptografia do header
encoded_header_token = jwt.encode(
claims=jwt_body,
key=CLIENT_PRIVATE_KEY,
algorithm="ES512",
headers=jwt_header
)
#Montar header assinado
signed_header = {
"AUTHORIZATION": encoded_header_token,
"API-CLIENT-KEY": API_KEY
}
return signed_header
if __name__ == "__main__":
#Utilizaremos as variáveis base_url, endpoint, method e request_body. Neste exemplo faremos um POST no endpoint "/test".
#As chaves contidas neste exemplo são apenas para fins de demonstração. Por favor, utilize suas próprias chaves.
CLIENT_PRIVATE_KEY = "SUA PRIVATE KEY AQUI"
API_KEY = "SUA API KEY AQUI"
BASE_URL = "https://api-auth.sandbox.qitech.app"
METHOD = "POST" #GET ou POST
REQUEST_BODY = {
"name": "QI Tech"
}
#Para fazer um GET na /test, é necessário inserir a API key ao final, enquanto para fazer um POST no mesmo endpoint, não é necessário
if METHOD == 'GET':
ENDPOINT = f"/test/{API_KEY}"
signed_header = get_auth_header(ENDPOINT, METHOD, CLIENT_PRIVATE_KEY, API_KEY)
response = requests.get(f"{BASE_URL}{ENDPOINT}", headers=signed_header)
else:
ENDPOINT = f"/test/"
signed_header = get_auth_header(ENDPOINT, METHOD, CLIENT_PRIVATE_KEY, API_KEY, REQUEST_BODY)
response = requests.post(f"{BASE_URL}{ENDPOINT}", json=REQUEST_BODY, headers=signed_header)
print(response.status_code)
print(response.json())
<?php
require __DIR__ . '/vendor/autoload.php';
//Aqui, importamos as bibliotecas necessárias ao longo do processo de autenticação.
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Signature\JWSTokenSupport;
use Jose\Component\Signature\Algorithm\ES512;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\JWSBuilder;
function get_auth_header($endpoint, $method, $privateKeyString, $api_key, $request_body = null) {
if ($request_body === null) {
$request_body = (object)[];
}
//O objeto de data e hora informado deve estar em UTC e deve seguir o padrão da norma internacional ISO 8601 ("2023-06-26T19:48:32.759844Z")
$microtime_float = microtime(true);
$datetime = new DateTimeImmutable('@' . floor($microtime_float), new DateTimeZone('UTC'));
$timestamp = $datetime->format('Y-m-d\TH:i:s.') . sprintf('%06d', ($microtime_float - floor($microtime_float)) * 1000000) . 'Z';
//Definimos o algoritmo de codificação JWT
$header = [
"typ" => "JWT",
"alg" => "ES512"
];
//Construir hash em MD5 para assinatura no cabeçalho (header) utilizando o payload
$request_body_json = json_encode($request_body);
$md5_hash = md5($request_body_json);
//Essas são as infromações necessárias para assinatura do cabeçalho
$payload = [
"payload_md5" => $md5_hash,
"timestamp" => $timestamp,
"method" => $method,
"uri" => $endpoint
];
// Inicializar Algorithm Manager com ES512
$algorithmManager = new AlgorithmManager([
new ES512(),
]);
// Inicializar JWS Builder
$jwsBuilder = new JWSBuilder(
$algorithmManager,
new JWSTokenSupport()
);
$privateKey = JWKFactory::createFromKey($privateKeyString);
//Realizar criptografia do header
$jws = $jwsBuilder
->create()
->withPayload(json_encode($payload))
->addSignature($privateKey, $header)
->build();
$serializer = new CompactSerializer();
$jwt = $serializer->serialize($jws, 0);
//Montar header assinado
$headers = [
'Authorization' => $jwt,
'API-CLIENT-KEY' => $api_key,
];
return $headers;
}
if (php_sapi_name() == 'cli' || (isset($_SERVER['REQUEST_METHOD']) && realpath($_SERVER['SCRIPT_FILENAME']) === __FILE__)) {
//Utilizaremos as variáveis base_url, endpoint, method e request_body. Neste exemplo faremos um POST no endpoint "/test".
$base_url = "https://api-auth.sandbox.qitech.app";
$method = "POST"; // HTTP method: "GET" or "POST"
$request_body = ["name" => "QI Tech"];
//As chaves contidas neste exemplo são apenas para fins de demonstração. Por favor, utilize suas próprias chaves.
$api_key = "SUA API KEY AQUI";
$privateKeyString = "SUA PRIVATE KEY AQUI";
$response = null;
#Para fazer um GET na /test, é necessário inserir a API key ao final, enquanto para fazer um POST no mesmo endpoint, não é necessário
if ($method == 'GET') {
$endpoint = "/test/" . $api_key;
$headers = get_auth_header($endpoint, $method, $privateKeyString, $api_key);
$url = $base_url . $endpoint;
$response = \WpOrg\Requests\Requests::get($url, $headers);
} else {
$endpoint = "/test";
$headers = get_auth_header($endpoint, $method, $privateKeyString, $api_key, $request_body);
$url = $base_url . $endpoint;
$response = \WpOrg\Requests\Requests::post($url, $headers, json_encode($request_body));
}
if ($response) {
echo "HTTP Status Code: " . $response->status_code . "\n";
$json_response = json_decode($response->body, true);
if (json_last_error() === JSON_ERROR_NONE) {
echo "Response JSON:\n";
print_r($json_response);
} else {
echo "Error decoding JSON. Raw Response Text:\n";
echo $response->body . "\n";
}
}
?>
//Aqui, importamos as bibliotecas necessárias ao longo do processo de autenticação.
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const axios = require('axios');
function getAuthHeader(endpoint, method, client_private_key, api_key, request_body = null) {
if (request_body === null) {
request_body = {};
}
//O objeto de data e hora informado deve estar em UTC e deve seguir o padrão da norma internacional ISO 8601 ("2023-06-26T19:48:32.759844Z")
const now = new Date();
const isoString = now.toISOString();
const timestamp = isoString.slice(0, -1) + (now.getMilliseconds() * 1000).toString().padStart(6, '0').slice(0, 3) + 'Z';
//Definimos o algoritmo de codificação JWT
const jwt_header = {
typ: 'JWT',
alg: 'ES512'
};
//Construir hash em MD5 para assinatura no cabeçalho (header) utilizando o payload
const str_body = JSON.stringify(request_body);
const md5_hash = crypto.createHash('md5').update(str_body).digest('hex');
//Essas são as infromações necessárias para assinatura do cabeçalho
const jwt_body = {
payload_md5: md5_hash,
timestamp: timestamp,
method: method,
uri: endpoint
};
// Inicializar JWS Builder
const encoded_header_token = jwt.sign(
jwt_body,
client_private_key,
{
algorithm: 'ES512',
header: jwt_header
}
);
//Realizar criptografia do header
const signed_header = {
'AUTHORIZATION': encoded_header_token,
'API-CLIENT-KEY': api_key
};
return signed_header;
}
//Utilizaremos as variáveis BASE_URL, ENDPOINT, METHOD e REQUEST_BODY. Neste exemplo faremos um POST no endpoint "/test".
async function main() {
const BASE_URL = "https://api-auth.sandbox.qitech.app";
const METHOD = "POST"; //"POST" ou "GET"
const REQUEST_BODY = {
name: "QI Tech"
};
const API_KEY = "SUA API KEY AQUI";
const CLIENT_PRIVATE_KEY = "SUA PRIVATE KEY AQUI";
let ENDPOINT;
let url;
let signed_header;
try {
//Para fazer um GET na /test, é necessário inserir a API key ao final, enquanto para fazer um POST no mesmo endpoint, não é necessário
if (METHOD === 'GET') {
ENDPOINT = `/test/${API_KEY}`;
url = `${BASE_URL}${ENDPOINT}`;
signed_header = getAuthHeader(ENDPOINT, METHOD, CLIENT_PRIVATE_KEY, API_KEY);
const response = await axios.get(url, { headers: signed_header });
console.log("Status Code:", response.status);
console.log("Response Body:", response.data);
} else {
ENDPOINT = "/test";
url = `${BASE_URL}${ENDPOINT}`; // Corrected string interpolation
signed_header = getAuthHeader(ENDPOINT, METHOD, CLIENT_PRIVATE_KEY, API_KEY, REQUEST_BODY);
const response = await axios.post(url, REQUEST_BODY, { headers: signed_header });
console.log("Status Code:", response.status);
console.log("Response Body:", response.data);
}
} catch (error) {
// More robust error handling for Axios
if (error.response) {
console.error("API Error - Status Code:", error.response.status);
console.error("API Error - Response Data:", error.response.data);
console.error("API Error - Headers:", error.response.headers);
} else if (error.request) {
console.error("Network Error: No response received from server.");
console.error("Request:", error.request);
} else {
console.error("Error setting up request:", error.message);
}
console.error("Full Error Object:", error);
}
}
main();
//Para Java precisaremos criar um arquivo com o nome de qitech-java-client
//Crie um arquivo chamado pom.xml e cole o final do código dentro dele
// Será necessário dentro do seu projeto criar algumas pastas - crie o seguinte path; src > main > java > com > qitech > api e insira seu arquivo java dentro com o nome de QItechApiClient.java
// Adicione sua private key no diretório raiz de seu projeto no mesmo nível que seu pom
// Para rodar o código abra o terminal ou comand prompt, navegue para a raiz de seu projeto e rode o seguinte código:
// mvn clean install exec:java
//Aqui, importamos as bibliotecas necessárias ao longo do processo de autenticação.
package com.qitech.api;
import com.google.gson.Gson;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
public class QItechApiClient {
public static Map<String, String> getAuthHeader(String endpoint, String method, PrivateKey privateKey, String apiKey, Map<String, Object> requestBody) throws NoSuchAlgorithmException {
//O objeto de data e hora informado deve estar em UTC e deve seguir o padrão da norma internacional ISO 8601 ("2023-06-26T19:48:32.759844Z")
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String timestamp = sdf.format(new Date());
//Construir hash em MD5 para assinatura no cabeçalho (header) utilizando o payload
String jsonBody = jsonToString(requestBody);
String md5Hash = md5Hash(jsonBody);
//Essas são as infromações necessárias para assinatura do cabeçalho
Map<String, Object> jwtBody = new HashMap<>();
jwtBody.put("payload_md5", md5Hash);
jwtBody.put("timestamp", timestamp);
jwtBody.put("method", method);
jwtBody.put("uri", endpoint);
//Realizar criptografia do header
JwtBuilder jwtBuilder = Jwts.builder()
.setClaims(jwtBody)
.signWith(privateKey, SignatureAlgorithm.ES512);
String encodedHeaderToken = jwtBuilder.compact();
//Montar header assinado
Map<String, String> signedHeader = new HashMap<>();
signedHeader.put("AUTHORIZATION", encodedHeaderToken);
signedHeader.put("API-CLIENT-KEY", apiKey);
return signedHeader;
}
public static void main(String[] args) {
Security.addProvider(new BouncyCastleProvider());
OkHttpClient client = null;
try {
//Utilizaremos as variáveis base_url, endpoint, method e request_body. Neste exemplo faremos um POST no endpoint "/test".
//As chaves contidas neste exemplo são apenas para fins de demonstração. Por favor, utilize suas próprias chaves.
final String BASE_URL = "https://api-auth.sandbox.qitech.app";
final String PRIVATE_KEY_FILENAME = "private.key";
final String API_CLIENT_KEY = "SUA API KEY AQUI";
final String METHOD = "GET"; //GET ou POST
final Map<String, Object> REQUEST_BODY = new HashMap<>();
REQUEST_BODY.put("name", "QI Tech");
String keyFromFile = readKeyFromFile(PRIVATE_KEY_FILENAME);
PrivateKey privateKey = getPrivateKey(keyFromFile);
String endpoint;
Request request;
//Para fazer um GET na /test, é necessário inserir a API key ao final, enquanto para fazer um POST no mesmo endpoint, não é necessário
if ("GET".equalsIgnoreCase(METHOD)) {
endpoint = "/test/" + API_CLIENT_KEY;
Map<String, String> headers = getAuthHeader(endpoint, "GET", privateKey, API_CLIENT_KEY, Collections.emptyMap());
request = new Request.Builder()
.url(BASE_URL + endpoint)
.headers(okhttp3.Headers.of(headers))
.get()
.build();
} else {
endpoint = "/test";
Map<String, String> headers = getAuthHeader(endpoint, "POST", privateKey, API_CLIENT_KEY, REQUEST_BODY);
RequestBody body = RequestBody.create(
jsonToString(REQUEST_BODY),
MediaType.parse("application/json; charset=utf-8")
);
request = new Request.Builder()
.url(BASE_URL + endpoint)
.headers(okhttp3.Headers.of(headers))
.post(body)
.build();
}
client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
System.out.println("--- Sending " + METHOD + " Request ---");
System.out.println("URL: " + BASE_URL + endpoint);
try (Response response = client.newCall(request).execute()) {
System.out.println("\n--- Received Response ---");
System.out.println("Status Code: " + response.code());
if (response.body() != null) {
System.out.println("Response Body: " + response.body().string());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (client != null) {
client.dispatcher().executorService().shutdown();
client.connectionPool().evictAll();
}
}
}
// --- Helper Methods ---
private static String readKeyFromFile(String filename) throws IOException {
String key = new String(Files.readAllBytes(Paths.get(filename)));
return key.replace("-----BEGIN EC PRIVATE KEY-----", "")
.replace("-----END EC PRIVATE KEY-----", "")
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s", "");
}
private static String jsonToString(Map<String, Object> jsonMap) { return new Gson().toJson(jsonMap); }
private static String md5Hash(String text) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(text.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : array) { sb.append(String.format("%02x", b)); }
return sb.toString();
}
private static PrivateKey getPrivateKey(final String encodedPvKey) throws IOException {
try {
byte[] derBytes = Base64.getDecoder().decode(encodedPvKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
try {
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(derBytes));
} catch (InvalidKeySpecException e) {
org.bouncycastle.asn1.sec.ECPrivateKey sec1Key = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(derBytes);
ECParameterSpec ecParameterSpec = ECNamedCurveTable.getParameterSpec("secp521r1");
ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(sec1Key.getKey(), ecParameterSpec);
return keyFactory.generatePrivate(privateKeySpec);
}
} catch (Exception e) {
throw new IOException("Failed to parse private key. Key is corrupted or not a valid EC key.", e);
}
}
}
////POM File
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qitech.api</groupId>
<artifactId>qitech-api-client</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- HTTP Client -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- JSON Web Token (JWT) Handling -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<!-- Cryptography Provider for ES512 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78</version>
</dependency>
<!-- JSON Serialization -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<mainClass>com.qitech.api.QItechApiClient</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
//Aqui, importamos as bibliotecas necessárias ao longo do processo de autenticação.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Jose;
using Newtonsoft.Json;
public static class QiTechAuthGenerator {
public static string GetAuthorizationHeader(
string endpoint,
string method,
string clientPrivateKey,
object requestBody)
{
string privateKeyBase64 = clientPrivateKey
.Replace("-----BEGIN EC PRIVATE KEY-----", "")
.Replace("-----END EC PRIVATE KEY-----", "")
.Replace("\n", "")
.Replace("\r", "");
using var privateKey = ECDsa.Create();
privateKey.ImportECPrivateKey(Convert.FromBase64String(privateKeyBase64), out _);
string payloadToHash;
if (method.ToUpper() == "GET") {
payloadToHash = "{}";
}
else {
payloadToHash = JsonConvert.SerializeObject(requestBody);
}
//Construir hash em MD5 para assinatura no cabeçalho (header) utilizando o payload
var payloadMd5Hash = CalculateMd5Hash(payloadToHash);
//Essas são as infromações necessárias para assinatura do cabeçalho
var jwtBody = new Dictionary<string, object> {
{ "payload_md5", payloadMd5Hash },
{ "timestamp", timestamp },
{ "method", method },
{ "uri", endpoint }
};
//Definimos o algoritmo de codificação JWT
var jwtHeader = new Dictionary<string, object> {
{ "typ", "JWT" },
{ "alg", "ES512" }
};
return JWT.Encode(jwtBody, privateKey, JwsAlgorithm.ES512, jwtHeader);
}
//Construir hash em MD5 para assinatura no cabeçalho (header) utilizando o payload
private static string CalculateMd5Hash(string input) {
using (var md5 = MD5.Create()) {
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
var builder = new StringBuilder();
foreach (var b in hashBytes) {
builder.Append(b.ToString("x2"));
}
return builder.ToString();
}
}
}
public class QiTechApiClient {
private readonly string _baseUrl;
private readonly string _apiKey;
private readonly string _clientPrivateKey;
public QiTechApiClient(string baseUrl, string apiKey, string clientPrivateKey) {
_baseUrl = baseUrl;
_apiKey = apiKey;
_clientPrivateKey = clientPrivateKey;
}
//Realizar criptografia do header
public async Task<string> CallEndpointAsync(string endpoint, string method, object requestBody) {
var signedHeader = QiTechAuthGenerator.GetAuthorizationHeader(
endpoint,
method,
_clientPrivateKey,
requestBody
);
var url = $"{_baseUrl}{endpoint}";
//Montar header assinado
using (var client = new HttpClient()) {
client.DefaultRequestHeaders.Add("AUTHORIZATION", signedHeader);
client.DefaultRequestHeaders.Add("API-CLIENT-KEY", _apiKey);
HttpResponseMessage httpResponse;
if (method.ToUpper() == "GET") {
httpResponse = await client.GetAsync(url);
}
else {
var jsonBody = JsonConvert.SerializeObject(requestBody);
var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
httpResponse = await client.PostAsync(url, content);
}
httpResponse.EnsureSuccessStatusCode();
var responseContent = await httpResponse.Content.ReadAsStringAsync();
return responseContent;
}
}
}
public class Program {
public static async Task Main() {
string response = "";
//Utilizaremos as variáveis baseUrl, endpoint, method e requestBody. Neste exemplo faremos um POST no endpoint "/test".
var baseUrl = "https://api-auth.sandbox.qitech.app";
var method = "POST";
var requestBody = new { name = "QI Tech" };
//As chaves contidas neste exemplo são apenas para fins de demonstração. Por favor, utilize suas próprias chaves.
var apiKey = "SUA API KEY AQUI";
var clientPrivateKey = @"SUA PRIVATE KEY AQUI";
try {
var apiClient = new QiTechApiClient(baseUrl, apiKey, clientPrivateKey);
//Para fazer um GET na /test, é necessário inserir a API key ao final, enquanto para fazer um POST no mesmo endpoint, não é necessário
if (method.ToUpper() == "GET") {
var endpoint = "/test/" + apiKey;
response = await apiClient.CallEndpointAsync(endpoint, method, null);
}
else {
var endpoint = "/test";
response = await apiClient.CallEndpointAsync(endpoint, method, requestBody);
}
Console.WriteLine("\nAPI Response:");
Console.WriteLine(response);
}
catch (HttpRequestException ex) {
Console.WriteLine($"\nHTTP Error: {ex.Message}");
}
catch (Exception ex) {
Console.WriteLine($"\nAn unexpected error occurred: {ex.Message}");
}
}
}