Asaas.Client
0.0.3
dotnet add package Asaas.Client --version 0.0.3
NuGet\Install-Package Asaas.Client -Version 0.0.3
<PackageReference Include="Asaas.Client" Version="0.0.3" />
<PackageVersion Include="Asaas.Client" Version="0.0.3" />
<PackageReference Include="Asaas.Client" />
paket add Asaas.Client --version 0.0.3
#r "nuget: Asaas.Client, 0.0.3"
#:package Asaas.Client@0.0.3
#addin nuget:?package=Asaas.Client&version=0.0.3
#tool nuget:?package=Asaas.Client&version=0.0.3
Asaas.Client
SDK em C# para integração com o Asaas — clientes, cobranças, assinaturas, notas fiscais, webhooks, subcontas e transferências.
Sumário
- Instalação · Configuração · Serviços disponíveis
- Clientes · Cobranças · Assinaturas · Webhooks
- Subcontas · Transferências e saques · Fluxo completo de subconta
- Enums · Tratamento de erros · Compatibilidade · Webhooks — recebimento
Instalação
dotnet add package Asaas.Client
Configuração
Informe o ambiente, a chave de API (access_token) e o User-Agent (nome da sua aplicação, obrigatório pelo Asaas).
| Ambiente | URL base |
|---|---|
AsaasEnvironment.SANDBOX |
https://api-sandbox.asaas.com/v3/ |
AsaasEnvironment.PRODUCAO |
https://api.asaas.com/v3/ |
Não versione a chave de API. Use user-secrets, variável de ambiente ou um cofre de segredos.
Uso direto
using Asaas.Client;
using Asaas.Client.Models.Options;
// Ambiente e credenciais
var client = new AsaasClient(AsaasEnvironment.SANDBOX, "minha-api-key", "MinhaAplicacao");
// A partir das opções
var client = new AsaasClient(new AsaasOptions()
{
Environment = AsaasEnvironment.SANDBOX,
AccessToken = "minha-api-key",
UserAgent = "MinhaAplicacao"
});
// A partir da configuração (seção "Asaas")
var client = new AsaasClient(configuration.GetAsaasOptions());
// Com log das requisições (passe um ILogger e ligue enableLogging)
var client = new AsaasClient(AsaasEnvironment.SANDBOX, "minha-api-key", "MinhaAplicacao", enableLogging: true, logger: meuLogger);
Injeção de dependência
// Program.cs ou Startup.cs
builder.Services.AddAsaas(AsaasEnvironment.PRODUCAO, "minha-api-key", "MinhaAplicacao");
// Com log das requisições
builder.Services.AddAsaas(AsaasEnvironment.PRODUCAO, "minha-api-key", "MinhaAplicacao", enableLogging: true);
// Com token do webhook
builder.Services.AddAsaas(AsaasEnvironment.PRODUCAO, "minha-api-key", "MinhaAplicacao", webhookToken: "token-secreto-do-webhook-com-32-caracteres");
// Ou via Options pattern
builder.Services.AddAsaas(options =>
{
options.Environment = AsaasEnvironment.PRODUCAO;
options.AccessToken = "minha-api-key";
options.UserAgent = "MinhaAplicacao";
options.WebhookToken = "token-secreto-do-webhook-com-32-caracteres";
options.EnableLogging = true;
});
// Ou a partir da configuração (seção "Asaas")
builder.Services.AddAsaas(builder.Configuration);
// No seu serviço ou controller
public class MeuServico(IAsaasClient client)
{
// use client.Cliente, client.Cobranca, client.Assinatura, client.Webhooks, client.Subconta, client.Transferencia
}
Configuração via appsettings.json
As opções (AsaasOptions) podem vir de qualquer fonte do IConfiguration: appsettings.json, user-secrets, variáveis de ambiente, cofre de segredos etc.
| Chave | Tipo | Obrigatória | Descrição |
|---|---|---|---|
Environment |
AsaasEnvironment |
Não | SANDBOX ou PRODUCAO. Padrão SANDBOX |
AccessToken |
string |
Sim | Chave de API, enviada no header access_token |
UserAgent |
string |
Sim | Nome da aplicação, enviado no header User-Agent |
WebhookToken |
string |
Não | Token esperado no header asaas-access-token (mesmo valor de AuthToken) |
EnableLogging |
bool |
Não | Liga o log de requisições e respostas. Padrão false |
Environment aceita o nome do enum sem diferenciar maiúsculas ("PRODUCAO", "producao") ou o número (0 = SANDBOX, 1 = PRODUCAO). Valor inválido lança InvalidOperationException no bind. Chave ausente → SANDBOX.
{
"Asaas": {
"Environment": "PRODUCAO",
"AccessToken": "minha-api-key",
"UserAgent": "MinhaAplicacao",
"WebhookToken": "token-secreto-do-webhook-com-32-caracteres",
"EnableLogging": false
}
}
A seção padrão é Asaas. Os dois métodos aceitam o parâmetro opcional section para ler de outra seção:
| Método | Uso |
|---|---|
services.AddAsaas(configuration, section = "Asaas") |
Registra o IAsaasClient no DI |
configuration.GetAsaasOptions(section = "Asaas") |
Retorna um AsaasOptions preenchido (sem DI) |
// Injeção de dependência — seção padrão "Asaas"
builder.Services.AddAsaas(builder.Configuration);
// Injeção de dependência — outra seção
builder.Services.AddAsaas(builder.Configuration, "Pagamentos:Asaas");
// Sem DI — seção padrão "Asaas"
var options = configuration.GetAsaasOptions();
var client = new AsaasClient(options);
// Sem DI — outra seção
var options = configuration.GetAsaasOptions("Pagamentos:Asaas");
Seção aninhada usa : como separador. Ex: "Pagamentos:Asaas" lê:
{
"Pagamentos": {
"Asaas": {
"Environment": "SANDBOX",
"AccessToken": "minha-api-key",
"UserAgent": "MinhaAplicacao"
}
}
}
Variáveis de ambiente usam __ como separador:
Asaas__Environment=PRODUCAO
Asaas__AccessToken=minha-api-key
Asaas__UserAgent=MinhaAplicacao
Asaas__WebhookToken=token-secreto-do-webhook-com-32-caracteres
Ler as opções já registradas (ex: WebhookToken no endpoint do webhook):
public class WebhookController(IOptions<AsaasOptions> options)
{
private readonly string webhookToken = options.Value.WebhookToken;
}
GetAsaasOptionsretorna umAsaasOptionsvazio quando a seção não existe.AccessTokeneUserAgentsão validados ao criar oAsaasClient.
Logging das requisições
Quando EnableLogging está ligado (e há um ILogger disponível — automático no DI), todas as requisições e respostas são logadas: método, URL, corpo, status HTTP e tempo de resposta.
info: Asaas.Client.AsaasClient[0]
Asaas -> POST https://api-sandbox.asaas.com/v3/customers
{"name":"Fulano","cpfCnpj":"12345678909"}
info: Asaas.Client.AsaasClient[0]
Asaas <- 200 POST https://api-sandbox.asaas.com/v3/customers (243ms)
{"object":"customer","id":"cus_000005219613",...}
- Request e resposta de sucesso → nível
Information; falhas (status ≥ 400) →Warning. EnableLogging = false(padrão) → nenhum log e zero overhead (os corpos nem são lidos).- Os corpos contêm dados pessoais (CPF, e-mail) — ligue só quando necessário.
Serviços Disponíveis
| Serviço | Endpoint | Descrição |
|---|---|---|
client.Cliente |
/v3/customers |
Clientes |
client.Cobranca |
/v3/payments |
Cobranças e QR Code Pix |
client.Assinatura |
/v3/subscriptions |
Assinaturas e cobranças geradas |
client.Assinatura.NotaFiscal |
/v3/subscriptions/{id}/invoiceSettings |
Configuração de nota fiscal |
client.Webhooks |
/v3/webhooks |
Configuração de webhooks |
client.Subconta |
/v3/accounts, /v3/myAccount |
Subcontas e situação cadastral |
client.Subconta.ChaveApi |
/v3/accounts/{id}/accessTokens |
Chaves de API das subcontas |
client.Subconta.DadosComerciais |
/v3/myAccount/commercialInfo |
Dados comerciais |
client.Subconta.Documento |
/v3/myAccount/documents |
Documentos da análise cadastral |
client.Transferencia |
/v3/transfers, /v3/finance/balance |
Saques e saldo |
Convenções
- Métodos:
Criar,Buscar,Listar,Atualizar,Excluir, nessa ordem, seguidos dos métodos específicos (QrCodePix,Status,Cancelar...). - Parâmetros:
id→request→ filtros →offset/limit→apiKey(sempre por último). ExcluirdevolveExclusaoResponse(Deleted,Id).- Listas devolvem
ListResponse<T>(Data,HasMore,TotalCount,Limit,Offset);limitpadrão 10, máx 100. - Campos nulos não são enviados. Na atualização parcial, preencha só o que deve mudar.
- Atualização parcial: assinatura, nota fiscal e webhook têm request própria (
AtualizarAssinaturaRequest,AtualizarNotaFiscalAssinaturaRequest,AtualizarWebhooksRequest). apiKey: métodos de subconta, documentos, dados comerciais e transferências aceitam a chave de API da subconta para agir em nome dela. SemapiKey, usam a chave configurada no cliente (conta raiz).
ClienteService (client.Cliente)
using Asaas.Client.Models.Requests;
var request = new ClienteRequest()
{
Name = "Fulano de Tal",
CpfCnpj = "12345678909",
Email = "fulano@email.com",
MobilePhone = "11999999999",
ExternalReference = "seu-identificador",
NotificationDisabled = true, // padrão true: o Asaas não envia notificações; null na atualização mantém o valor atual
PostalCode = "01310100",
Address = "Av. Paulista",
AddressNumber = "1000",
Complement = "Sala 1",
Province = "Bela Vista",
Phone = "1133334444", // opcionais
AdditionalEmails = "financeiro@empresa.com",
Company = "Empresa LTDA",
Observations = "Cliente VIP"
};
// Criar (guarde o Id)
var cliente = await client.Cliente.Criar(request);
// Buscar
var dados = await client.Cliente.Buscar(cliente.Id);
// Atualizar (campos nulos não são enviados; NotificationDisabled = null mantém o valor atual)
await client.Cliente.Atualizar(cliente.Id, new ClienteRequest()
{
Email = "novo@email.com",
NotificationDisabled = null
});
// Excluir
var exclusao = await client.Cliente.Excluir(cliente.Id);
// exclusao.Deleted, exclusao.Id
CobrancaService (client.Cobranca)
var request = new CobrancaRequest()
{
Customer = cliente.Id,
BillingType = AsaasBillingType.PIX,
Value = 99.90,
DueDate = DateTime.Today.AddDays(3),
Description = "Pedido 123",
ExternalReference = "123",
Discount = new DescontoRequest() { Value = 5, DueDateLimitDays = 0, Type = AsaasValueType.PERCENTAGE }, // opcional
Interest = new JurosRequest() { Value = 1 }, // opcional: 1% ao mês
Fine = new MultaRequest() { Value = 2, Type = AsaasValueType.PERCENTAGE } // opcional
// InstallmentCount = 3, InstallmentValue = 33.30 // parcelado (apenas criação)
};
// Criar
var cobranca = await client.Cobranca.Criar(request);
// cobranca.Id, cobranca.Status, cobranca.InvoiceUrl (fatura), cobranca.BankSlipUrl (boleto), cobranca.NetValue
// QR Code Pix
var pix = await client.Cobranca.QrCodePix(cobranca.Id);
// pix.EncodedImage (imagem base64), pix.Payload (copia e cola), pix.ExpirationDate
// Buscar
var dados = await client.Cobranca.Buscar(cobranca.Id);
// Atualizar (BillingType, Value e DueDate são obrigatórios; Customer e parcelamento são ignorados)
request.Value = 120.00;
await client.Cobranca.Atualizar(cobranca.Id, request);
// Excluir
var exclusao = await client.Cobranca.Excluir(cobranca.Id);
// exclusao.Deleted, exclusao.Id
| Campo | Uso |
|---|---|
Discount |
Desconto até DueDateLimitDays dias antes do vencimento (0 = até o vencimento) |
Interest |
Juros ao mês após o vencimento (percentual) |
Fine |
Multa após o vencimento (FIXED ou PERCENTAGE) |
InstallmentCount + InstallmentValue ou TotalValue |
Cobrança parcelada (só na criação; gera uma cobrança por parcela) |
Callback |
Redireciona o pagador após o pagamento |
Split de pagamento
Divide o valor recebido com outras contas Asaas (ex: subcontas), pelo WalletId. Vale também para AssinaturaRequest.
var request = new CobrancaRequest()
{
Customer = cliente.Id,
BillingType = AsaasBillingType.PIX,
Value = 100.00,
DueDate = DateTime.Today.AddDays(3),
Split =
[
new SplitRequest() { WalletId = subconta.WalletId, PercentualValue = 90 }, // 90% do valor líquido
new SplitRequest() { WalletId = "outra-carteira", FixedValue = 5.00 } // ou valor fixo
]
};
var cobranca = await client.Cobranca.Criar(request);
// cobranca.Split: Status (PENDING, DONE, CANCELLED...), TotalValue, CancellationReason
O WalletId vem de client.Subconta.Criar (subconta.WalletId). Acompanhe a liquidação pelo evento PAYMENT_SPLIT_DONE (ver WEBHOOK.md).
AssinaturaService (client.Assinatura)
var request = new AssinaturaRequest()
{
Customer = cliente.Id,
BillingType = AsaasBillingType.PIX,
Value = 49.90,
Cycle = AsaasCycle.MONTHLY,
NextDueDate = DateTime.Today.AddDays(1), // vencimento da primeira cobrança
Description = "Plano mensal",
EndDate = DateTime.Today.AddYears(1), // opcional
MaxPayments = 12, // opcional
ExternalReference = "assinatura-123",
Split = [new SplitRequest() { WalletId = subconta.WalletId, PercentualValue = 10 }], // opcional
Callback = new CallbackRequest() // opcional
{
SuccessUrl = "https://meu-sistema.com/obrigado",
AutoRedirect = true
}
};
// Criar
var assinatura = await client.Assinatura.Criar(request);
// Buscar
var dados = await client.Assinatura.Buscar(assinatura.Id);
// dados.Status: ACTIVE, INACTIVE ou EXPIRED
// Cobranças geradas pela assinatura (paginadas; limit padrão 10, máx 100)
var cobrancas = await client.Assinatura.ListarCobrancas(assinatura.Id, offset: 0, limit: 10, status: "PENDING");
// cobrancas.Data, cobrancas.HasMore, cobrancas.TotalCount
// Atualizar (parcial: só os campos informados mudam; por padrão, só as cobranças futuras)
await client.Assinatura.Atualizar(assinatura.Id, new AtualizarAssinaturaRequest()
{
Value = 59.90,
UpdatePendingPayments = true // aplica também às cobranças pendentes
});
// Suspender / reativar
await client.Assinatura.Atualizar(assinatura.Id, new AtualizarAssinaturaRequest() { Status = AsaasSubscriptionStatus.INACTIVE });
await client.Assinatura.Atualizar(assinatura.Id, new AtualizarAssinaturaRequest() { Status = AsaasSubscriptionStatus.ACTIVE, NextDueDate = DateTime.Today.AddDays(1) });
// Excluir
await client.Assinatura.Excluir(assinatura.Id);
Nota fiscal da assinatura (client.Assinatura.NotaFiscal)
var request = new NotaFiscalAssinaturaRequest()
{
MunicipalServiceId = "55021",
MunicipalServiceName = "Análise e desenvolvimento de sistemas.",
EffectiveDatePeriod = AsaasEffectiveDatePeriod.ON_PAYMENT_CONFIRMATION,
ReceivedOnly = true, // emite apenas para cobranças pagas (padrão do SDK true; do Asaas, false)
UpdatePayment = false, // true: desconta os impostos do valor da cobrança
Observations = "Mensalidade",
Taxes = new Taxes() // todas as alíquotas são obrigatórias (padrão 0)
{
ISS = 2,
PIS = 0.65,
COFINS = 3,
CSLL = 0,
INSS = 0,
IR = 0,
RetainIss = false
}
};
// Criar
await client.Assinatura.NotaFiscal.Criar(assinatura.Id, request);
// Buscar
var config = await client.Assinatura.NotaFiscal.Buscar(assinatura.Id);
// Atualizar (ex: emitir 5 dias antes do vencimento; Taxes é obrigatório e substituído por inteiro)
await client.Assinatura.NotaFiscal.Atualizar(assinatura.Id, new AtualizarNotaFiscalAssinaturaRequest()
{
EffectiveDatePeriod = AsaasEffectiveDatePeriod.BEFORE_PAYMENT_DUE_DATE,
DaysBeforeDueDate = 5, // 5, 10, 15, 30 ou 60
Taxes = request.Taxes
});
// Excluir
await client.Assinatura.NotaFiscal.Excluir(assinatura.Id);
WebhooksService (client.Webhooks)
var request = new WebhooksRequest()
{
Name = "Principal",
Url = "https://meu-sistema.com/webhook/asaas",
Email = "dev@meu-sistema.com",
AuthToken = "token-secreto-do-webhook-com-32-caracteres", // enviado no header asaas-access-token
SendType = AsaasSendType.SEQUENTIALLY,
Events = [AsaasWebhookEvent.PAYMENT_RECEIVED, AsaasWebhookEvent.PAYMENT_CONFIRMED, AsaasWebhookEvent.PAYMENT_OVERDUE]
};
// Criar
var webhook = await client.Webhooks.Criar(request);
// Buscar
var dados = await client.Webhooks.Buscar(webhook.Id);
// dados.Enabled, dados.Interrupted, dados.HasAuthToken, dados.PenalizedRequestsCount
// Listar
var webhooks = await client.Webhooks.Listar(offset: 0, limit: 10);
// Atualizar (parcial: só os campos informados mudam)
await client.Webhooks.Atualizar(webhook.Id, new AtualizarWebhooksRequest()
{
Interrupted = false // retoma a fila interrompida
});
// Remover penalização (retoma entregas atrasadas)
await client.Webhooks.RemoverPenalizacao(webhook.Id);
// Excluir
var exclusao = await client.Webhooks.Excluir(webhook.Id);
// exclusao.Deleted, exclusao.Id
AuthToken: 32 a 255 caracteres, sem espaços, diferente da chave de API. Limite de 10 webhooks por conta.
Recebimento e validação dos eventos: ver WEBHOOK.md.
SubcontaService (client.Subconta)
A conta raiz precisa ser pessoa jurídica. O corpo da criação é o mesmo nos dois modelos:
| Modelo | Habilitação | Onboarding |
|---|---|---|
| Normal | Padrão | Asaas envia e-mail de ativação; titular envia documentos pela interface do Asaas |
| BaaS | Gerente de contas habilita na conta raiz | Asaas não se comunica com o titular; sua plataforma conduz o envio (client.Subconta.Documento) |
var request = new SubcontaRequest()
{
Name = "Loja do Fulano",
Email = "fulano@email.com",
CpfCnpj = "12345678000199",
CompanyType = AsaasCompanyType.LIMITED, // pessoa jurídica
// BirthDate = new DateTime(1990, 1, 1), // pessoa física
MobilePhone = "11999999999",
IncomeValue = 25000,
Address = "Av. Paulista",
AddressNumber = "1000",
Province = "Bela Vista",
PostalCode = "01310100",
Webhooks = // opcional
[
new WebhooksRequest()
{
Name = "Subconta",
Url = "https://meu-sistema.com/webhook/asaas",
Email = "dev@meu-sistema.com",
AuthToken = "token-secreto-do-webhook-com-32-caracteres",
Events = [AsaasWebhookEvent.ACCOUNT_STATUS_GENERAL_APPROVAL_APPROVED, AsaasWebhookEvent.TRANSFER_DONE]
}
]
};
// Criar — guarde ApiKey e WalletId: a chave não é retornada novamente
var subconta = await client.Subconta.Criar(request);
// subconta.Id, subconta.WalletId, subconta.ApiKey, subconta.AccountNumber
// Buscar / listar
var dados = await client.Subconta.Buscar(subconta.Id);
var subcontas = await client.Subconta.Listar(cpfCnpj: "12345678000199", offset: 0, limit: 10);
Situação da conta
Consultas em /v3/myAccount usam a chave de API da subconta (sem chave → própria conta do cliente).
var status = await client.Subconta.Status(subconta.ApiKey);
// status.CommercialInfo, status.BankAccountInfo, status.Documentation, status.General
// PENDING, AWAITING_APPROVAL, APPROVED ou REJECTED
if (status.Aprovada) // General == APPROVED
{
// conta liberada
}
Para acompanhar sem consultar, use os eventos ACCOUNT_STATUS_* do webhook (ex: ACCOUNT_STATUS_GENERAL_APPROVAL_APPROVED).
// Sandbox: aprova a subconta na hora (a análise não acontece sozinha)
await client.Subconta.AprovarSandbox(subconta.ApiKey);
Dados comerciais (client.Subconta.DadosComerciais)
Quando CommercialInfo for REJECTED (ou expirar), consulte e reenvie todos os dados.
var comercial = await client.Subconta.DadosComerciais.Buscar(subconta.ApiKey);
// comercial.Status, comercial.DenialReason, comercial.CommercialInfoExpiration
await client.Subconta.DadosComerciais.Atualizar(new DadosComerciaisRequest()
{
PersonType = AsaasPersonType.JURIDICA,
CpfCnpj = "12345678000199",
CompanyType = AsaasCompanyType.LIMITED,
IncomeValue = 25000,
Email = "fulano@email.com",
MobilePhone = "11999999999",
PostalCode = "01310100",
Address = "Av. Paulista",
AddressNumber = "1000",
Province = "Bela Vista"
}, subconta.ApiKey);
Documentos (client.Subconta.Documento)
Aguarde ao menos 15 segundos após a criação antes de consultar.
var documentos = await client.Subconta.Documento.Listar(subconta.ApiKey);
foreach (var grupo in documentos.Data.Where(x => x.Status is AsaasDocumentStatus.NOT_SENT or AsaasDocumentStatus.REJECTED))
{
if (!string.IsNullOrWhiteSpace(grupo.OnboardingUrl))
{
// envie o titular ao link (documento de identificação + selfie); envio via API é recusado
continue;
}
await using var arquivo = File.OpenRead("contrato-social.pdf");
await client.Subconta.Documento.Criar(grupo.Id, grupo.Type, arquivo, "contrato-social.pdf", subconta.ApiKey);
}
// documentos.RejectReasons: motivos de reprovação
// Arquivo já enviado (Id em grupo.Documents)
var enviado = await client.Subconta.Documento.Buscar(arquivoId, subconta.ApiKey);
await client.Subconta.Documento.Atualizar(arquivoId, novoArquivo, "contrato-social.pdf", subconta.ApiKey);
await client.Subconta.Documento.Excluir(arquivoId, subconta.ApiKey);
A análise leva até 48h. No sandbox, use client.Subconta.AprovarSandbox.
Chaves de API (client.Subconta.ChaveApi)
Recupera o acesso quando a chave original foi perdida. Pré-requisitos: habilitar "Gerenciamento de Chaves de API de Subcontas" em Integrações > Chaves de API (expira em 2 horas) e ativar a lista de IPs permitidos com o IP da aplicação. Sem isso → 403.
// Listar (sem o valor da chave)
var chaves = await client.Subconta.ChaveApi.Listar(subconta.Id);
// Criar — guarde ApiKey: não é retornada novamente
var chave = await client.Subconta.ChaveApi.Criar(subconta.Id, new ChaveApiRequest()
{
Name = "Integração",
ExpirationDate = DateTime.Today.AddYears(1)
});
// Desativar
await client.Subconta.ChaveApi.Atualizar(subconta.Id, chave.Id, new ChaveApiRequest()
{
Name = "Integração",
Enabled = false,
ExpirationDate = DateTime.Today.AddYears(1)
});
// Excluir
await client.Subconta.ChaveApi.Excluir(subconta.Id, chave.Id);
Encerrar subconta (BaaS)
Irreversível. A chave da subconta é obrigatória, para não encerrar a conta raiz por engano.
var encerramento = await client.Subconta.Encerrar("Cliente cancelou o contrato", subconta.ApiKey);
TransferenciaService (client.Transferencia)
Saque para conta bancária de outra instituição ou chave Pix, ou transferência interna para outra conta Asaas. Informe a chave de API da subconta de origem (sem chave → conta do cliente).
// Saldo disponível
var saldo = await client.Transferencia.Saldo(subconta.ApiKey);
// Saque via chave Pix
var saque = await client.Transferencia.Criar(new TransferenciaRequest()
{
Value = 150.00,
PixAddressKey = "fulano@email.com",
PixAddressKeyType = AsaasPixAddressKeyType.EMAIL,
Description = "Saque",
ExternalReference = "saque-123"
}, subconta.ApiKey);
// Saque para conta bancária (Pix quando o banco participa, senão TED)
var saqueConta = await client.Transferencia.Criar(new TransferenciaRequest()
{
Value = 150.00,
OperationType = AsaasTransferOperationType.TED, // opcional
BankAccount = new ContaBancariaRequest()
{
Bank = new BancoRequest() { Code = "237" },
OwnerName = "Fulano de Tal",
CpfCnpj = "12345678000199",
Agency = "0001",
Account = "123456",
AccountDigit = "7",
BankAccountType = AsaasBankAccountType.CONTA_CORRENTE
}
}, subconta.ApiKey);
// saque.Id, saque.Status (PENDING, BANK_PROCESSING, DONE, CANCELLED, FAILED), saque.TransferFee, saque.Authorized
// Transferência interna (ex: da conta raiz para a subconta)
var interna = await client.Transferencia.Criar(new TransferenciaRequest()
{
Value = 50.00,
WalletId = subconta.WalletId
});
// Buscar
var dados = await client.Transferencia.Buscar(saque.Id, subconta.ApiKey);
// Listar (filtros opcionais)
var transferencias = await client.Transferencia.Listar(dateCreatedStart: DateTime.Today.AddDays(-30), dateCreatedEnd: DateTime.Today, offset: 0, limit: 10, apiKey: subconta.ApiKey);
// Cancelar (apenas PENDING)
if (dados.Cancelavel)
{
await client.Transferencia.Cancelar(saque.Id, subconta.ApiKey);
}
| Destino | Preencha |
|---|---|
| Chave Pix | PixAddressKey + PixAddressKeyType |
| Conta bancária | BankAccount (Pix se o banco participar, senão TED; force com OperationType) |
| Outra conta Asaas | WalletId (transferência interna) |
ScheduleDateagenda a transferência; sem ela, é imediata.Authorized = falseindica que o saque aguarda autorização por token (SMS/app).- Acompanhe pelos eventos
TRANSFER_*do webhook.
Fluxo completo de subconta
// 1. Criar a subconta (normal ou BaaS, conforme a conta raiz) e guardar Id, WalletId e ApiKey
var subconta = await client.Subconta.Criar(request);
// 2. BaaS: aguardar 15s e conduzir os documentos
await Task.Delay(TimeSpan.FromSeconds(15));
var documentos = await client.Subconta.Documento.Listar(subconta.ApiKey);
// OnboardingUrl → enviar o titular ao link; sem link → client.Subconta.Documento.Criar(...)
// 3. Acompanhar a aprovação (webhook ACCOUNT_STATUS_GENERAL_APPROVAL_APPROVED ou consulta)
var status = await client.Subconta.Status(subconta.ApiKey);
// 4. Receber: cobranças com split para a subconta
await client.Cobranca.Criar(new CobrancaRequest()
{
Customer = cliente.Id,
BillingType = AsaasBillingType.PIX,
Value = 100.00,
DueDate = DateTime.Today.AddDays(3),
Split = [new SplitRequest() { WalletId = subconta.WalletId, PercentualValue = 90 }]
});
// 5. Sacar: saldo e transferência em nome da subconta
var saldo = await client.Transferencia.Saldo(subconta.ApiKey);
if (status.Aprovada && saldo.Balance > 0)
{
await client.Transferencia.Criar(new TransferenciaRequest()
{
Value = saldo.Balance,
PixAddressKey = "12345678000199",
PixAddressKeyType = AsaasPixAddressKeyType.CNPJ
}, subconta.ApiKey);
}
Enums
| Enum | Valores |
|---|---|
AsaasEnvironment |
SANDBOX, PRODUCAO |
AsaasBillingType |
UNDEFINED (pagador escolhe), BOLETO, CREDIT_CARD, PIX; só no retorno: DEBIT_CARD, TRANSFER, DEPOSIT |
AsaasCycle |
WEEKLY, BIWEEKLY, MONTHLY, BIMONTHLY, QUARTERLY, SEMIANNUALLY, YEARLY |
AsaasEffectiveDatePeriod |
ON_PAYMENT_CONFIRMATION, ON_PAYMENT_DUE_DATE, BEFORE_PAYMENT_DUE_DATE, ON_DUE_DATE_MONTH, ON_NEXT_MONTH |
AsaasSendType |
SEQUENTIALLY (preserva a ordem), NON_SEQUENTIALLY (paralelo) |
AsaasWebhookEvent |
Eventos do webhook — ver WEBHOOK.md |
AsaasPersonType |
FISICA, JURIDICA |
AsaasCompanyType |
MEI, LIMITED, INDIVIDUAL, ASSOCIATION |
AsaasTaxRegime |
MEI, NATIONAL_SIMPLE, NORMAL_REGIME, UNKNOWN |
AsaasAccountStatus |
PENDING, AWAITING_APPROVAL, APPROVED, REJECTED |
AsaasDocumentType |
IDENTIFICATION, IDENTIFICATION_SELFIE, SOCIAL_CONTRACT, MEI_CERTIFICATE, ENTREPRENEUR_REQUIREMENT, ... |
AsaasDocumentStatus |
NOT_SENT, PENDING, APPROVED, REJECTED, IGNORED |
AsaasTransferOperationType |
PIX, TED |
AsaasPixAddressKeyType |
CPF, CNPJ, EMAIL, PHONE, EVP |
AsaasBankAccountType |
CONTA_CORRENTE, CONTA_POUPANCA |
AsaasValueType |
FIXED, PERCENTAGE (desconto e multa) |
AsaasSubscriptionStatus |
ACTIVE, INACTIVE (atualização de assinatura) |
Compatibilidade
Mudanças em relação à versão 0.0.2:
| Mudança | Impacto |
|---|---|
Assinatura.Atualizar, Assinatura.NotaFiscal.Atualizar e Webhooks.Atualizar recebem request própria de atualização |
A sobrecarga antiga continua funcionando, marcada como [Obsolete]. Atualizar(id, new() { ... }) sem o nome da classe fica ambíguo: informe a classe |
Excluir devolve ExclusaoResponse |
.Id continua funcionando |
ClienteRequest.NotificationDisabled e AssinaturaRequest.UpdatePendingPayments viraram bool? |
Atribuição igual; leitura como bool precisa de ajuste |
Taxes (request): alíquotas viraram double (padrão 0) |
Todas são obrigatórias no Asaas |
Deductions virou double? |
Aceita decimal |
NotaFiscalAssinaturaResponse.EffectiveDatePeriod virou nulável e passou a ler invoiceCreationPeriod |
Antes vinha sempre ON_PAYMENT_CONFIRMATION |
AsaasBillingType ganhou DEBIT_CARD, TRANSFER, DEPOSIT |
Só retorno; evita erro de leitura |
WebhookValidator.TryParse não lança exceção |
Retorna false para corpo inválido |
Tratamento de erros
Status HTTP de erro lança AsaasErrorException:
try
{
await client.Cobranca.Criar(request);
}
catch (AsaasErrorException ex) when (ex.StatusCode == HttpStatusCode.TooManyRequests)
{
// limite de requisições atingido
await Task.Delay(ex.RetryAfter ?? TimeSpan.FromSeconds(60));
}
catch (AsaasErrorException ex)
{
// ex.StatusCode → HttpStatusCode
// ex.Code → código do primeiro erro (ex: "invalid_value")
// ex.Message → descrições dos erros
// ex.Errors → lista completa (Code + Description)
// ex.RawBody → corpo bruto da resposta
// ex.RetryAfter → tempo até liberar o limite (header RateLimit-Reset) em respostas 429
foreach (var erro in ex.Errors)
{
Console.WriteLine($"{erro.Code}: {erro.Description}");
}
}
| 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 is compatible. 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 is compatible. 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. |
-
net10.0
- Microsoft.Extensions.Configuration.Binder (>= 10.0.12)
- Microsoft.Extensions.Http (>= 10.0.12)
-
net8.0
- Microsoft.Extensions.Configuration.Binder (>= 10.0.12)
- Microsoft.Extensions.Http (>= 10.0.12)
-
net9.0
- Microsoft.Extensions.Configuration.Binder (>= 10.0.12)
- Microsoft.Extensions.Http (>= 10.0.12)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.3 | 0 | 9/29/2026 |
| 0.0.2 | 69 | 9/24/2026 |
| 0.0.1 | 67 | 9/24/2026 |
| 0.0.1-preview.15 | 99 | 3/3/2026 |
| 0.0.1-preview.14 | 240 | 8/27/2025 |
| 0.0.1-preview.13 | 169 | 7/17/2025 |
| 0.0.1-preview.12 | 164 | 7/16/2025 |
| 0.0.1-preview.11 | 117 | 7/4/2025 |
| 0.0.1-preview.10 | 177 | 7/3/2025 |
| 0.0.1-preview.9 | 170 | 7/3/2025 |
| 0.0.1-preview.8 | 174 | 7/2/2025 |
| 0.0.1-preview.7 | 191 | 7/2/2025 |
| 0.0.1-preview.6 | 181 | 6/19/2025 |
| 0.0.1-preview.5 | 188 | 5/22/2025 |
| 0.0.1-preview.4 | 169 | 5/22/2025 |
| 0.0.1-preview.3 | 170 | 5/22/2025 |
| 0.0.1-preview.2 | 186 | 5/22/2025 |
| 0.0.1-preview.1 | 181 | 5/22/2025 |