No matching endpoints
Nothing here matches
Envie o cabeçalho X-App-Secret da sua app e faça POST de JSON para /api/auth/* para validar chaves e gerir sessões. Gere chaves em /api/admin/* com um token Bearer. As respostas são sempre { "success": true|false, … }.
Introdução
A API do PWF Auth está organizada em torno de REST. Todos os pedidos e respostas são JSON sobre HTTPS. Existem três famílias de endpoints:
- API de cliente (
/api/auth/*,/api/update/*) — chamada a partir da sua aplicação distribuída usando o segredo da app. - API de administração (
/api/admin/*) — gestão de chaves e apps, autenticada com um token Bearer. - API de cliente/revendedor (
/api/customer/*,/api/reseller/*) — portais de autosserviço.
Todos os caminhos abaixo são relativos a esse URL base. Cada endpoint exige HTTPS; pedidos em HTTP simples são redirecionados.
Prefer machines? The whole surface is described in openapi.json (OpenAPI 3.1) — import it into Postman, Insomnia, or a code generator.
API and platform changes are announced in the changelog — breaking changes are always flagged there first.
Autenticação
Endpoints de cliente — Segredo da app
Envie o segredo da sua app no cabeçalho X-App-Secret. Encontra-o em Painel → a sua app. O segredo identifica a que aplicação pertence um pedido.
curl https://pwfauth.com/api/auth/check-key.php \
-H "X-App-Secret: 9f02532d9c60… # 64-char hex, from your dashboard" \
-H "Content-Type: application/json" \
-d '{"license_key":"XXXXX-XXXXX-XXXXX-XXXXX"}'
Endpoints de administração — Token Bearer
Autentique-se em /api/admin/login.php para receber um JWT e envie-o como Authorization: Bearer <token> em cada chamada de administração.
TOKEN=$(curl -s https://pwfauth.com/api/admin/login.php \
-d '{"username":"admin","password":"…"}' | jq -r .token)
curl https://pwfauth.com/api/admin/keys.php \
-H "Authorization: Bearer $TOKEN"
O envelope encriptado
Os endpoints de nível SDK trocam um envelope AES-256-CBC + HMAC-SHA256 em vez de JSON simples. O formato de transporte é {"p": base64(IV || ciphertext), "t": unix_timestamp, "s": hmac_sha256_hex(p + t)} — as chaves de encriptação e de MAC derivam ambas do segredo da sua app, sem necessidade de troca de chaves adicional.
{
"p": "aXYxNmJ5dGVzY2lwaGVydGV4dA…", // base64( IV || AES-256-CBC ciphertext )
"t": 1785671000, // unix timestamp (±300s accepted)
"s": "b7fd09…" // hmac_sha256_hex( p + t, mac_key )
}
Endpoints marcados com Segredo da app + envelope encriptado exigem-no no pedido e respondem encriptados. O check-key.php deteta automaticamente: envie JSON simples e recebe JSON simples (é isso que faz os exemplos curl desta página funcionarem); envie um envelope e a resposta vem encriptada.
Envelopes com mais de ±300 segundos são rejeitados, por isso mantenha o relógio do cliente razoavelmente certo. Nunca precisa de construir isto à mão: os clientes de exemplo open-source (VB.NET, C#, Python) incluem uma implementação CryptoEnvelope pronta.
How the envelope is built
Both directions use the same recipe. Two keys are derived from your app secret, so every app gets distinct encryption and signing keys:
enc_key = SHA256("enc:" + app_secret) # 32 bytes
mac_key = SHA256("mac:" + app_secret) # 32 bytes
# client → server (and server → client — same recipe)
iv = random_bytes(16)
ct = AES-256-CBC(enc_key, iv, json_body) # PKCS#7 padding
p = base64(iv || ct)
t = unix_time() # ±300 s accepted
s = hex(HMAC-SHA256(p + str(t), mac_key))
send { "p": p, "t": t, "s": s }
# receiving: verify s FIRST (constant-time), check |now - t| ≤ 300,
# then base64-decode p, split off the 16-byte IV, decrypt the rest.
Which endpoints require it
Each endpoint card carries a colour-coded auth pill; this table is the same information at a glance:
| Auth model | Endpoints |
|---|---|
| Público | app/changelog · app/pricing · admin/login |
| Segredo da app · simples ou envelope | auth/check-key |
| Segredo da app | auth/trial · auth/request-hwid-reset · auth/account-register · auth/account-login · auth/change-password · update/validate · update/download |
| Segredo da app + envelope encriptado | auth/login · auth/heartbeat · auth/logout · app/text · app/slides · app/info · app/social-click · update/check |
| Bearer | admin/* |
| Segredo de fulfillment | app/fulfill |
Respostas e erros
Cada resposta inclui um booleano success. Os erros acrescentam uma message legível e um error_code estável e legível por máquinas:
{
"success": false,
"message": "This license key has been banned.",
"error_code": "BANNED"
}
| error_code | Significado |
|---|---|
MISSING_FIELDS | Falta um campo obrigatório no corpo. |
INVALID_KEY | A chave de licença não existe para esta app. |
INVALID_CREDENTIALS | Utilizador/palavra-passe rejeitados (contas de utilizador + login de admin). |
HWID_MISMATCH | A chave está associada a outro dispositivo. |
EXPIRED | A licença ultrapassou a data de expiração. |
BANNED / PAUSED | A chave foi banida ou pausada pelo proprietário. |
MAINTENANCE | A app está em modo de manutenção. |
SESSION_EXPIRED / SESSION_MISMATCH | A sessão de heartbeat é inválida. |
TOO_MANY_ATTEMPTS | Login brute-force lockout — the account is locked temporarily; retry_after in the response says for how many seconds. |
TRIAL_DISABLED / TRIAL_USED / TRIAL_LIMIT | Criação de teste recusada — desativada para esta app, já usada neste dispositivo, ou o limite por IP foi atingido. |
Códigos de estado HTTP
| error_code | Significado |
|---|---|
200 | Sucesso — o corpo JSON traz o resultado. |
400 | Validação falhou — campos em falta ou malformados (ver error_code). |
401 | X-App-Secret ou token Bearer em falta ou inválido. |
403 | Autenticado mas não autorizado (app errada, token revogado …). |
404 | Recurso não encontrado. |
405 | Método HTTP errado para este endpoint. |
429 | Rate limited — wait for the Retry-After header before retrying. |
500 | Erro de servidor — mensagem genérica de propósito; tente mais tarde. |
Limites de utilização & fair use
Não há quota global de pedidos, mas estão ativas algumas proteções contra abuso:
- O login de admin está protegido contra força bruta — falhas repetidas bloqueiam a conta temporariamente.
- Os testes são limitados por dispositivo (HWID) e por IP; exceder devolve
TRIAL_LIMIT. - A regeneração do segredo tem rate-limit por app para travar ciclos de rotação acidentais.
- Mantenha os heartbeats no intervalo que a resposta de login indicar (30 s por omissão) — bater mais depressa não acrescenta nada.
Início rápido
A integração mínima: valide uma chave quando a app arranca e depois envie heartbeat para manter a sessão viva.
# Validate a key from the terminal (plain JSON works here)
curl -X POST https://pwfauth.com/api/auth/check-key.php \
-H "X-App-Secret: $APP_SECRET" \
-d '{"license_key":"XXXXX-XXXXX-XXXXX-XXXXX"}'
# → { "success": true, "valid": true, "key": { "status": "active", … } }
Nota: o fluxo de sessão completo (login → heartbeat → logout) usa o envelope encriptado, pelo que não é testável à mão com curl. Ligue-o em minutos com o Quick Start do painel (gera snippets funcionais em 9 linguagens com as suas credenciais reais) ou com os clientes de exemplo open-source.
The same flow with an official SDK
Login, heartbeat and the server-side kill switch in a few lines — the SDK handles the encrypted envelope for you:
// dotnet add package PWFAuth
using PWFAuth;
var client = new PwfClient(APP_SECRET);
client.SessionEnded += (s, e) => // ban / pause / expiry / revoke / offline
{
Console.WriteLine($"{e.ErrorCode}: {e.Message}");
Environment.Exit(0);
};
var login = await client.LoginAsync("XXXXX-XXXXX-XXXXX-XXXXX");
if (!login.Success) { Console.WriteLine(login.Message); return; }
client.StartHeartbeat(); // keeps the session alive AND enforces the kill switch
' dotnet add package PWFAuth
Dim client As New PwfClient(APP_SECRET)
AddHandler client.SessionEnded, Sub(s, e) ' ban / pause / expiry / revoke / offline
MessageBox.Show(e.Message)
Application.Exit()
End Sub
Dim login = Await client.LoginAsync("XXXXX-XXXXX-XXXXX-XXXXX")
If login.Success Then client.StartHeartbeat()
# pip install pwfauth
import sys
from pwfauth import PwfClient
client = PwfClient(APP_SECRET)
client.on_session_ended = lambda code, msg: sys.exit(msg) # kill switch
login = client.login("XXXXX-XXXXX-XXXXX-XXXXX")
if not login.success:
sys.exit(login.message)
client.start_heartbeat() # keeps the session alive AND enforces the kill switch
// npm install pwfauth
import { PwfClient } from 'pwfauth';
const client = new PwfClient(process.env.PWFAUTH_SECRET);
client.on('sessionEnded', ({ errorCode, message }) => { // kill switch
console.error(`${errorCode}: ${message}`);
process.exit(1);
});
const login = await client.login('XXXXX-XXXXX-XXXXX-XXXXX');
if (!login.success) { console.error(login.message); process.exit(1); }
client.startHeartbeat(); // keeps the session alive AND enforces the kill switch
Licenças e sessões
Ative uma chave na primeira utilização, associe-a ao HWID do dispositivo e abra uma sessão. Revalida e inicia uma nova sessão nos logins seguintes. Aplica max_devices encerrando a sessão mais antiga.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
license_key | obrigatório | A chave de licença a ativar / validar. |
hwid | obrigatório | Impressão digital de hardware estável do dispositivo. |
{
"success": true,
"session_id": "8f2c…",
"user": {
"license_key": "XXXXX-XXXXX-XXXXX-XXXXX",
"key_type": "days", "duration": 30,
"expires_at": "2026-09-01T12:00:00Z",
"days_remaining": 30, "status": "active"
},
"features": { "pro_tier": true },
"heartbeat_interval": 30
}
Mantém uma sessão ativa. Chame-o a cada heartbeat_interval segundos (devolvido por login). Se parar de chamar, a sessão é encerrada no servidor.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
session_id | obrigatório | Sessão devolvida por login. |
license_key | opcional | Se enviada, a sessão tem de pertencer a esta chave. |
{ "success": true, "message": "Heartbeat received" }
// the moment the key is banned / paused / expired / reset, the SAME call answers:
{ "success": false, "error_code": "BANNED",
"message": "This license key has been banned." } // session is dropped — log the user out
Encerre uma sessão de imediato (ex.: ao sair da app). Corpo: session_id obrigatório, license_key opcional.
Consulta leve de estado — sem criar sessão nem associar HWID. Útil para verificar «esta chave ainda é válida?».
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
license_key | obrigatório | A chave a inspecionar. |
curl -X POST https://pwfauth.com/api/auth/check-key.php \
-H "X-App-Secret: $APP_SECRET" \
-d '{"license_key":"XXXXX-XXXXX-XXXXX-XXXXX"}'
var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-App-Secret", APP_SECRET);
var res = await http.PostAsync("https://pwfauth.com/api/auth/check-key.php",
new StringContent("{\"license_key\":\"XXXXX-XXXXX-XXXXX-XXXXX\"}"));
import urllib.request, json
req = urllib.request.Request("https://pwfauth.com/api/auth/check-key.php",
data=json.dumps({"license_key": "XXXXX-XXXXX-XXXXX-XXXXX"}).encode(),
headers={"X-App-Secret": APP_SECRET})
print(json.load(urllib.request.urlopen(req)))
const res = await fetch('https://pwfauth.com/api/auth/check-key.php', {
method: 'POST',
headers: { 'X-App-Secret': process.env.APP_SECRET },
body: JSON.stringify({ license_key: 'XXXXX-XXXXX-XXXXX-XXXXX' })
});
console.log(await res.json());
$ch = curl_init('https://pwfauth.com/api/auth/check-key.php');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-App-Secret: ' . $APP_SECRET],
CURLOPT_POSTFIELDS => '{"license_key":"XXXXX-XXXXX-XXXXX-XXXXX"}']);
$res = json_decode(curl_exec($ch), true);
{
"success": true, "valid": true,
"key": {
"status": "active", "key_type": "days", "duration": 30,
"activated_at": "2026-08-02T12:00:00Z",
"expires_at": "2026-09-01T12:00:00Z",
"days_remaining": 30, "max_devices": 1
}
}
Validação de licença leve, sem vínculo de HWID nem sessão — ideal como verificação prévia antes do login completo. JSON simples a entrar, JSON simples a sair.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
license_key | obrigatório | A chave a inspecionar. |
Submeta um pedido de reposição de HWID a partir da caixa de diálogo na app quando um utilizador muda de máquina. O proprietário da app aprova-o no painel.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
license_key or username | obrigatório | Identifica a associação de quem será reposta. |
reason | opcional | Nota mostrada ao proprietário. |
Testes gratuitos
Emite uma chave de teste com tempo limitado, associada ao dispositivo solicitante. Um teste por HWID por app. A duração do teste é definida pelo proprietário da app.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
hwid | obrigatório | Impressão digital do dispositivo que pede o teste. |
{
"success": true, "message": "Trial activated! You have 3 days.",
"trial_key": "TRIAL-1A2B3-C4D5E-F6A7B",
"session_id": "8f2c…",
"expires_at": "2026-08-23T12:00:00Z", "days_remaining": 3,
"user": { "key_type": "days", "status": "active", … },
"app": { "name": "…", "version": "…" }
}
Contas de utilizador
Prefere logins com nome de utilizador/palavra-passe em vez de chaves diretas? O PWF Auth inclui um modelo de contas completo com hashing bcrypt e associação de HWID.
Crie uma conta de utilizador final. Corpo: username, password obrigatório, email opcional.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
username | obrigatório | Nome de utilizador pretendido (único por app). |
password | obrigatório | Palavra-passe (guardada com hash no servidor). |
email | opcional | E-mail de contacto da conta. |
Autentique e associe um dispositivo. Corpo: username, password, hwid obrigatório. Devolve a mesma estrutura de sessão que login.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
username | obrigatório | Nome de utilizador da conta. |
password | obrigatório | Palavra-passe da conta. |
hwid | obrigatório | Impressão digital do dispositivo à qual a sessão fica vinculada. |
Altere a palavra-passe de um utilizador. Corpo: username, current_password, new_password obrigatório.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
username | obrigatório | Nome de utilizador da conta. |
current_password | obrigatório | Palavra-passe atual (verificada antes da alteração). |
new_password | obrigatório | Nova palavra-passe. |
Conteúdo da app & controlo remoto
Estes endpoints permitem à sua app publicada puxar conteúdo que edita ao vivo no painel — textos, slides, preços, changelog — sem lançar uma atualização.
Obter texto(s) remoto(s). Com ?name=… devolve uma entrada; sem parâmetro devolve todos os textos da app. Overrides por chave vencem os defaults da app. A chave de licença segue em Authorization: Bearer
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
?name | opcional | Chave do texto a obter (omitir para todos). |
Devolve os slides de anúncio ativos da app. Envie o corpo-envelope {"action":"get_slides"}; a resposta vem encriptada.
Metadados da app + links sociais (nome, branding, URLs). Resposta em envelope.
Incrementa o contador de cliques de um link social (para as estatísticas de envolvimento no painel).
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
link_id | obrigatório | ID numérico do link social. |
Feed público de changelog sem autenticação para uma app — mostre um widget "Novidades" em qualquer lado. Apenas entradas publicadas.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
?app_id | obrigatório | A app cujo changelog será lido. |
?limit | opcional | 1–50, por omissão 20. |
?since | opcional | Data ISO — apenas entradas publicadas a partir dela. |
?category | opcional | Filtro: new / improved / fixed / removed / security / deprecated. |
Interface pública de preços: níveis de subscrição e planos legacy de uma app; POST cria uma encomenda; ?action=check lê a subscrição ativa de um utilizador.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
?app_id | obrigatório | A app cujos preços serão lidos. |
?type | opcional | levels ou plans (omitir para ambos). |
Fulfillment de encomendas servidor-a-servidor para gateways de pagamento automáticos — um IPN verificado conclui a encomenda e dispara a geração + entrega da chave. Autenticado pelo segredo de fulfillment partilhado das definições do painel, nunca por uma sessão de utilizador.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
order_id | obrigatório | A encomenda a concluir (ORD-…). |
secret | obrigatório | O seu order_fulfill_secret. |
payment_ref | opcional | Referência de pagamento opcional do gateway. |
Atualizações OTA
Pergunte se há uma build mais recente disponível para o chamador — respeitando o canal, filtros de SO/arquitetura, requisitos de versão mínima e lançamentos faseados (o mesmo chamador fica de forma estável no mesmo segmento).
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
v | obrigatório | Versão atual do chamador (semver). |
channel | opcional | stable (predefinição), beta ou alpha. |
os / arch | opcional | windows·macos·linux / x64·x86·arm64. |
hwid / license_key | opcional | Usado para a distribuição estável por segmentos. |
{
"success": true, "update_available": true,
"update": {
"version": "1.4.0", "channel": "stable",
"is_mandatory": false, "file_size": 5242880,
"sha256": "…", "changelog": "…",
"download_url": "api/update/download.php?v=1.4.0"
}
}
Transmita o binário de uma dada versão. Use o download_url devolvido por check.php e verifique o sha256 após o download.
Webhooks
Turn events into HTTP calls to your server: key activations, bans, expiries, orders, new updates and more. Configure destinations per app (or for all apps) in the panel under Application → Webhooks, pick the events you care about, and PWF Auth POSTs a signed JSON body to your URL. Delivery is queue-based — expect it within a minute or two of the event, not in the same instant.
Delivery payload
{
"event": "key.activated",
"timestamp": "2026-08-20T14:07:02Z",
"data": {
"app_id": "01af6643-…",
"license_key": "XXXXX-XXXXX-XXXXX-XXXXX",
"hwid": "A1B2C3…"
}
}
Delivery headers
| Header | Descrição |
|---|---|
X-Webhook-Id | Unique delivery id (whd_…). Stays the same across retries of one event — use it to deduplicate. |
X-Webhook-Timestamp | Unix timestamp of the delivery attempt. |
X-Webhook-Attempt | 1-based attempt counter. |
X-Webhook-Signature | Legacy signature: hex(HMAC-SHA256(body, secret)). |
X-Webhook-Signature-V2 | Preferred signature: t=<ts>,v1=hex(HMAC-SHA256(ts + "." + body, secret)) — the timestamp inside the MAC makes replays detectable. |
Verifying the signature
Always verify before trusting a delivery: compute the V2 MAC over timestamp + "." + raw body with your endpoint secret, compare in constant time, and reject stale timestamps (±5 minutes is plenty). Answer 2xx fast — heavy work belongs in your own queue.
// X-Webhook-Signature-V2: t=<ts>,v1=<hex>
[$t, $v1] = explode(',', $_SERVER['HTTP_X_WEBHOOK_SIGNATURE_V2'] ?? ',');
$t = substr($t, 2); $v1 = substr($v1, 3);
$raw = file_get_contents('php://input');
$ok = hash_equals(hash_hmac('sha256', $t . '.' . $raw, $secret), $v1)
&& abs(time() - (int)$t) < 300;
if (!$ok) { http_response_code(400); exit; }
http_response_code(200); // answer fast — queue heavy work
// X-Webhook-Signature-V2: t=<ts>,v1=<hex>
const [t, v1] = req.headers['x-webhook-signature-v2']
.split(',').map(kv => kv.split('=')[1]);
const mac = crypto.createHmac('sha256', secret)
.update(`${t}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(v1))
&& Math.abs(Date.now() / 1000 - Number(t)) < 300;
res.sendStatus(ok ? 200 : 400); // answer fast — queue heavy work
# X-Webhook-Signature-V2: t=<ts>,v1=<hex>
import hmac, time
t, v1 = (kv.split("=", 1)[1]
for kv in request.headers["X-Webhook-Signature-V2"].split(","))
mac = hmac.new(secret, f"{t}.{raw_body}".encode(), "sha256").hexdigest()
ok = hmac.compare_digest(mac, v1) and abs(time.time() - int(t)) < 300
return ("", 200) if ok else ("", 400) # answer fast — queue heavy work
Retries & failure policy
- A delivery counts as successful on any
2xx/3xxanswered within 5 seconds. - Failures retry up to 5 attempts with widening gaps: 1 m → 5 m → 30 m → 2 h → 6 h.
X-Webhook-Idis minted once per event and reused on every retry — idempotency is oneseen?lookup away.- A destination that fails 20 times in a row is paused automatically; re-enable it from the panel (a
testevent button is right there).
Events
Subscribe to specific events or leave the filter empty to receive them all. event in the body tells you which one fired:
| Event | Fires when |
|---|---|
key.created | Keys are generated (panel or admin API). |
key.activated | A key's first successful login binds it to a device. |
key.banned / key.unbanned | A key is banned / unbanned. |
key.deleted | A key is deleted. |
key.rotated | A key string is rotated (the old string stops working). |
key.suspected_leak | Leak detection flags a key as suspected shared/leaked. |
key_expiring | A key approaches expiry (scheduled sweep). |
key_expired | A key expires (scheduled sweep). |
trial.created | A trial key is issued to a new device. |
hwid_reset.requested | A client requests a device (HWID) reset. |
new_order | A purchase order is created. |
order.approved | An order is approved and fulfilled. |
subscription.* | Subscription lifecycle: created / renewed / cancelled / renewal order created. |
update.published | A new application version is published. |
changelog.published | A changelog entry goes live. |
app.revoked | An application is revoked / disabled. |
suspicious_activity | The suspicious-activity heuristic fires. |
test | Manual test delivery from the panel. |
API de administração
Endpoints do lado do servidor para gerir apps e chaves. Todos exigem um token Authorization: Bearer do endpoint de login abaixo.
Prefere não guardar a palavra-passe num script? Crie um Personal Access Token no painel em Perfil → API Tokens e use-o como valor Bearer (pwf_…). Nunca expira até o revogar, funciona em todos os endpoints /api/admin/* e está excluído por design da gestão de credenciais (palavra-passe, e-mail, 2FA, criação de mais tokens).
Troque credenciais por um JWT. Se a 2FA estiver ativada, devolve requires_2fa + um step1_token a concluir via /api/admin/totp.php.
| Campo do corpo | Obrig.? | Descrição |
|---|---|---|
username | obrigatório | Nome de utilizador do administrador. |
password | obrigatório | Palavra-passe do administrador. |
Gere chaves de licença em massa. O mesmo endpoint também suporta GET (listar), PUT (editar), DELETE e consultas de ação como ?action=ban|pause|extend|reset-hwid e ?action=export.
curl -X POST https://pwfauth.com/api/admin/keys.php \
-H "Authorization: Bearer $TOKEN" \
-d '{"app_id":"01af6643-cf3a-4280-b9ce-cb5fa8ae987c",
"count":100,"key_type":"days","duration_value":30}'
A superfície de administração cobre ainda apps, sessions, updates, feature-flags, webhooks, analytics, audit, resellers e mais — cada um sob /api/admin/ com a mesma auth Bearer. Inicie sessão no painel para os explorar.
SDKs
A API REST funciona a partir de qualquer coisa que consiga enviar um pedido HTTP. Há SDKs oficiais de ficheiro único para VB.NET / C#, com exemplos de primeira para Python e PHP. Tudo o resto — Node, Go, Rust, Java, Swift — fala com os mesmos endpoints JSON documentados acima.
- Clientes de exemplo open-source (VB.NET · C# · Python) — fluxos completos de login/heartbeat/envelope, prontos a copiar
- Quick Start no painel — 5 passos guiados que geram snippets funcionais em 9 linguagens com as suas credenciais reais
- OpenAPI 3.1 spec (
openapi.json) — one-click import into Postman / Insomnia, or feed it to your code generator
Pronto para integrar?
Crie uma conta gratuita, registe uma app e copie o seu X-App-Secret do painel.