Wabroker.Sdk
0.14.0
dotnet add package Wabroker.Sdk --version 0.14.0
NuGet\Install-Package Wabroker.Sdk -Version 0.14.0
<PackageReference Include="Wabroker.Sdk" Version="0.14.0" />
<PackageVersion Include="Wabroker.Sdk" Version="0.14.0" />
<PackageReference Include="Wabroker.Sdk" />
paket add Wabroker.Sdk --version 0.14.0
#r "nuget: Wabroker.Sdk, 0.14.0"
#:package Wabroker.Sdk@0.14.0
#addin nuget:?package=Wabroker.Sdk&version=0.14.0
#tool nuget:?package=Wabroker.Sdk&version=0.14.0
Wabroker.Sdk
Cliente .NET (net8.0) para a API do broker Wabroker (multi-provider WhatsApp:
Meta Cloud API, WAHA, Evolution). Para os recursos que já cobre (veja
"Recursos cobertos" abaixo), espelha campo a campo o cliente TypeScript
@wabroker/sdk (packages/sdk/src/client.ts) — mesmos paths, verbos e formatos de
erro; o namespace do provider (wamid/Baileys) nunca cruza a fronteira do contrato.
A URL final de cada chamada é {BaseUrl}/{ApiVersion}{path} — por padrão
https://api.grwthy.com/v1/... (veja ApiVersion em "Criar o client").
A v0.2.0 ainda não cobre todos os recursos tenant-facing do SDK TypeScript —
veja "Cobertura / Roadmap".
Instalar
dotnet add package Wabroker.Sdk
Criar o client
Caminho feliz — só ApiKey é obrigatório; BaseUrl assume o SaaS
(https://api.grwthy.com) e ApiVersion assume "v1":
using Wabroker;
var client = new WabrokerClient(new WabrokerClientOptions
{
ApiKey = "sk_tn_...", // só no header Authorization — nunca logue nem coloque na URL
});
Para self-host ou apontar para outra versão da API, sobrescreva BaseUrl
e/ou ApiVersion:
var client = new WabrokerClient(new WabrokerClientOptions
{
BaseUrl = new Uri("https://broker.minhaempresa.com.br"), // self-host
ApiVersion = "v2", // opcional — compõe o path: {BaseUrl}/{ApiVersion}/...
ApiKey = "sk_tn_...",
});
A ApiKey identifica o tenant; toda chamada é automaticamente escopada a ele —
não há como (nem por que) informar tenantId em nenhum método.
Enviar uma mensagem
using Wabroker.Models;
var result = await client.Messages.SendAsync(
channelRef: "ch_abc123", // id do canal ou o número E.164 sem "+"
new SendMessageInput
{
To = "5511999998888",
Content = new TextContent("Olá! Seu pedido foi confirmado."),
IdempotencyKey = Guid.NewGuid().ToString(),
});
Console.WriteLine(result.MessageId); // sempre "msg_...", nunca o id do provider
Content aceita qualquer uma das cinco variantes de OutboundContent:
TextContent, MediaContent, TemplateContent, InteractiveContent e
ReactionContent.
IdempotencyKey é obrigatório: reenviar a mesma chave para o mesmo tenant
devolve o resultado do envio original em vez de duplicar o disparo.
Metadata (opcional, IReadOnlyDictionary<string, string>) é um dado seu,
totalmente opaco para o broker — nunca interpretado, indexado ou logado, só
ecoado de volta em message.sent. O cap de forma (≤20 chaves, chave ≤64
caracteres, valor ≤512 caracteres, total serializado ≤4096 bytes) é validado
no servidor; o SDK não revalida. Omitido → omitido no evento (nunca null).
var result = await client.Messages.SendAsync("ch_abc123", new SendMessageInput
{
To = "5511999998888",
Content = new TextContent("Olá! Seu pedido foi confirmado."),
IdempotencyKey = Guid.NewGuid().ToString(),
Metadata = new Dictionary<string, string> { ["contrato"] = "CT-88213" },
});
Enviar por um pool
Um pool agrupa canais e o broker escolhe o número ocioso (LRU) na hora de
admitir a mensagem — útil para distribuir volume sem o chamador saber qual
canal está livre. O poolRef recomendado é o slug do pool (fixo, não
muda quando o pool é renomeado); o id pl_… também funciona:
var result = await client.Messages.SendToPoolAsync(
poolRef: "pool-de-vendas",
new SendMessageInput
{
To = "5511999998888",
Content = new TextContent("Oi!"),
IdempotencyKey = Guid.NewGuid().ToString(),
});
Verificar um webhook
O broker assina eventos de webhook no estilo Stripe: header
t=<unix>,v1=<hmac-hex>, HMAC-SHA256 de {t}.{body} com o segredo do tenant.
using Wabroker;
// body = corpo cru (string) recebido na requisição; NUNCA desserialize antes de verificar.
// header = valor do header de assinatura (ex.: "X-WaBroker-Signature").
var evento = WabrokerWebhooks.VerifyAndParse<MeuEventoDeWebhook>(body, header, secret);
VerifyAndParse<T> lança WabrokerApiException com
WabrokerErrorCode.InvalidSignature se a assinatura for inválida ou estiver
fora da janela de tolerância (5 minutos por padrão). Se só a verificação
booleana interessar, use WabrokerWebhooks.VerifySignature(body, header, secret).
Injeção de dependência (ASP.NET Core / Generic Host)
using Wabroker;
builder.Services.AddWabrokerClient(o =>
{
o.ApiKey = builder.Configuration["Wabroker:ApiKey"]!;
// Opcionais — omita para usar o SaaS (https://api.grwthy.com) na v1:
// o.BaseUrl = new Uri(builder.Configuration["Wabroker:BaseUrl"]!); // self-host
// o.ApiVersion = "v2";
});
AddWabrokerClient registra o WabrokerClient como singleton, resolvendo o
HttpClient via IHttpClientFactory (nome lógico "Wabroker") — evita
exaustão de sockets em aplicações de longa duração. Só ApiKey é obrigatório;
BaseUrl (default https://api.grwthy.com) e ApiVersion (default "v1")
são opcionais. Se ApiKey faltar, a primeira resolução do WabrokerClient
lança InvalidOperationException (a mensagem nunca inclui o valor da API key).
Depois, injete normalmente:
public sealed class NotificacaoService(WabrokerClient wabroker)
{
public Task EnviarAsync(string to, string texto) =>
wabroker.Messages.SendAsync("ch_abc123", new SendMessageInput
{
To = to,
Content = new TextContent(texto),
IdempotencyKey = Guid.NewGuid().ToString(),
});
}
Erros
Toda falha não-2xx vira WabrokerApiException, com Code de uma taxonomia
fechada (WabrokerErrorCode), HttpStatus, Retryable e, quando presente,
RetryAfter (segundos). Um timeout de rede depois da requisição já ter saído
não é reinterpretado como falha definitiva pelo SDK — o chamador decide como
tratar a incerteza; o SDK só normaliza o erro de transporte
(WabrokerErrorCode.Timeout/NetworkError), sem tentar de novo sozinho.
try
{
await client.Messages.SendAsync(channelRef, input);
}
catch (WabrokerApiException ex) when (ex.Code == WabrokerErrorCode.RecipientSuppressed)
{
// destinatário na lista de supressão/opt-out do tenant
}
Recursos cobertos (paridade com client.ts)
Os paths abaixo omitem o prefixo {BaseUrl}/{ApiVersion} (ex.: channels vira
https://api.grwthy.com/v1/channels com as opções default).
| Recurso | Client | Endpoints |
|---|---|---|
| Mensagens | client.Messages |
channels/{ref}/messages(/batch), pools/{ref}/messages(/batch), messages/{id}, messages, messages/metrics |
| Canais | client.Channels |
channels, channels/connect(/{id}), channels/{id}/* (conexão, credenciais, PIN, status, overview, eventos, jornada, tags), channels/metrics |
| Tags | client.Tags |
tags |
| Pools | client.Pools |
pools, pools/{id}/channels(/{channelId}) |
| Templates | client.Templates |
templates, templates/{id}, templates/sync |
| Entregas | client.Deliveries |
deliveries |
| Supressões | client.Suppressions |
suppressions |
| Membros | client.Members |
members, members/{userId} |
| Aquecimento | client.Warming |
warming/strategies, warming/enrollments(/{id}), warming/tier |
| Webhooks | WabrokerWebhooks |
verificação/parse de assinatura (nenhum endpoint HTTP — recebido pelo consumidor) |
Um teste de reflexão (Wabroker.Sdk.Tests/ParityTests.cs) mantém este índice
honesto: falha se um método esperado desaparecer de um sub-client.
Cobertura / Roadmap
A v0.2.0 cobre os 9 recursos tenant-facing listados acima (mensagens,
canais, tags, pools, templates, entregas, supressões, membros, aquecimento) mais
a verificação de assinatura de webhook, com paridade 1:1 em relação ao
@wabroker/sdk TypeScript dentro desses recursos.
Os seguintes recursos do SDK TypeScript ainda não têm client .NET e ficam para versões futuras:
- Billing (
billing/*) - API keys (
api-keys/*) - Settings (
settings/*) - Webhooks — configuração/rotação de segredo (
webhooks/config,webhooks/rotate-secret; a verificação de assinatura recebida já está coberta porWabrokerWebhooks) - Compliance — erasure/export/risk-acceptance (
compliance/*) - Meta — descoberta de árvore/embedded signup (
meta/discover,meta/embedded-signup) - Me — identidade do chamador (
me,me/tenants)
Publicação
dotnet nuget push no NuGet.org é uma ação do dono do pacote (conta + API
key) — não faz parte deste fluxo.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.Http (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.