Desenvolvedores

Referência da API v1

REST · JSON · OAuth 2.0 Bearer https://api.manilo.app Estável — sem mudanças incompatíveis dentro da v1

Visão geral

A API do Manilo é uma API REST JSON para gerenciar programaticamente o mesmo registro financeiro que você usa no app iOS — contas, categorias, orçamentos, grupos compartilhados e transações. Use-a para criar importadores, exportadores, pontes de sincronização e painéis, ou para alimentar as suas próprias automações.

  • URL base: https://api.manilo.app — a URL base anterior api.ledgy.app continua funcionando.
  • Prefixo de versão: todos os endpoints deste documento ficam sob /api/v1/.
  • Transporte: somente HTTPS. Requisições HTTP não são aceitas.
  • Codificação: corpos de requisição e resposta em JSON. UTF-8. Nomes de propriedades em camelCase.
  • Autenticação: Authorization: Bearer … em todas as requisições.
  • Assinatura do Cloud: obrigatória em todos os endpoints da v1. Veja Exigência de assinatura.
Procurando um assistente de IA? Se você quer que o Claude, o ChatGPT ou o Cursor conversem com o Manilo em seu nome, use o endpoint do Model Context Protocol em https://api.manilo.app/mcp — veja Integrações. A API REST documentada aqui é para o código que você mesmo escreve.

Início rápido

Três passos até a sua primeira requisição autenticada.

1. Gere um Token de Acesso Pessoal

  1. Entre no seu painel do Manilo e abra Configurações → Acesso à API.
  2. Clique em + Novo token.
  3. Dê ao token um nome descritivo (por exemplo, “Zapier — exportação semanal”), escolha os escopos necessários (veja Escopos) e, se quiser, defina uma expiração.
  4. Copie o token. Ele é exibido uma única vez. Os tokens começam com o prefixo lgpat_ seguido de 64 caracteres hexadecimais.

A mesma página lista os seus tokens ativos com a data do último uso e a quantidade de permissões, exibe um aviso de “Expira em 30 dias” e permite revogar qualquer token na hora pelo ícone de lixeira. Cada conta pode ter até 25 tokens ativos ao mesmo tempo.

2. Faça uma requisição

cURLListar contas
# Replace lgpat_… with your token
curl "https://api.manilo.app/api/v1/accounts" \
  -H "Authorization: Bearer lgpat_a1b2c3d4e5…"

3. Analise a resposta

200 OKapplication/json
{
  "items": [
    {
      "id": "acc_01HK8V…",
      "name": "Wise EUR",
      "currencyCode": "EUR",
      "initialBalance": 1240.50,
      "icon": "wallet",
      "color": "#4A90E2",
      "order": 0,
      "createdAt": "2026-04-12T08:13:09Z",
      "updatedAt": "2026-05-01T17:02:31Z"
    }
  ],
  "totalCount": 1
}
Trate o seu token como uma senha. Qualquer pessoa com o token pode ler ou modificar o seu registro financeiro dentro dos escopos que você concedeu. Revogue tokens comprometidos imediatamente em Configurações → Acesso à API.

Autenticação

Toda requisição a /api/v1/ precisa levar um cabeçalho Authorization. Dois tipos de token são aceitos:

  • Token de Acesso Pessoal (PAT) — bearer token de longa duração que você cria na página Configurações → Acesso à API do painel. Formato: lgpat_ + 64 caracteres hexadecimais. Com escopos, revogável e com expiração opcional. Recomendado para todas as integrações de terceiros.
  • JWT de sessão — token de curta duração emitido para os apps próprios (iOS e painel). Não tem restrições de escopo. Você pode usá-lo para um teste pontual, se conseguir extraí-lo de uma sessão autenticada, mas os PATs são o caminho suportado.

Formato do cabeçalho

HTTP
Authorization: Bearer lgpat_a1b2c3d4e5f6…

Limites de token

  • Até 25 PATs ativos por conta do Manilo.
  • É possível definir uma expiração opcional no momento da criação. Tokens expirados retornam 401 Unauthorized.
  • Tokens revogados param de funcionar imediatamente — o Manilo guarda apenas um hash SHA-256 do token, nunca o valor, então um token vazado não pode ser recuperado, apenas revogado e substituído.

Falhas comuns de autenticação

401
Token ausente, malformado, expirado ou revogado.
403
O token é válido, mas o endpoint solicitado exige um escopo que o seu PAT não tem, ou a sua assinatura do Cloud não está ativa.

Escopos

Os PATs seguem um modelo de negação por padrão. Um token só pode chamar endpoints cujo escopo exigido ele possui; todo o resto retorna 403 Forbidden. Conceda o conjunto mais restrito de escopos de que a sua integração realmente precisa.

Escopos disponíveis:

accounts:read accounts:write categories:read categories:write budgets:read budgets:write groups:read groups:write transactions:read transactions:write tags:read tags:write recurring:read recurring:write settings:read settings:write

Cada endpoint listado abaixo mostra o escopo exigido em uma pequena etiqueta roxa. Escopos :write não implicam :read — peça os dois se precisar dos dois.

Exigência de assinatura

Todos os endpoints da v1 — inclusive os de somente leitura — exigem que o usuário que faz a chamada tenha uma assinatura ativa do Manilo Cloud. Se a assinatura foi interrompida, expirou ou nunca foi iniciada, a API responde com:

403 Forbidden
HTTP/1.1 403 Forbidden
X-Subscription-Required: true
Content-Type: application/json

{ "error": "Active cloud subscription required" }

O cabeçalho X-Subscription-Required permite que os clientes distingam um bloqueio por assinatura de uma negação de permissão genérica. Restaure o acesso reativando o Cloud no app iOS ou em dashboard.manilo.app/upgrade.

Erros

Os erros usam códigos de status HTTP padrão. O corpo da resposta é um objeto JSON de um único campo:

JSON
{ "error": "Human-readable message" }

Códigos de status que você deve tratar:

200
OK — recurso retornado, ou lista retornada.
201
Created — novo recurso criado. O cabeçalho Location aponta para a URL canônica.
204
No Content — exclusão bem-sucedida; sem corpo.
400
Falha de validação — campo obrigatório ausente, valor fora do intervalo, JSON malformado.
401
Falha de autenticação — veja Autenticação.
403
Permissão negada — escopo insuficiente ou assinatura inativa.
404
Recurso não encontrado, ou oculto por falta de autorização.
409
Conflito — por exemplo, violação de restrição de unicidade.
5xx
Falha do lado do servidor. É seguro repetir leituras idempotentes com backoff exponencial.

Paginação e filtros

Por padrão, os endpoints de listagem retornam todos os itens correspondentes. As transações, o único recurso que pode crescer muito, aceitam paginação por cursor.

Cursor de transações

cURLListagem paginada
curl "https://api.manilo.app/api/v1/transactions?limit=50&type=expense&dateFrom=2026-01-01" \
  -H "Authorization: Bearer lgpat_…"

A resposta inclui um nextCursor. Envie-o de volta no parâmetro de consulta cursor para buscar a próxima página; quando nextCursor for null, você chegou ao fim.

  • limit — tamanho da página, limitado a 1..200. Padrão: 50.
  • cursor — token opaco. Trate-o como uma caixa-preta.
  • type, dateFrom, dateTo, categoryId, accountId, groupId — filtros opcionais; veja o endpoint Listar transações.

Tipos e formatos

  • IDs — strings opacas. Não faça parsing delas; trate-as como identificadores UTF-8 que diferenciam maiúsculas de minúsculas.
  • Timestamps — ISO-8601 em UTC com um Z no final, por exemplo "2026-05-13T10:30:00Z".
  • Datas (por exemplo, o date da transação) — mesmo formato ISO-8601, mas apenas a parte da data é significativa.
  • Valores monetários — números JSON em unidades principais com até 4 casas decimais (por exemplo, 12.50). Nunca em unidades menores. Sempre acompanhados de currencyCode.
  • Códigos de moeda — ISO-4217, exatamente três letras maiúsculas (por exemplo, "EUR", "USD", "GBP").
  • Exclusões — todas as operações de exclusão são exclusões reversíveis (soft deletes). Os itens excluídos deixam de aparecer nas respostas de listagem e de leitura; parceiros de compartilhamento e recibos históricos são preservados.
  • Efeitos colaterais — excluir uma conta, categoria ou grupo mantém intactas as transações dependentes; as referências delas são desvinculadas. O endpoint Excluir conta aceita uma estratégia explícita.

Contas

As contas são os recipientes que guardam saldos — uma conta bancária, um cartão de crédito, uma carteira de dinheiro, uma corretora. Toda transação está ligada a uma (ou a duas, no caso das transferências).

GET /api/v1/accounts accounts:read

Retorna todas as contas que o usuário autenticado possui ou às quais tem acesso.

GET /api/v1/accounts/{id} accounts:read

Busca uma conta pelo id. Retorna 404 se não for encontrada.

POST /api/v1/accounts accounts:write

Cria uma conta. Retorna 201 com o objeto criado e um cabeçalho Location.

Corpo da requisição
CampoTipoDescrição
namestringobrigatórioNome de exibição. Máx. 100 caracteres.
currencyCodestringobrigatórioISO-4217. Exatamente 3 letras.
initialBalancenumberobrigatórioSaldo inicial em currencyCode.
orderintegerobrigatórioPosição de ordenação. Menor vem primeiro.
iconstringopcionalIdentificador de ícone de /api/v1/icons. Máx. 50.
colorstringopcionalCor em hexadecimal, por exemplo "#4A90E2". Máx. 20.
iconColorstringopcionalSobrescreve a cor do ícone.
Requisição
POST /api/v1/accounts
{
  "name": "Cash",
  "currencyCode": "EUR",
  "initialBalance": 50.00,
  "order": 2,
  "icon": "wallet",
  "color": "#22C55E"
}
201 Created
{
  "id": "acc_01HK8V…",
  "name": "Cash",
  "currencyCode": "EUR",
  "initialBalance": 50.00,
  "order": 2,
  "icon": "wallet",
  "color": "#22C55E",
  "iconColor": null,
  "shareInviteToken": null,
  "createdAt": "2026-05-13T10:30:00Z",
  "updatedAt": "2026-05-13T10:30:00Z"
}
PUT /api/v1/accounts/{id} accounts:write

Substitui uma conta existente. O corpo é idêntico ao de Criar; todos os campos devem ser informados.

DELETE /api/v1/accounts/{id} accounts:write

Exclui uma conta de forma reversível. Defina o que acontece com as transações dela pelo parâmetro de consulta action.

Parâmetros de consulta
CampoTipoDescrição
actionenumopcionalDetach (padrão): limpa a referência de conta em cada transação. Move: reatribui as transações para moveTargetAccountId. DeleteAll: exclui de forma reversível todas as transações vinculadas que pertencem a você.
moveTargetAccountIdstringopcionalObrigatório quando action=Move. Id da conta de destino.

Categorias

As categorias identificam para que serve uma transação (mercado, aluguel, renda de freelance). As categorias do sistema são somente leitura e compartilhadas por todos os usuários; as categorias de usuário são suas para gerenciar. Os grupos de categorias reúnem categorias relacionadas.

GET /api/v1/categories/system-categories categories:read

Retorna o conjunto curado de categorias “conhecidas” do Manilo — o conjunto inicial que vem com o app iOS. Elas são versionadas globalmente e podem ser cacheadas com segurança por version.

Categorias de usuário

GET /api/v1/categories categories:read

Lista todas as categorias definidas pelo usuário.

GET /api/v1/categories/{id} categories:read

Busca uma categoria de usuário pelo id.

POST /api/v1/categories categories:write

Cria uma categoria de usuário.

Corpo da requisição
CampoTipoDescrição
namestringobrigatórioNome de exibição. Máx. 100.
typestringobrigatório"income" ou "expense".
orderintegerobrigatórioPosição de ordenação dentro do grupo.
isPinnedbooleanobrigatórioFixa no topo do seletor.
categoryGroupIdstringopcionalId do grupo pai, ou null para ficar sem grupo.
iconstringopcionalIdentificador de ícone.
colorstringopcionalCor em hexadecimal.
PUT /api/v1/categories/{id} categories:write

Substitui uma categoria de usuário. O corpo é idêntico ao de Criar.

DELETE /api/v1/categories/{id} categories:write

Exclui uma categoria de usuário de forma reversível. As transações não são excluídas; o categoryId delas é limpo.

Grupos de categorias

GET /api/v1/categories/groups categories:read

Lista os seus grupos de categorias.

GET /api/v1/categories/groups/{id} categories:read

Busca um grupo de categorias.

POST /api/v1/categories/groups categories:write

Cria um grupo de categorias.

Corpo da requisição
CampoTipoDescrição
namestringobrigatórioNome de exibição. Máx. 100.
orderintegerobrigatórioPosição de ordenação.
iconstringopcionalIdentificador de ícone.
colorstringopcionalCor em hexadecimal.
PUT /api/v1/categories/groups/{id} categories:write

Substitui um grupo de categorias.

DELETE /api/v1/categories/groups/{id} categories:write

Exclui um grupo de forma reversível. As categorias filhas sobrevivem — o categoryGroupId delas é limpo.

Orçamentos

Um orçamento limita os gastos de uma categoria (ou, quando categoryId é nulo, do registro financeiro inteiro) em uma janela recorrente. Compartilhe um orçamento com um grupo definindo groupId.

GET /api/v1/budgets budgets:read

Lista todos os orçamentos.

GET /api/v1/budgets/{id} budgets:read

Busca um orçamento.

POST /api/v1/budgets budgets:write

Cria um orçamento.

Corpo da requisição
CampoTipoDescrição
amountnumberobrigatórioLimite por período. Precisa ser maior que 0.
currencyCodestringobrigatórioISO-4217.
periodintegerobrigatório0 Semanal · 1 Mensal · 2 Trimestral · 3 Anual.
startDatestring (ISO-8601)obrigatórioInício do primeiro período.
isActivebooleanobrigatórioSe este orçamento está em vigor no momento.
endDatestring (ISO-8601)opcionalParar de acompanhar depois desta data.
namestringopcionalRótulo. Máx. 200.
categoryIdstringopcionalCategoria a acompanhar. Omita para orçar todos os gastos.
groupIdstringopcionalGrupo com quem compartilhar. Omita para deixar pessoal.
PUT /api/v1/budgets/{id} budgets:write

Substitui um orçamento.

DELETE /api/v1/budgets/{id} budgets:write

Exclui um orçamento de forma reversível.

Grupos

Os grupos são registros financeiros compartilhados — uma casa, uma viagem, um apartamento dividido. Todos os membros veem as mesmas transações; a propriedade continua pessoal. Participação e convites são gerenciados no app iOS; o que a API expõe aqui é o recurso em si.

GET /api/v1/groups groups:read

Lista os grupos que você possui ou dos quais é membro.

GET /api/v1/groups/{id} groups:read

Busca um grupo.

POST /api/v1/groups groups:write

Cria um grupo. Você se torna o dono; convide membros pelo app iOS.

Corpo da requisição
CampoTipoDescrição
namestringobrigatórioNome de exibição. Máx. 100.
descriptionstringopcionalTexto livre. Máx. 500.
iconstringopcionalIdentificador de ícone.
colorstringopcionalCor em hexadecimal.
PUT /api/v1/groups/{id} groups:write

Substitui os metadados de um grupo.

DELETE /api/v1/groups/{id} groups:write

Exclui um grupo de forma reversível. Os membros perdem a visibilidade; as transações subjacentes voltam a ser pessoais.

Transações

As transações são os verbos do registro financeiro. Elas vêm em quatro formatos: income, expense, transfer (de conta para conta) e adjustment (reajuste pontual). O endpoint base cria income/expense; as transferências têm o próprio endpoint; existem variantes em lote para importadores de alto volume.

GET /api/v1/transactions transactions:read

Lista transações com paginação por cursor e filtros.

Parâmetros de consulta
CampoTipoDescrição
limitintegeropcionalTamanho da página. 1..200. Padrão: 50.
cursorstringopcionalToken opaco de continuação, vindo da resposta anterior.
typestringopcional"income", "expense", "transfer" ou "adjustment".
dateFromstring (ISO-8601)opcionalLimite inferior, inclusivo.
dateTostring (ISO-8601)opcionalLimite superior, inclusivo.
categoryIdstringopcionalFiltra por uma categoria.
accountIdstringopcionalFiltra por uma conta.
groupIdstringopcionalFiltra por um grupo compartilhado.
200 OK
{
  "items": [ /* TransactionDto[] */ ],
  "totalCount": 317,
  "nextCursor": "eyJrIjoiMjAyNi0wNS0xM1QxMDoz…"
}
GET /api/v1/transactions/{id} transactions:read

Busca uma transação.

POST /api/v1/transactions transactions:write

Cria uma única transação de receita ou despesa. Para transferências, use /transfer.

Corpo da requisição
CampoTipoDescrição
typestringobrigatório"income" ou "expense".
amountnumberobrigatórioValor positivo em currencyCode.
currencyCodestringobrigatórioISO-4217.
datestring (ISO-8601)obrigatórioQuando a transação ocorreu (UTC).
accountIdstringopcionalConta de origem/destino.
categoryIdstringopcionalRótulo de categoria.
payeestringopcionalEstabelecimento ou contraparte. Máx. 200.
notestringopcionalObservação livre. Máx. 2000.
groupIdstringopcionalCompartilhar com um grupo.
exchangeRatenumberopcionalTaxa de câmbio quando currencyCode ≠ moeda principal do usuário.
convertedAmountnumberopcionalValor na moeda principal do usuário.
RequisiçãoCafé de €8.50 ontem no Wise
POST /api/v1/transactions
{
  "type": "expense",
  "amount": 8.50,
  "currencyCode": "EUR",
  "date": "2026-05-12T09:14:00Z",
  "accountId": "acc_01HK8V…",
  "categoryId": "cat_food_drinks",
  "payee": "Pret",
  "note": "Flat white"
}
PUT /api/v1/transactions/{id} transactions:write

Substitui uma transação. O corpo é idêntico ao de Criar.

DELETE /api/v1/transactions/{id} transactions:write

Exclui uma transação de forma reversível.

POST /api/v1/transactions/transfer transactions:write

Cria uma transferência entre duas contas. Sem categoria. Para transferências entre moedas diferentes, informe exchangeRate e convertedAmount na moeda de destino.

Corpo da requisição
CampoTipoDescrição
fromAccountIdstringobrigatórioConta de origem.
toAccountIdstringobrigatórioConta de destino. Precisa ser diferente da de origem.
amountnumberobrigatórioValor enviado, em currencyCode.
currencyCodestringobrigatórioMoeda de origem, ISO-4217.
datestring (ISO-8601)obrigatórioData da transferência.
exchangeRatenumberopcionalObrigatório quando as moedas de origem e destino são diferentes.
convertedAmountnumberopcionalValor creditado no destino, na moeda dele.
notestringopcionalMáx. 2000.

Operações em lote

Feitas para importadores. Cada lote é limitado a 100 itens e roda em modo best-effort: uma única linha inválida não desfaz as outras. Os itens bem-sucedidos e os erros por linha são reportados separadamente, para você repetir apenas as falhas.

POST /api/v1/transactions/bulk transactions:write

Cria até 100 transações em uma chamada.

200 OK
{
  "items": [ /* successful TransactionDto[] */ ],
  "errors": [
    { "index": 3, "error": "Invalid currency code" }
  ]
}
PUT /api/v1/transactions/bulk transactions:write

Atualiza até 100 transações em uma chamada. Cada item precisa incluir o seu id junto com o corpo completo da transação.

POST /api/v1/transactions/bulk-delete transactions:write

Exclui de forma reversível até 100 transações em uma chamada. Usa POST em vez de DELETE para que o corpo da requisição seja aceito por todos os clientes HTTP.

Corpo da requisição
CampoTipoDescrição
idsstring[]obrigatórioDe 1 a 100 ids de transação.
200 OK
{
  "deleted": 97,
  "notFound": [ "tx_old1", "tx_old2", "tx_old3" ]
}

O objeto de transação

CampoTipoDescrição
idstringIdentificador opaco.
typestringincome · expense · transfer · adjustment.
amountnumberEm currencyCode.
currencyCodestringISO-4217.
exchangeRatenumber | nullDefinido em lançamentos entre moedas diferentes.
convertedAmountnumber | nullO mesmo valor na moeda principal do usuário.
datestringISO-8601 UTC.
accountIdstring | nullEm transferências, esta é a conta de origem.
toAccountIdstring | nullConta de destino, apenas em transferências.
categoryIdstring | nullNulo em transferências.
groupIdstring | nullDefinido se estiver compartilhado com um grupo.
payeestring | nullEstabelecimento ou contraparte.
notestring | nullTexto livre.
receiptImagePathstring | nullCaminho do recibo anexado. Busque pelo endpoint de recibos (separado da v1).
recurringTransactionIdstring | nullDefinido se esta linha foi gerada por uma regra de recorrência.
sourcestringEtiqueta de origem — api, mobile, web, import, entre outras.
createdAtstringISO-8601 UTC.
updatedAtstringISO-8601 UTC.

Ícones

O Manilo vem com um conjunto curado de ícones e uma paleta de cores usados em tudo — contas, categorias e grupos. Busque o catálogo uma vez, guarde em cache e reutilize os identificadores ao criar recursos.

GET /api/v1/icons

Retorna a biblioteca completa de ícones, agrupada em categorias, junto com a paleta de cores suportada. É versionada — pode ser cacheada com segurança pelo campo version.

200 OK
{
  "version": "2026.05.10",
  "library": "font-awesome-6",
  "categories": [
    {
      "id": "finance",
      "name": "Finance",
      "icons": [ "wallet", "credit-card", "piggy-bank" ]
    }
  ],
  "colors": [
    { "name": "Blue", "hex": "#4A90E2" },
    { "name": "Green", "hex": "#22C55E" }
  ]
}

Versionamento

  • Sem mudanças incompatíveis dentro da v1. Vamos apenas acrescentar novos endpoints, novos campos opcionais e novos valores de enum. O tipo, a nulabilidade ou a obrigatoriedade de um campo não vão mudar.
  • Novos valores de enum não são mudanças incompatíveis. Trate valores desconhecidos de type, source ou action como “não renderizar” em vez de quebrar — vamos adicioná-los conforme o produto crescer.
  • Mudanças incompatíveis datadas (se algum dia forem necessárias) virão sob /api/v2/ com pelo menos 6 meses de disponibilidade paralela e um cabeçalho de descontinuação nas respostas da v1.

Suporte

Achou um bug, quer um endpoint ou esbarrou em algo que não está documentado? Abra a central de ajuda ou escreva para support@manilo.app — inclua o id da requisição (devolvido no cabeçalho de resposta X-Request-Id) ao relatar um problema.

Para divulgações sensíveis de segurança (vazamento de token, contorno de permissão, leitura não autorizada), escreva para security@manilo.app.