
Cliente .NET tipado, sem dependências externas, para a API v3 do Asaas.
Instalação · Quick Start · Managers · Conformidade · Changelog · Contribuir
- Visão Geral
- Destaques
- Requisitos
- Instalação
- Quick Start
- Conceitos Centrais
- Managers Disponíveis
- Exemplos por Domínio
- Configuração Avançada
- Qualidade e Conformidade
- Testes
- Arquitetura
- Versionamento
- Roadmap
- Contribuindo
- Segurança
- Licença
- Aviso
Asaas.Api é um SDK .NET não-oficial que cobre 100% da API v3 documentada do Asaas — mais de 150 endpoints distribuídos em 27 domain managers. Foi projetado para ser:
- Type-safe: enums tipados para todos os status, billing types, frequências e códigos. Sem strings mágicas.
- Schema-first: cada modelo é verificado endpoint-a-endpoint contra a especificação OpenAPI oficial via MCP. Contract tests congelam o shape JSON.
- Sem dependências externas: usa apenas
System.Text.Json(built-in do .NET 10). - Production-ready: 664 testes unit/contract + 15 integration tests reais contra
api-sandbox.asaas.comrodando em CI nightly.
Veja CONFORMANCE.md para o relatório de auditoria endpoint-a-endpoint.
- 27 managers prontos para usar — Customer, Payment, Subscription, Installment, Pix (estático, automático, recorrente), Webhook, Invoice, Anticipation, Transfer, PaymentLink, CreditCard, PaymentDunning, BillPayment, MobilePhoneRecharge, Notification, FiscalInfo, Finance, MyAccount, AsaasAccount, Wallet, CreditBureauReport, Chargeback, Escrow, Checkout, Sandbox.
- Modelos auditados contra o schema oficial — 42 famílias de bugs corrigidos na auditoria v3.2.0 (campos inventados removidos, enums incompletos completados, nullables corrigidos, casing de filtros padronizado).
- Cobertura de testes em três camadas:
- Unit tests para cada manager (chamada HTTP correta, route, método)
- Contract tests com fixtures dos exemplos oficiais MCP (shape JSON congelado)
- Integration tests opcionais contra sandbox real (skip automático sem token)
- Robustez de runtime:
bool?em filtros serializa lowercase (true/false, nãoTrue/False),decimal?usaInvariantCulture(12.5, não12,5em pt-BR),DateTime?usa formato ISO em qualquer cultura. - Sem mocks frágeis: o test runner real (Moq + MockHttpMessageHandler) injeta resposta HTTP no
BaseManager, validando o JSON exato que sairia na rede. - CI pronto: workflows GitHub Actions para build/test em todo PR e workflow separado de integration tests com secret
ASAAS_SANDBOX_TOKEN.
- .NET 10 SDK ou superior
- Conta Asaas com
access_token(sandbox ou produção)
dotnet add package Asaas.ApiInstall-Package Asaas.Api<PackageReferenceInclude="Asaas.Api"Version="3.2.0" />usingCodout.Apis.Asaas;usingCodout.Apis.Asaas.Core;usingCodout.Apis.Asaas.Models.Common.Enums;usingCodout.Apis.Asaas.Models.Customer;usingCodout.Apis.Asaas.Models.Payment;// 1. Configurevarsettings=newApiSettings(accessToken:Environment.GetEnvironmentVariable("ASAAS_TOKEN")!,applicationName:"MeuApp/1.0",asaasEnvironment:AsaasEnvironment.SANDBOX);varasaas=newAsaasApi(settings);// 2. Crie um clientevarcustomer=awaitasaas.Customer.Create(newCreateCustomerRequest{Name="Maria da Silva",CpfCnpj="01020558075",Email="maria@example.com"});if(!customer.WasSuccessful()){foreach(varerrorincustomer.Errors)Console.WriteLine($"[{error.Code}] {error.Description}");return;}// 3. Crie uma cobrança Pixvarpayment=awaitasaas.Payment.Create(newCreatePaymentRequest{CustomerId=customer.Data.Id,BillingType=BillingType.PIX,Value=150.00m,DueDate=DateTime.UtcNow.Date.AddDays(7),Description="Pedido #1234"});// 4. Obtenha o QR Code Pixvarqr=awaitasaas.Payment.GetPixQrCode(payment.Data.Id);Console.WriteLine(qr.Data.Payload);// copia-e-colaConsole.WriteLine(qr.Data.EncodedImage);// base64 PNG| Ambiente | Enum | Base URL |
|---|---|---|
| Sandbox | AsaasEnvironment.SANDBOX | https://api-sandbox.asaas.com/v3 |
| Produção | AsaasEnvironment.PRODUCTION | https://api.asaas.com/v3 |
Use sempre Sandbox durante desenvolvimento. O manager asaas.Sandbox lança InvalidOperationException se for chamado em ambiente de produção.
Toda chamada retorna ResponseObject<T> (item único) ou ResponseList<T> (paginada). Ambos expõem WasSuccessful(), StatusCode e Errors:
ResponseObject<Customer>response=awaitasaas.Customer.Find("cus_123");if(response.WasSuccessful()){Customercustomer=response.Data;Console.WriteLine(customer.Name);}else{Console.WriteLine($"Status: {response.StatusCode}");foreach(varerrorinresponse.Errors)Console.WriteLine($"[{error.Code}] {error.Description}");}ResponseList<Payment>list=awaitasaas.Payment.List(offset:0,limit:10);Console.WriteLine($"Total: {list.TotalCount} — HasMore: {list.HasMore}");foreach(varpaymentinlist.Data)Console.WriteLine($"{payment.Id} — R$ {payment.Value} — {payment.Status}");A maioria dos List aceita um filtro opcional. Todos os filtros são objetos tipados que herdam de RequestParameters:
varpayments=awaitasaas.Payment.List(0,20,newPaymentListFilter{CustomerId="cus_123",BillingType=BillingType.PIX,Status=PaymentStatus.PENDING,DueDateGE=DateTime.UtcNow.Date,DueDateLE=DateTime.UtcNow.Date.AddMonths(1),Anticipated=false});bool?, DateTime?, decimal? e enums são serializados no formato exato que a API exige, com fallback para InvariantCulture (resolve o bug clássico de 12,5 em vez de 12.5 em pt-BR).
varresult=awaitasaas.Payment.Create(request);if(result.StatusCode==HttpStatusCode.BadRequest){// Validação de regras de negócio do AsaasvarinvalidCustomer=result.Errors.FirstOrDefault(e =>e.Code=="invalid_customer");if(invalidCustomeris not null)// cliente não existe ou não tem cobrança permitida
...}if(result.StatusCode==HttpStatusCode.Unauthorized)// access_token inválido ou expirado
...if(result.StatusCode==HttpStatusCode.TooManyRequests)// backoff exponencial recomendado
...A serialização JSON usa configuração centralizada em Core/JsonSerializerConfiguration.cs:
- camelCase automático (
CustomerId→customerId) null-ignoring (campos não setados não vão na requisição)- enums como string (com
SafeEnumConverterFactoryque aceita valores novos sem quebrar) - datas flexíveis (aceita
2025-01-01,2025-01-01T10:00:00,2025-01-01 10:00:00, etc.)
Query strings (filtros) usam RequestParameters que sempre serializa em InvariantCulture, independente da cultura do thread.
| Manager | Propriedade | Endpoints | Descrição |
|---|---|---|---|
| Clientes | asaas.Customer | 7 | CRUD + notificações |
| Cobranças | asaas.Payment | 28+ | Boleto/Pix/Cartão + splits + refunds + documents + billing/viewing info + simulate + limits |
| Parcelamentos | asaas.Installment | 10 | CRUD + refund + splits + paymentBook |
| Assinaturas | asaas.Subscription | 12 | CRUD + creditCard + invoiceSettings + payments |
| Links de pagamento | asaas.PaymentLink | 11 | CRUD + imagens |
| Pix | asaas.Pix | 13 | AddressKeys, QrCodes, Transactions (com filter), tokenBucket, decode, pay |
| Pix Automático | asaas.PixAutomatic | 6 | Autorizações recorrentes Bacen + payment instructions |
| Pix Recorrente | asaas.PixRecurring | 5 | Recorrências parceladas + itens |
| Webhooks | asaas.Webhook | 6 | CRUD + removeBackoff (~100 eventos disponíveis) |
| Notas Fiscais | asaas.Invoice | 7 | Schedule, Find, List (com 7 filtros), Update, Authorize, Cancel |
| Informações Fiscais | asaas.FiscalInfo | 4 | CreateOrUpdate + Find + lookups municipais |
| Financeiro | asaas.Finance | 4 | Balance + Statistics (com filter) + Split |
| Transferências | asaas.Transfer | 5 | Para Asaas/banco/Pix + Find + List + Cancel |
| Antecipações | asaas.Anticipation | 8 | CRUD + Simulate + Limits + Automatic configuration |
| Negativações | asaas.PaymentDunning | 9 | CRUD + Simulate + History + PartialPayments + ResendDocument |
| Pagamento de contas | asaas.BillPayment | 5 | CRUD + Simulate + Cancel |
| Recarga celular | asaas.MobilePhoneRecharge | 5 | CRUD + GetProvider |
| Notificações | asaas.Notification | 2 | Update + BatchUpdate |
| Cartão de crédito | asaas.CreditCard | 3 | TokenizeCreditCard + PreAuthorization config |
| Contas Asaas (subaccounts) | asaas.AsaasAccount | 6 | CRUD + ResendActivationLink + AccessTokens |
| Minha conta | asaas.MyAccount | 10 | CommercialInfo + Status + Fees + AccountNumber + PaymentCheckoutConfig + Documents |
| Carteiras | asaas.Wallet | 1 | List |
| Consulta SERASA | asaas.CreditBureauReport | 3 | Create + Find + List (com filter) |
| Chargebacks | asaas.Chargeback | 3 | List + FindByPayment + CreateDispute |
| Escrow | asaas.Escrow | 6 | Configuração subconta/padrão + payment escrow |
| Checkout | asaas.Checkout | 2 | Create + Cancel |
| Sandbox | asaas.Sandbox | 3 | ApproveAccount + ConfirmPayment + ForceOverdue (bloqueado em PRODUCTION) |
Lista completa de endpoints por manager: CONFORMANCE.md §1–§29.
usingCodout.Apis.Asaas.Models.Common;usingCodout.Apis.Asaas.Models.Common.Enums;usingCodout.Apis.Asaas.Models.Payment;// Pixvarpix=awaitasaas.Payment.Create(newCreatePaymentRequest{CustomerId="cus_123",BillingType=BillingType.PIX,Value=150m,DueDate=DateTime.UtcNow.Date.AddDays(7),Description="Pedido #1234"});// Boleto com multa e jurosvarboleto=awaitasaas.Payment.Create(newCreatePaymentRequest{CustomerId="cus_123",BillingType=BillingType.BOLETO,Value=1000m,DueDate=DateTime.UtcNow.Date.AddDays(7),Discount=newDiscount{Value=50m,DueDateLimitDays=3,Type=DiscountType.FIXED},Interest=newInterest{Value=2m},// % ao mêsFine=newFine{Value=1m,Type=FineType.PERCENTAGE}});// Cartão tokenizado (em endpoint dedicado)varwithCard=awaitasaas.Payment.CreateWithCreditCard(newCreatePaymentRequest{CustomerId="cus_123",BillingType=BillingType.CREDIT_CARD,Value=299.90m,DueDate=DateTime.UtcNow.Date,CreditCardToken="tok_a75a1d98-c52d-4a6b",// tokenizado previamenteRemoteIp="200.123.45.67"});usingCodout.Apis.Asaas.Models.Subscription;usingCodout.Apis.Asaas.Models.Subscription.Enums;varsub=awaitasaas.Subscription.Create(newCreateSubscriptionRequest{CustomerId="cus_123",BillingType=BillingType.CREDIT_CARD,Value=99.90m,NextDueDate=DateTime.UtcNow.Date.AddDays(30),Cycle=Cycle.MONTHLY,Description="Plano Premium",CreditCard=newCreditCardRequest{/* ... */},CreditCardHolderInfo=newCreditCardHolderInfoRequest{/* ... */}});// Listar cobranças geradas pela assinaturavarpayments=awaitasaas.Subscription.ListPayments("sub_123",0,20);// Filtros novos (v3.2.0 — B-27e)varfiltered=awaitasaas.Subscription.List(0,50,newSubscriptionListFilter{Status=SubscriptionStatus.INACTIVE,DeletedOnly=false,Sort="dateCreated",Order="desc"});usingCodout.Apis.Asaas.Models.PaymentLink;usingCodout.Apis.Asaas.Models.PaymentLink.Enums;varlink=awaitasaas.PaymentLink.Create(newCreatePaymentLinkRequest{Name="Produto XYZ",Value=199.90m,BillingType=BillingType.UNDEFINED,ChargeType=ChargeType.DETACHED,DueDateLimitDays=10});Console.WriteLine($"Compartilhe: {link.Data.Url}");usingCodout.Apis.Asaas.Models.Pix;usingCodout.Apis.Asaas.Models.Pix.Enums;// Criar QR Code estáticovarqr=awaitasaas.Pix.CreateStaticQrCode(newCreatePixStaticQrCodeRequest{AddressKey="minha-chave-pix",Description="Doação",Value=50m});// Criar chave EVP (aleatória)varkey=awaitasaas.Pix.CreateAddressKey(newCreatePixAddressKeyRequest{Type=PixAddressKeyType.EVP});// Listar transações com filtro de status (v3.2.0 — novo)vartxs=awaitasaas.Pix.ListTransactions(0,20,newPixTransactionListFilter{Status=PixTransactionStatus.AWAITING_REQUEST});usingCodout.Apis.Asaas.Models.Webhook;usingCodout.Apis.Asaas.Models.Webhook.Enums;varwebhook=awaitasaas.Webhook.Create(newCreateWebhookRequest{Name="Notificações de pagamento",Url="https://meusite.com/webhook/asaas",Email="ops@meusite.com",Enabled=true,Interrupted=false,ApiVersion=3,AuthToken="whsec_min_32_caracteres_para_assinar_callbacks",SendType=WebhookSendType.SEQUENTIALLY,Events=[WebhookEvent.PAYMENT_CONFIRMED,WebhookEvent.PAYMENT_RECEIVED,WebhookEvent.PAYMENT_OVERDUE,WebhookEvent.PAYMENT_REFUNDED]});Nota: Este SDK expõe
WebhookManagerpara configurar endpoints, mas não fornece decoders tipados para os payloads que o Asaas envia para a sua URL. A deserialização do payload recebido fica a cargo do consumidor.
usingCodout.Apis.Asaas.Models.Transfer;usingCodout.Apis.Asaas.Models.Transfer.Enums;// Para outra conta Asaas (POST /v3/transfers/)awaitasaas.Transfer.TransferToAsaasAccount(newAsaasAccountTransferRequest{WalletId="wallet_destino",Value=500m});// Para banco externo (TED ou Pix — POST /v3/transfers)awaitasaas.Transfer.TransferToBankAccount(newBankAccountTransferRequest{Value=1000m,BankAccount=newBankAccount{Bank=newBank{Code="341"},OwnerName="Empresa LTDA",CpfCnpj="12345678000100",Agency="1234",Account="56789",AccountDigit="0",BankAccountType=BankAccountType.CONTA_CORRENTE}});// Listar com filtros de data (v3.2.0 — B-29h)varlist=awaitasaas.Transfer.List(0,50,newTransferListFilter{DateCreatedGE=DateTime.UtcNow.Date.AddDays(-30),DateCreatedLE=DateTime.UtcNow.Date});usingCodout.Apis.Asaas.Models.Invoice;usingCodout.Apis.Asaas.Models.Common;varinvoice=awaitasaas.Invoice.Schedule(newCreateInvoiceRequest{PaymentId="pay_123",ServiceDescription="Serviço de consultoria",Observations="Referente ao mês de janeiro",Value=1500m,Deductions=0m,EffectiveDate=DateTime.UtcNow.Date,MunicipalServiceName="Consultoria em TI",Taxes=newTaxes{RetainIss=false,Iss=2m,Pis=0.65m,Cofins=3m,Csll=1m,Inss=0m,Ir=1.5m}});awaitasaas.Invoice.Authorize(invoice.Data.Id);// Lookup de códigos municipaisvarservices=awaitasaas.FiscalInfo.ListServices(description:"consultoria");varbalance=awaitasaas.Finance.GetBalance();Console.WriteLine($"Saldo: R$ {balance.Data.Value}");// Estatísticas com filtros (v3.2.0 — B-37b)varstats=awaitasaas.Finance.GetPaymentStatistics(newPaymentStatisticsFilter{BillingType=BillingType.PIX,Status=PaymentStatus.RECEIVED,DateCreatedGE=DateTime.UtcNow.Date.AddDays(-30),DateCreatedLE=DateTime.UtcNow.Date});Console.WriteLine($"Quantidade: {stats.Data.Quantity} — Total: R$ {stats.Data.Value}");// Split a receber/enviar (v3.2.0 — schema corrigido B-37a)varsplit=awaitasaas.Finance.GetSplitStatistics();Console.WriteLine($"A receber: R$ {split.Data.Income} — A enviar: R$ {split.Data.Value}");// Em AsaasEnvironment.SANDBOX você pode acelerar fluxos de teste:awaitasaas.Sandbox.ApproveAccount();// aprova conta sandboxawaitasaas.Sandbox.ConfirmPayment("pay_123");// confirma pagamento sem boleto/pixawaitasaas.Sandbox.ForceOverdue("pay_123");// força vencimento imediato// Em PRODUCTION todos lançam InvalidOperationException antes de fazer HTTP.varsettings=newApiSettings("TOKEN","MeuApp/1.0",AsaasEnvironment.PRODUCTION){TimeOut=TimeSpan.FromSeconds(60)};O parâmetro applicationName em ApiSettings se torna parte do User-Agent da requisição, ajudando o suporte Asaas a identificar a integração em caso de troubleshooting:
newApiSettings("TOKEN","ECommerceXYZ/2.5.0",AsaasEnvironment.PRODUCTION);// User-Agent enviado: ECommerceXYZ/2.5.0BaseManager usa um SocketsHttpHandler estático e compartilhado por toda a instância de AsaasApi. Recomenda-se manter um único AsaasApi como singleton ao longo do ciclo de vida da aplicação (registrar no DI com AddSingleton).
// ASP.NET Corebuilder.Services.AddSingleton(_ =>newAsaasApi(newApiSettings(accessToken:builder.Configuration["Asaas:Token"]!,applicationName:"MeuApp/1.0",asaasEnvironment:AsaasEnvironment.PRODUCTION)));Esta biblioteca passa por auditoria schema-first contínua contra o MCP oficial do Asaas, garantindo que cada modelo, enum, filtro e nome de campo bate exatamente com a especificação OpenAPI publicada.
| Métrica | Valor |
|---|---|
| Managers auditados | 27 / 27 (100%) |
| Endpoints cobertos | ~150 |
| Famílias de bugs corrigidos | 42 (B-19 a B-42) |
| Testes unit + contract | 664 passando |
| Integration tests sandbox | 15 / 15 passando |
| Warnings de build | 0 |
Relatório completo: CONFORMANCE.md — inclui tabela endpoint-a-endpoint por manager, lista de bugs por padrão (envelope, casing, nullable, enums inventados, etc.) e riscos remanescentes classificados.
dotnet build Codout.Apis.Asaas/# Roda todos os testes que não dependem do sandbox
dotnet test Codout.Apis.Asaas.Tests/ --filter "Category!=Integration"# Tests de um manager específico
dotnet test Codout.Apis.Asaas.Tests/ --filter "FullyQualifiedName~CustomerManagerTests"Integration tests fazem chamadas reais contra api-sandbox.asaas.com. São puladas automaticamente quando a variável de ambiente ASAAS_SANDBOX_TOKEN está vazia — o CI local não quebra:
$env:ASAAS_SANDBOX_TOKEN="aact_YTU0..."
dotnet test Codout.Apis.Asaas.Tests/--filter "Category=Integration"O repositório expõe dois workflows GitHub Actions:
ci.yml— roda em todo push/PR. Build + testes unit/contract (integration filtrados fora).integration-sandbox.yml— dispatch manual + nightly às 04:00 UTC. Usa o secretASAAS_SANDBOX_TOKENconfigurado no repositório.
dotnet pack Codout.Apis.Asaas/ -c ReleaseCodout.Apis.Asaas/
├── AsaasApi.cs # Facade — entry point com 27 managers via Lazy<T>
├── Core/
│ ├── ApiSettings.cs # Configuração (token, ambiente, timeout, app name)
│ ├── BaseManager.cs # Base HTTP (GET/POST/PUT/DELETE), SocketsHttpHandler estático
│ ├── JsonSerializerConfiguration.cs # camelCase + SafeEnumConverterFactory + FlexibleDateTimeConverter
│ ├── RequestParameters.cs # Query string builder (InvariantCulture, bool lowercase)
│ ├── Response/
│ │ ├── Base/BaseResponse.cs # StatusCode + Errors + WasSuccessful()
│ │ ├── ResponseObject<T>.cs
│ │ └── ResponseList<T>.cs # envelope padrão {object, hasMore, totalCount, limit, offset, data}
│ └── Extension/ # DateTime, StatusCode, String helpers
├── Managers/ # 27 domain managers
└── Models/ # Request/Response por domínio (1 classe por arquivo)
├── Customer/
├── Payment/
├── Pix/
├── ...
└── Common/ # Discount, Interest, Fine, CreditCard, Split, etc.
Este projeto segue Versionamento Semântico:
- MAJOR (
x.0.0): mudanças incompatíveis — campos removidos, tipos alterados, métodos renomeados. - MINOR (
3.x.0): novos endpoints, novos campos opcionais, novos filtros, bug fixes que mudem tipo de campo opcional (e.g.string→enum?). - PATCH (
3.2.x): bug fixes não-comportamentais, melhorias de doc, cleanup.
Cada release tem uma entrada detalhada no CHANGELOG.md com:
- Lista de breaking changes por modelo
- Bugs corrigidos com referência ao código B-XX rastreável
- Métricas de testes
Itens não-bloqueantes que podem entrar em releases futuras:
- Decoders tipados para os payloads de webhook recebidos do Asaas (atualmente, consumidores deserializam manualmente).
- Lookups adicionais do FiscalInfo (
federalServiceCodes,nbsCodes,operationIndicatorCodes,taxClassificationCodes,taxSituationCodes,nationalPortal). - Auditoria contínua quando a spec da Reforma Tributária estabilizar.
Contribuições são bem-vindas! Para mudanças significativas, abra uma issue primeiro para discutir o que você gostaria de mudar.
- Faça fork do repositório.
- Crie uma branch para sua feature ou fix (
git checkout -b feature/minha-feature). - Audite o(s) endpoint(s) afetado(s) contra o MCP oficial. Adicione/atualize o fixture em
Codout.Apis.Asaas.Tests/Fixtures/e o contract test correspondente. - Garanta que
dotnet test --filter "Category!=Integration"passa. - Atualize CONFORMANCE.md com o(s) bug(s) corrigido(s) seguindo a numeração B-XX.
- Atualize CHANGELOG.md com a entrada.
- Abra um Pull Request descrevendo a mudança e referenciando o(s) endpoint(s) MCP consultado(s).
Se você descobrir uma vulnerabilidade de segurança, não abra uma issue pública. Em vez disso, envie um email para o autor (veja LICENSE para contato) ou abra um security advisory privado.
Por convenção:
- Tokens da Asaas (
access_token,ASAAS_SANDBOX_TOKEN) nunca devem ser commitados. - O
User-Agentenviado pela biblioteca não inclui PII. - Logs gerados pelo SDK não incluem o
access_token.
MIT © Clovis Coli Jr / Codout
Esta é uma biblioteca não-oficial. Não possui vínculo, endosso ou suporte oficial da Asaas. Para suporte oficial da API, consulte a documentação do Asaas ou o Help Center.
Para questões específicas deste SDK, use as issues do GitHub.