Plataforma para gestão de Editoras, Parceiros, Clientes, Serviços, Projetos, Pagamentos e Financeiro — conectando editoras a parceiros criativos com checkout integrado e controle de saldos/saques.
Entidade raiz (tenant). Toda requisição é autenticada pela ApiKey de uma Editora. Possui clientes, parceiros vinculados e projetos.
Contratante vinculado a uma editora. Possui vínculo externo (VinculoId) e tipo customizável (Agente/Autor).
Prestador de serviço. Possui catálogo de serviços, saldo bloqueado/disponível, Pix e pode solicitar saques.
Oferta de um parceiro com valor, prazo, descrição, exigências e tags. Pode ser ativado ou inativado.
Vincula Cliente ↔ Parceiro dentro de uma Editora. Contém itens, pagamento, entregas, conversas e avaliações.
Saldo bloqueado ao iniciar projeto; liberado após aprovação. Checkout via Pagarme v5 (webhook x-hub-signature). Parceiro solicita saque; admin aprova/rejeita e confirma pagamento.
Todos os commands (ITransactionalRequest) geram um AuditLog na tabela AuditLogs com ação, módulo, ator (Editora/Parceiro/Usuário), IP, rota HTTP e resultado (sucesso/falha com erros).
{módulo}/api/{rota} — a API unificada usa MapGroup() para criar grupos de rota por módulo.
Exemplo: parceiro/api/parceiro/auth/login é tratado diretamente pelo grupo /parceiro sem proxy intermediário.
Rota: /admin/api/...
Gestão de clientes, rotação de ApiKey e processamento de pagamentos/webhooks.
Rota: /agente/api/...
Clientes tipo Agente: criação de projetos e itens, avaliações, mensagens e consulta de serviços.
Rota: /autor/api/...
Clientes tipo Autor: criação de projetos e itens, avaliações, mensagens e consulta de serviços.
Rota: /editora/api/...
Avaliações da editora, aprovação de parceiros, gestão de saques, monitoramento de projetos e stats.
Rota: /parceiro/api/...
Login, CRUD de serviços, financeiro (saldos/saques), mensagens, projetos e resumo do parceiro.
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | admin/api/cliente | Listar clientes (paginado) | ApiKey |
| GET | admin/api/cliente/{id} | Obter cliente por id | ApiKey |
| POST | admin/api/cliente | Cadastrar cliente | ApiKey |
| PUT | admin/api/cliente/{id} | Atualizar cliente | ApiKey |
| DELETE | admin/api/cliente/{id} | Excluir cliente | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | admin/api/editoras/{id}/rotate-key | Rotacionar ApiKey | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | admin/api/pagamentos/webhook/{gateway} | Webhook do gateway | Pública |
| POST | admin/api/pagamentos/confirmar | Confirmar pagamento | ApiKey |
| POST | admin/api/pagamentos/{projetoId}/reconciliar-taxa | Agendar reconciliação manual da taxa real do gateway | ApiKey |
appsettings.json seção TickerQ:Dashboard). Permite visualizar e gerenciar jobs em background.
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | agente/api/cliente | Cadastrar cliente (tipo Agente) | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | agente/api/projeto | Listar projetos | ApiKey |
| GET | agente/api/projeto/{id} | Obter projeto | ApiKey |
| GET | agente/api/projeto/{id}/avaliacoes | Avaliações do projeto | ApiKey |
| POST | agente/api/projeto | Criar projeto | ApiKey |
| POST | agente/api/projeto/{id}/pagamento/finalizar | Finalizar para pagamento | ApiKey |
| GET | agente/api/projeto/{id}/pagamento/link?clienteId={id} | Obter ou regerar link de checkout (Redis → gateway) | ApiKey |
| PATCH | agente/api/projeto/{id}/status/cancelado | Cancelar projeto | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | agente/api/projeto/{id}/itens | Adicionar item | ApiKey |
| DELETE | agente/api/projeto/{id}/itens/{itemId} | Remover item | ApiKey |
| PATCH | agente/api/projeto/{id}/itens/{itemId} | Atualizar quantidade | ApiKey |
| PATCH | agente/api/projeto/{id}/itens/{itemId}/briefing | Adicionar briefing | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | agente/api/avaliacao | Criar avaliação (origem Cliente) | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | agente/api/projeto/{projetoId}/mensagens | Enviar mensagem | ApiKey |
| GET | agente/api/projeto/{projetoId}/mensagens/conversa | Obter conversa | ApiKey |
| GET | agente/api/projeto/{projetoId}/mensagens/{mensagemId} | Obter mensagem | ApiKey |
| GET | agente/api/projeto/{projetoId}/mensagens/ultima | Última mensagem | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | agente/api/servico/{id} | Obter serviço | ApiKey |
| GET | agente/api/servico | Listar serviços | ApiKey |
| GET | agente/api/servico/parceiro/{parceiroId} | Serviços de parceiro | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | agente/api/parceiro/{id} | Obter parceiro por id | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | autor/api/cliente | Cadastrar cliente (tipo Autor) | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | autor/api/projeto | Listar projetos | ApiKey |
| GET | autor/api/projeto/{id} | Obter projeto | ApiKey |
| GET | autor/api/projeto/{id}/avaliacoes | Avaliações do projeto | ApiKey |
| POST | autor/api/projeto | Criar projeto | ApiKey |
| POST | autor/api/projeto/{id}/pagamento/finalizar | Finalizar para pagamento | ApiKey |
| GET | autor/api/projeto/{id}/pagamento/link?clienteId={id} | Obter ou regerar link de checkout (Redis → gateway) | ApiKey |
| PATCH | autor/api/projeto/{id}/status/cancelado | Cancelar projeto | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | autor/api/projeto/{id}/itens | Adicionar item | ApiKey |
| DELETE | autor/api/projeto/{id}/itens/{itemId} | Remover item | ApiKey |
| PATCH | autor/api/projeto/{id}/itens/{itemId} | Atualizar quantidade | ApiKey |
| PATCH | autor/api/projeto/{id}/itens/{itemId}/briefing | Adicionar briefing | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | autor/api/avaliacao | Criar avaliação (origem Cliente) | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | autor/api/projeto/{projetoId}/mensagens | Enviar mensagem | ApiKey |
| GET | autor/api/projeto/{projetoId}/mensagens/conversa | Obter conversa | ApiKey |
| GET | autor/api/projeto/{projetoId}/mensagens/{mensagemId} | Obter mensagem | ApiKey |
| GET | autor/api/projeto/{projetoId}/mensagens/ultima | Última mensagem | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | autor/api/servico/{id} | Obter serviço | ApiKey |
| GET | autor/api/servico | Listar serviços | ApiKey |
| GET | autor/api/servico/parceiro/{parceiroId} | Serviços de parceiro | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | autor/api/parceiro/{id} | Obter parceiro por id | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | editora/api/avaliacao | Criar avaliação (origem Editora) | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | editora/api/projeto/{projetoId}/mensagens/conversa | Obter conversa | ApiKey |
| GET | editora/api/projeto/{projetoId}/mensagens/{mensagemId} | Obter mensagem | ApiKey |
| GET | editora/api/projeto/{projetoId}/mensagens/ultima | Última mensagem | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | editora/api/servico/{id} | Obter serviço | ApiKey |
| GET | editora/api/servico | Listar serviços disponíveis | ApiKey |
| GET | editora/api/servico/parceiro/{parceiroId} | Listar serviços de um parceiro | ApiKey |
| GET | editora/api/servico/stats | Estatísticas de serviços | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | editora/api/parceiro/{id} | Obter parceiro por id | ApiKey |
| POST | editora/api/parceiros/{id}/aprovar | Aprovar parceiro | ApiKey |
| POST | editora/api/parceiros/{id}/reprovar | Reprovar parceiro | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | editora/api/saques | Listar solicitações (filtro status/parceiro) | ApiKey |
| GET | editora/api/saques/stats | Estatísticas de saques | ApiKey |
| POST | editora/api/saques/{id}/aprovar | Aprovar saque → EmProcessamento | ApiKey |
| POST | editora/api/saques/{id}/rejeitar | Rejeitar saque (estorna saldo) | ApiKey |
| POST | editora/api/saques/{id}/confirmar-pagamento | Confirmar pagamento (comprovante) | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | editora/api/projeto | Listar projetos | ApiKey |
| GET | editora/api/projeto/{id} | Obter projeto | ApiKey |
| GET | editora/api/projeto/{id}/avaliacoes | Avaliações do projeto | ApiKey |
| GET | editora/api/projeto/stats | Estatísticas de projetos | ApiKey |
| PATCH | editora/api/projeto/{id}/status/cancelado | Cancelar projeto | ApiKey |
API completa do parceiro: autenticação, cadastro, gestão de serviços, saldos/saques, mensagens e projetos.
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | parceiro/api/parceiro/auth/login | Login (email + senha) → retorna token | ApiKey |
| POST | parceiro/api/parceiro/auth/logout | Logout (invalida token no Redis) | Bearer |
| GET | parceiro/api/parceiro/auth/me | Dados do parceiro autenticado | Bearer |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | parceiro/api/parceiro | Listar parceiros (paginado, filtro nome/email) | ApiKey |
| GET | parceiro/api/parceiro/{id} | Obter parceiro por id (204 se não encontra) | ApiKey |
| POST | parceiro/api/parceiro | Cadastrar parceiro vinculado à Editora | ApiKey |
| PUT | parceiro/api/parceiro/{id} | Atualizar dados gerais | ApiKey |
| GET | parceiro/api/parceiro/resumo | Resumo consolidado (saldos, projetos, serviços) | Bearer |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | parceiro/api/parceiro/servico | Listar meus serviços (paginado) | Bearer |
| GET | parceiro/api/parceiro/servico/{id} | Obter serviço (valida ownership) | Bearer |
| POST | parceiro/api/parceiro/servico | Criar serviço | Bearer |
| PUT | parceiro/api/parceiro/servico/{id} | Atualizar serviço | Bearer |
| DELETE | parceiro/api/parceiro/servico/{id} | Excluir serviço (soft-delete) | Bearer |
| PATCH | parceiro/api/parceiro/servico/{id}/ativar | Ativar serviço | Bearer |
| PATCH | parceiro/api/parceiro/servico/{id}/inativar | Inativar serviço | Bearer |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | parceiro/api/parceiro/financeiro/saldos | Saldos (bloqueado + disponível) | Bearer |
| GET | parceiro/api/parceiro/financeiro/saques | Listar solicitações de saque | Bearer |
| POST | parceiro/api/parceiro/financeiro/saques | Solicitar saque (valor ≤ saldo disponível) | Bearer |
| GET | parceiro/api/parceiro/financeiro/extrato | Extrato de movimentações (filtro tipo) | Bearer |
| PUT | parceiro/api/parceiro/financeiro/pix | Atualizar dados Pix | Bearer |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| GET | parceiro/api/projeto | Listar projetos do parceiro | ApiKey |
| GET | parceiro/api/projeto/{id} | Obter projeto | ApiKey |
| GET | parceiro/api/projeto/{id}/avaliacoes | Avaliações do projeto | ApiKey |
| POST | parceiro/api/projeto/{id}/pronto-entregas | Marcar como pronto + entregas | ApiKey |
| PATCH | parceiro/api/projeto/{id}/status/cancelado | Cancelar projeto | ApiKey |
| Método | Rota | Descrição | Auth |
|---|---|---|---|
| POST | parceiro/api/projeto/{projetoId}/mensagens | Enviar mensagem (remetente Parceiro) | ApiKey |
| GET | parceiro/api/projeto/{projetoId}/mensagens/conversa | Obter conversa completa | ApiKey |
| GET | parceiro/api/projeto/{projetoId}/mensagens/{mensagemId} | Obter mensagem por id | ApiKey |
| GET | parceiro/api/projeto/{projetoId}/mensagens/ultima | Última mensagem da conversa | ApiKey |
Header: X-Api-Key: <chave>
A chave é um Value Object de 64 caracteres que codifica o EditoraId + timestamp.
O middleware tenta resolver via Redis (cache 1h) e faz fallback para o Postgres.
Header: Authorization: Bearer <token>
Sessão server-side no Redis (não é JWT). Obtido via POST api/parceiro/auth/login.
Endpoints protegidos usam RequireParceiroFilter (IEndpointFilter) que exige token válido + parceiro ativo.
Não exigem autenticação:
POST admin/api/pagamentos/webhook/{gateway}/swagger, /openapi/admin/tickerq (protegido por Basic Auth próprio)/health, /alive (apenas Development)| Transição | Requisitos | Efeitos |
|---|---|---|
| Reservado → AguardandoPagamento | Projeto deve ter ≥ 1 item | Gera pagamento e inicia checkout |
| AguardandoPagamento → EmAndamento | Pagamento aprovado | Cria conversa; credita saldo bloqueado do parceiro |
| EmAndamento → Pronto | Parceiro marca como pronto | Pode adicionar URLs de entrega |
| Pronto → Finalizado | Avaliação aprovada do Cliente + Editora | Move saldo bloqueado → disponível |
| * → Cancelado | Qualquer status exceto Finalizado | Estorna saldo bloqueado se EmAndamento com pagamento aprovado |
Aumenta quando pagamento é aprovado e projeto entra EmAndamento. Valor = ValorLiquido do pagamento.
Aumenta quando projeto é Finalizado (avaliações aprovadas). Saldo bloqueado é transferido para disponível.
Parceiro solicita (valor ≤ disponível) → Admin aprova → Admin confirma pagamento (Pix/TED + comprovante). Se rejeitado, valor é estornado.
Após pagamento aprovado, um job TickerQ consulta os payables do Pagarme para obter a taxa real cobrada pelo gateway (fee + anticipation_fee + fraud_coverage_fee).
Ajusta TaxaCobrada no pagamento e o saldo do parceiro (SaldoBloqueado ou SaldoDisponivel conforme status do projeto).
Flag TaxaReconciliada indica se já foi reconciliado.
Admin pode forçar via POST admin/api/pagamentos/{projetoId}/reconciliar-taxa.
O agendamento é abstraído por IReconciliacaoJobScheduler (impl TickerQ registrada no módulo Admin).
Inspecione jobs via dashboard TickerQ.
ticker).
Inspecione via dashboard TickerQ (Basic Auth).
Consulta payables do Pagarme para obter taxa real. Trigger: 5min após aprovação, retry a cada 10min (max 6 tentativas).
Cancela projetos AguardandoPagamento há mais de 48h. Executa a cada 1 hora.
Fallback para webhook perdido: consulta status de pagamentos pendentes no gateway. Executa a cada 30 minutos. Aprova ou reprova conforme resposta.
| Chave | Endpoint | TTL |
|---|---|---|
stats:projeto:{editoraId} | GET editora/api/projeto/stats | 5 min |
stats:saque:{editoraId} | GET editora/api/saques/stats | 5 min |
stats:servico:{editoraId} | GET editora/api/servico/stats | 5 min |
stats:resumoParceiro:{parceiroId}:{editoraId} | GET parceiro/api/parceiro/resumo | 5 min |
checkout:link:{projetoId} | GET {mod}/api/projeto/{id}/pagamento/link | 3h |
Disponível em http://localhost:8085. Coleta métricas, traces e logs exportados via OTLP/gRPC pelos containers api e migrationwork. Ativo quando OTEL_EXPORTER_OTLP_ENDPOINT está configurado (injetado automaticamente pelo Aspire).
Quando a variável NEW_RELIC_LICENSE_KEY está presente, um segundo exportador OTLP/gRPC envia traces, métricas e logs para otlp.nr-data.net:4317 — em paralelo ao Aspire Dashboard, sem substituí-lo.
ServiceDefaults/Extensions.cs → AddOpenTelemetryExporters(). A chave New Relic é propagada via parâmetro Aspire new-relic-license-key (secret) e configurada em src/CapZeroApp.AppHost/appsettings.Production.json.
┌────────────────────────────────────────────────────────────────┐
│ API Unificada — CapZeroApp.Api │
│ Kestrel serve arquivos estáticos + rotas modulares │
│ │
│ MapGroup("/admin") ── módulo Admin (clientes, editoras, │
│ pagamentos, TickerQ) │
│ MapGroup("/agente") ── módulo Agente (clientes, projetos, │
│ itens, mensagens) │
│ MapGroup("/autor") ── módulo Autor (idêntico ao Agente, │
│ tipo Autor) │
│ MapGroup("/editora") ── módulo Editora (avaliações, │
│ parceiros, saques) │
│ MapGroup("/parceiro") ── módulo Parceiro (auth, serviços, │
│ financeiro) │
│ / ── arquivos estáticos (esta doc) │
└────────────────────────────────────────────────────────────────┘
│ │
┌────▼────┐ ┌────▼────┐
│ Postgres │ │ Redis │
│capzerodb │ │ cache │
└─────────┘ └─────────┘
URL: {módulo}/api/{rota} (estrutura preservada, sem proxy intermediário)
Ex: parceiro/api/parceiro/auth/login → MapGroup("/parceiro") resolve direto
Ex: editora/api/saques → MapGroup("/editora") resolve direto
Migration Worker: aplica migrations + seed da Editora padrão "Flyve"
1 container · 1 pool Postgres · 1 conexão Redis
• Domain & Application (lógica de negócio)
• Presentation.Shared (endpoints reutilizáveis)
• Infrastructure (auth, persistence, payment)
dotnet run --project src/CapZeroApp.AppHost — sobe Postgres, Redis, migration worker e a API unificada.
{módulo}/api/{rota}.
A API usa MapGroup() por módulo — sem gateway ou reverse proxy entre o cliente e a aplicação.
Ex: parceiro/api/parceiro/servico é resolvido diretamente pelo grupo /parceiro.
Cada endpoint é uma classe estática com um Map*() extension method. Endpoints chamam IMediator.Send(). Commands implementam ITransactionalRequest e rodam dentro de transação EF Core.
Validações retornam Result<T> com erros agregados (operador +). Sem exceções para regras de negócio. Falhas mapeadas via result.ToEndpointResult().
Campos críticos usam VOs (ApiKey, Nome, Email, Money, Pix, Url…) criados via Create().
Entidades com ISoftDelete têm filtro global no DbContext. Exclusão via MarkAsDeleted().
Comportamento externo ao TransactionalBehavior. Registra cada command com contexto de autenticação (Editora, Parceiro, Usuário), método HTTP, rota, IP e resultado. Falhas de auditoria nunca afetam o fluxo principal. Gravação via scope DI isolado.
ITransactionalRequest) é auditada automaticamente via AuditBehavior no pipeline do Mediator. A auditoria roda fora da transação de negócio (scope DI isolado) e nunca interrompe o fluxo principal em caso de falha.
AuditLogs (PostgreSQL)| Coluna | Tipo | Descrição |
|---|---|---|
Id | uuid | PK gerado automaticamente |
Timestamp | timestamptz | Momento exato da operação (UTC) |
EditoraId | uuid? | Tenant que originou a requisição (X-Api-Key) |
ParceiroId | uuid? | Parceiro autenticado via Bearer, se presente |
UsuarioId | uuid? | Usuário do parceiro autenticado, se presente |
Acao | varchar(200) | Nome do Command/Request (ex.: CadastrarParceiroCommand) |
Modulo | varchar(50) | Módulo inferido da rota HTTP (ex.: parceiro, admin) |
HttpMethod | varchar(10) | Método HTTP (GET, POST, PATCH…) |
Rota | varchar(500) | Caminho da requisição |
IpOrigem | varchar(50) | IP do cliente |
Sucesso | bool | true se o command retornou Result.IsSuccess |
Erros | varchar(2000)? | Erros de negócio ou mensagem de exceção em caso de falha |
ITransactionalRequest e não geram registros. Isso evita ruído na tabela e mantém a auditoria focada em operações com efeito colateral.
IPaymentGateway). Pagarme v5 já está integrado (webhook x-hub-signature, HMAC-SHA256).DistributedApplicationTestingBuilder.