ranjit

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 15 Imported by: 0

README

Ranjit

Um serviço open source em Go para integrar contas, saldos e transações ao seu backend.

Você instala o Ranjit uma vez e usa sua API pelo SDK Go. O serviço cuida dos conectores, importação de extratos, sincronização e armazenamento. Roda como binário ou container, com SQLite local ou PostgreSQL na hospedagem. SDKs para outras linguagens podem usar o mesmo contrato HTTP.

seu aplicativo → seu backend → SDK Go → Ranjit → APIs bancárias / extratos
                                          ↓
                                  SQLite ou PostgreSQL

As integrações diretas usam as credenciais da aplicação criada pelo titular no banco. Para compartilhamento entre bancos pelo Open Finance, ainda é necessária uma operação habilitada e outro adaptador. Os limites de acesso estão documentados com as referências oficiais.

Usar no backend

Para começar localmente, instale o binário abaixo, rode ranjit serve e obtenha a chave com ranjit key. No seu backend:

go get github.com/getcortexlabs/ranjit@v0.3.0
export RANJIT_URL=http://localhost:8080
# Configure RANJIT_API_KEY com a chave da sua instalação.
client, err := ranjit.NewClientFromEnv()
if err != nil {
    return err
}
page, err := client.SearchTransactions(ctx, ranjit.TransactionFilter{
    CustomerID: authenticatedUserID,
    Limit:      100,
})

O SDK é um cliente HTTP: o Ranjit roda como processo separado do seu backend. A chave fica apenas no servidor. Seu aplicativo autentica os usuários e determina quais dados cada um pode acessar; customer_id sozinho não é uma permissão.

O exemplo de backend Go importa um CSV e consulta transações sem precisar de acesso bancário. O guia de instalação em servidor e Orbit cobre PostgreSQL, segredos e a configuração do SDK. O painel e os comandos locais continuam disponíveis como ferramentas de apoio.

Instalar

macOS e Linux, sem Go e sem Docker:

curl -fsSL https://raw.githubusercontent.com/getcortexlabs/ranjit/main/install.sh -o /tmp/ranjit-install.sh
sh /tmp/ranjit-install.sh

O instalador baixa o binário da release, verifica o SHA-256 e instala em ~/.local/bin. Se essa pasta ainda não estiver no PATH, ele mostra o comando para executar. Não usa sudo nem altera arquivos do shell. Para escolher outra pasta, use RANJIT_INSTALL_DIR; para fixar uma versão, RANJIT_VERSION.

No Windows, baixe o ZIP correspondente ao processador em Releases, extraia e execute ranjit.exe. Os arquivos .tar.gz também permitem instalação manual no macOS/Linux. checksums.txt acompanha cada release.

Usar

O caminho mais curto é abrir o painel local:

ranjit ui

O comando cria a configuração, inicia o servidor e abre o navegador. Em Importar extrato, escolha um OFX ou CSV, confira a prévia e confirme. Para experimentar com dados fictícios:

ranjit demo
ranjit accounts
ranjit transactions

Para usar um extrato que você exportou do banco:

ranjit import extrato.ofx
ranjit accounts
ranjit transactions
ranjit status

Isso funciona localmente, sem credenciais de API ou servidor rodando. CSV também funciona:

ranjit import --account pessoal extrato.csv
# CSV com valores como -12,34 e campos separados por ponto e vírgula:
ranjit import --account pessoal --decimal , extrato.csv

O CSV precisa de date,description,amount ou data,descrição,valor. A coluna id é recomendada. Sem IDs, repetir o mesmo arquivo é seguro; novos arquivos com períodos sobrepostos são recusados para evitar confundir lançamentos iguais. Datas aceitas: YYYY-MM-DD e DD/MM/YYYY. Veja o formato dos extratos.

Para conexão automática com a API de um banco:

ranjit configure
ranjit doctor --live
ranjit sync meu-perfil

O assistente pede o banco, o nome do perfil e os caminhos dos arquivos de credenciais. Rode novamente para adicionar outra conta. Se ranjit serve estiver rodando, reinicie-o depois de alterar os perfis. Os requisitos de acesso continuam sendo os de cada banco; o assistente configura uma integração já habilitada.

ranjit status mostra a última sincronização, os lançamentos armazenados e o progresso do job. ranjit doctor verifica a configuração local; --live consulta o saldo, sem imprimir valores ou credenciais. Essa consulta não equivale a homologar o extrato. Todos os conectores bancários estão marcados como experimental.

A configuração pessoal fica na pasta de configuração do sistema, dentro de ranjit/config.json. O SQLite fica em data/ ao lado desse arquivo. RANJIT_CONFIG=/outro/caminho/config.json permite uma instalação separada. Arquivos novos recebem permissão 0600 nos sistemas Unix.

No dia a dia

ranjit backup minha-copia.db
ranjit service install
ranjit update --check

O serviço inicia ao entrar no computador, sem exigir administrador. Para atualizar: ranjit service stop, ranjit update e ranjit service start. A atualização verifica o checksum, guarda o binário anterior e faz backup do banco existente. O painel e ranjit doctor avisam quando certificados estão perto de vencer.

ranjit pause ID interrompe a coleta e mantém o histórico. ranjit renew ID verifica novamente o acesso e retoma a mesma conexão. Para restaurar, pare o serviço e use ranjit restore --replace minha-copia.db; a restauração guarda uma cópia anterior e deixa conexões bancárias pausadas. Os detalhes estão em operação.

ranjit validate --report teste.json meu-perfil testa o acesso configurado e gera um relatório sem valores, identificadores de conta ou credenciais. A conferência com o extrato oficial continua manual; veja o procedimento.

API e sincronização periódica

ranjit serve

A API escuta em http://localhost:8080. O painel fica em /app/; ranjit ui abre uma sessão sem copiar a chave. ranjit key mostra a chave para integrar seu backend; guarde-a como segredo. Para consulta no terminal, os comandos acima dispensam a API. ranjit revoke ID revoga uma conexão e remove seus dados financeiros locais.

Docker

O instalador também baixa uma imagem pronta, verifica o checksum e carrega no Docker. Não exige conta em registry:

curl -fsSL https://raw.githubusercontent.com/getcortexlabs/ranjit/main/install.sh -o /tmp/ranjit-install.sh
sh /tmp/ranjit-install.sh --docker
cd ranjit-docker
docker compose up -d
docker compose exec ranjit /ranjit demo
docker compose exec ranjit /ranjit accounts

O servidor gera a configuração e a chave no primeiro uso. O volume mantém os dados; a porta é publicada apenas em loopback. Para obter a chave: docker compose exec ranjit /ranjit key. Para importar, monte a pasta dos extratos como volume de leitura e execute /ranjit import /caminho/extrato.ofx. A imagem usa um filesystem somente leitura; credenciais também devem ser montadas como volumes de leitura. O container roda sem root.

Compilar

Go 1.26 ou superior, com o patch mais recente da versão:

git clone https://github.com/getcortexlabs/ranjit.git
cd ranjit
make build
./bin/ranjit demo

O fluxo por variáveis de ambiente continua disponível: make setup gera .env, make run inicia a API e make example demonstra o SDK. O Compose principal do repositório usa esse .env e compila a imagem com docker compose up --build. make smoke testa a API já em execução.

Conectar a própria conta Efí

O guia Efí mostra como configurar Client ID, Client Secret e certificado para homologação ou produção. A modalidade Pro admite empreendedores sem CNPJ. O conector usa apenas leitura, e cada instalação mantém suas credenciais localmente.

O histórico inicial cobre Pix recebidos e suas devoluções concluídas. Compras, Pix enviados e o extrato completo não estão incluídos. O conector foi testado com respostas simuladas da API; a validação com uma conta habilitada ainda está pendente.

Conectar a própria conta Inter Empresas

O guia Inter explica como configurar a API Banking para consultar saldo disponível e lançamentos do extrato. A integração atende contas PJ; o banco não disponibiliza essas APIs para PF ou MEI. A instalação seleciona explicitamente a conta e solicita apenas extrato.read.

Os testes locais usam respostas simuladas. A validação com uma conta Inter habilitada ainda está pendente.

Sicoob, C6 Empresas e Santander Empresas

Os guias de Sicoob, C6 Empresas e Santander Empresas explicam como configurar cada aplicação para consultar saldo e extrato da própria conta. Cada banco tem seus requisitos de habilitação e seu ambiente de testes.

Os três conectores têm testes locais com respostas simuladas. A homologação com credenciais bancárias está pendente. No Santander, o guia registra uma divergência entre o Swagger e a coleção Postman que precisa ser conferida nessa etapa.

Provedor Acesso Cobertura
file Arquivo OFX/CSV exportado pelo titular Lançamentos e saldo quando informado no OFX
sandbox Local, sem credenciais bancárias Contas e transações fictícias
efi Aplicação Efí habilitada Saldo, Pix recebidos e suas devoluções
inter Aplicação Inter Empresas PJ habilitada Saldo disponível e extrato da conta
sicoob Aplicação do cooperado habilitada Saldo e extrato mensal
c6 Aplicação C6 Empresas PJ habilitada Saldo disponível e extrato
santander Aplicação Santander Empresas habilitada Saldo disponível e lançamentos efetivados

Integrar

Integrações com /v1 usam Authorization: Bearer <RANJIT_API_KEY>. Essa chave pertence ao backend da aplicação. Ela permite acessar todos os clientes daquela instalação; customer_id é um identificador de agrupamento, não uma barreira de autorização entre usuários.

set -a
. ./.env
set +a

curl http://localhost:8080/v1/connections \
  -H "Authorization: Bearer $RANJIT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"customer_id":"user-42","institution_id":"sandbox-bank"}'

No sandbox, a resposta traz a conexão e authorization_url. O link vence em dez minutos e só pode ser usado uma vez. A aprovação enfileira a primeira sincronização. O consentimento simulado dura 90 dias, contados da criação da conexão; esse prazo não pretende reproduzir a regra de um banco. Nos conectores diretos, a conexão usa api_credentials, é criada ativa após verificar o acesso e não retorna link de autorização.

O exemplo Go mostra o fluxo completo. O contrato HTTP está em docs/openapi.json, e os detalhes de paginação, erros e estados em docs/api.md.

Método Caminho Uso
POST /v1/imports?customer_id=...&format=ofx Importar extrato local
POST /v1/imports/preview Conferir extrato sem gravar
GET /v1/transactions Buscar por conta, descrição e período
POST /v1/connections/{id}/pause Pausar coleta e manter histórico
POST /v1/connections/{id}/renew Verificar acesso e retomar coleta
GET /v1/connections/{id}/status Ver progresso, contagens e datas dos lançamentos
GET /v1/institutions Instituições configuradas e cobertura de dados
POST /v1/connections Criar conexão; link de autorização no sandbox
GET /v1/connections?customer_id=... Listar conexões do cliente
GET /v1/connections/{id} Consultar estado e última sincronização
POST /v1/connections/{id}/sync Enfileirar sincronização
GET /v1/jobs/{id} Acompanhar execução e tentativas
GET /v1/connections/{id}/accounts Consultar contas e saldos
GET /v1/accounts/{id}/transactions Consultar transações
DELETE /v1/connections/{id} Revogar e remover dados normalizados

Decisões do projeto

Um binário, um banco e um worker. net/http faz o transporte; SQLite ou PostgreSQL guarda os dados e a fila; o provedor só entrega lotes normalizados. O painel usa HTML, CSS e JavaScript embutidos no executável, sem etapa de build do frontend. Não há Redis, ORM ou framework web. O driver SQLite funciona sem CGO.

Os valores monetários usam centavos inteiros. As importações são atômicas e fazem upsert por identificador estável do provedor. As respostas de leitura já recebidas ficam temporariamente no banco de dados, vinculadas ao job. A retomada mantém o período solicitado e reaproveita essas respostas; tokens e headers não entram nesse armazenamento. Os registros temporários são removidos ao concluir, falhar definitivamente, expirar ou revogar. O resultado de uma tentativa antiga é rejeitado, mesmo se chegar depois da nova tentativa.

Revogar uma conexão cancela seus jobs e apaga contas e transações na mesma transação. Em conexões diretas, pausar ou vencer o prazo local interrompe a coleta e preserva o histórico para consulta. O consentimento simulado continua bloqueando leitura e removendo dados quando vence.

A arquitetura explica os limites dos pacotes e os motivos dessas escolhas. O guia de provedores descreve o contrato que uma futura integração precisa cumprir.

Desenvolvimento

make check     # testes com detector de corrida, go vet e formatação
make build     # bin/ranjit, sem CGO

Os testes usam SQLite em diretórios temporários e exercitam os handlers HTTP reais com transporte em memória. Cobrem consentimento, autenticação, paginação, isolamento dos IDs entre conexões, rollback, repetição de sincronização, concorrência, expiração e retomada após reinício.

Antes de operar fora da máquina local, leia operação. A versão atual tem uma chave por instalação e banco sem criptografia em repouso. A configuração pessoal admite vários perfis; cada perfil direto acessa a conta vinculada às suas credenciais. O modo legado por variáveis de ambiente seleciona um provedor por processo. Webhooks, múltiplos operadores, outros produtos bancários e PostgreSQL ficam para mudanças com casos de uso definidos.

Contribuições: CONTRIBUTING.md. Licença: MIT.

Documentation

Overview

Package ranjit defines the public API types and Go client.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotFound            = errors.New("not found")
	ErrConflict            = errors.New("connection is not active")
	ErrInvalid             = errors.New("invalid input")
	ErrConsent             = errors.New("authorization link is invalid, expired or already used")
	ErrLease               = errors.New("job lease is no longer valid")
	ErrProviderCredentials = errors.New("provider credentials are invalid, missing required scopes or have changed")
	ErrProviderUnavailable = errors.New("provider is unavailable")
)

Functions

func NewID

func NewID(prefix string) string

func StableID

func StableID(prefix, owner, externalID string) string

Types

type APIError

type APIError struct {
	StatusCode int
	Code       string
	Message    string
	RequestID  string
}

func (*APIError) Error

func (e *APIError) Error() string

type Account

type Account struct {
	ID           string     `json:"id"`
	ConnectionID string     `json:"connection_id"`
	Name         string     `json:"name"`
	Type         string     `json:"type"`
	Balance      *Money     `json:"balance"`
	BalanceAt    *time.Time `json:"balance_at,omitempty"`
	UpdatedAt    time.Time  `json:"updated_at"`
}

type Client

type Client struct {
	HTTPClient *http.Client
	// contains filtered or unexported fields
}

func NewClient

func NewClient(baseURL, apiKey string) (*Client, error)

func NewClientFromEnv added in v0.3.0

func NewClientFromEnv() (*Client, error)

NewClientFromEnv reads the service address and key from backend configuration. The key belongs on the server; never expose it in a browser or mobile client.

func (*Client) Accounts

func (c *Client) Accounts(ctx context.Context, connectionID, cursor string, limit int) (Page[Account], error)

func (*Client) Connect

func (c *Client) Connect(ctx context.Context, input ConnectRequest) (ConnectResponse, error)

func (*Client) Connection

func (c *Client) Connection(ctx context.Context, id string) (Connection, error)

func (*Client) Connections

func (c *Client) Connections(ctx context.Context, customer, cursor string, limit int) (Page[Connection], error)

func (*Client) Import

func (c *Client) Import(ctx context.Context, input io.Reader, opts ImportOptions) (ImportResult, error)

Import uploads a local OFX/CSV export. Requests are limited to 8 MiB.

func (*Client) Institutions

func (c *Client) Institutions(ctx context.Context) (Page[Institution], error)

func (*Client) Job

func (c *Client) Job(ctx context.Context, id string) (Job, error)

func (*Client) Pause added in v0.2.0

func (c *Client) Pause(ctx context.Context, id string) error

func (*Client) PreviewImport added in v0.2.0

func (c *Client) PreviewImport(ctx context.Context, input io.Reader, opts ImportOptions) (ImportPreview, error)

func (*Client) Renew added in v0.2.0

func (c *Client) Renew(ctx context.Context, id string) (Connection, error)

func (*Client) Revoke

func (c *Client) Revoke(ctx context.Context, connectionID string) error

func (*Client) SearchTransactions added in v0.2.0

func (c *Client) SearchTransactions(ctx context.Context, f TransactionFilter) (Page[Transaction], error)

func (*Client) Status

func (c *Client) Status(ctx context.Context, connectionID string) (ConnectionStatus, error)

func (*Client) Sync

func (c *Client) Sync(ctx context.Context, connectionID string) (Job, error)

func (*Client) Transactions

func (c *Client) Transactions(ctx context.Context, accountID, cursor string, limit int) (Page[Transaction], error)

type ConnectRequest

type ConnectRequest struct {
	CustomerID    string `json:"customer_id"`
	InstitutionID string `json:"institution_id"`
}

type ConnectResponse

type ConnectResponse struct {
	Connection             Connection `json:"connection"`
	AuthorizationURL       string     `json:"authorization_url,omitempty"`
	AuthorizationExpiresAt time.Time  `json:"authorization_expires_at,omitzero"`
}

type Connection

type Connection struct {
	ID                string     `json:"id"`
	CustomerID        string     `json:"customer_id"`
	InstitutionID     string     `json:"institution_id"`
	Provider          string     `json:"provider"`
	Status            string     `json:"status"`
	CreatedAt         time.Time  `json:"created_at"`
	ConsentExpiresAt  time.Time  `json:"consent_expires_at,omitzero"`
	LastSyncedAt      *time.Time `json:"last_synced_at,omitempty"`
	AuthorizationMode string     `json:"authorization_mode"`
	CredentialID      string     `json:"-"`
}

func (Connection) HistoryAvailable added in v0.2.0

func (c Connection) HistoryAvailable() bool

type ConnectionStatus

type ConnectionStatus struct {
	Connection   Connection `json:"connection"`
	LatestJob    *Job       `json:"latest_job,omitempty"`
	Accounts     int        `json:"accounts"`
	Transactions int        `json:"transactions"`
	DataFrom     string     `json:"data_from,omitempty"`
	DataThrough  string     `json:"data_through,omitempty"`
}

type ImportOptions

type ImportOptions struct {
	Columns    map[string]string
	Delimiter  string
	CustomerID string
	Account    string
	Format     string
	Decimal    string
	DateFormat string
}

type ImportPreview added in v0.2.0

type ImportPreview struct {
	Result  ImportResult   `json:"result"`
	From    string         `json:"from"`
	Through string         `json:"through"`
	Sample  []ImportSample `json:"sample"`
}

ImportPreview describes a dry run. Its connection ID may not exist yet.

type ImportResult

type ImportResult struct {
	New           int    `json:"new"`
	Updated       int    `json:"updated"`
	Unchanged     int    `json:"unchanged"`
	ConnectionID  string `json:"connection_id"`
	Accounts      int    `json:"accounts"`
	Transactions  int    `json:"transactions"`
	Duplicate     bool   `json:"duplicate"`
	Deduplication string `json:"deduplication"`
}

type ImportSample added in v0.2.0

type ImportSample struct {
	PostedOn    string `json:"posted_on"`
	Description string `json:"description"`
	Amount      Money  `json:"amount"`
}

type Institution

type Institution struct {
	ID             string   `json:"id"`
	Name           string   `json:"name"`
	Provider       string   `json:"provider"`
	Sandbox        bool     `json:"sandbox"`
	ConnectionMode string   `json:"connection_mode"`
	DataCoverage   []string `json:"data_coverage"`
	Validation     string   `json:"validation"`
	Profile        string   `json:"profile,omitempty"`
}

type Job

type Job struct {
	ID                string    `json:"id"`
	ConnectionID      string    `json:"connection_id"`
	Status            string    `json:"status"`
	Attempts          int       `json:"attempts"`
	ErrorCode         string    `json:"error_code,omitempty"`
	CreatedAt         time.Time `json:"created_at"`
	UpdatedAt         time.Time `json:"updated_at"`
	LeaseToken        string    `json:"-"`
	RequestsCompleted int       `json:"requests_completed"`
}

type Money

type Money struct {
	AmountMinor int64  `json:"amount_minor"`
	Currency    string `json:"currency"`
}

Money uses signed minor units. BRL 12.34 is 1234; debits are negative. Values are restricted to the exact integer range supported by JSON clients.

func (Money) Validate

func (m Money) Validate() error

type Page

type Page[T any] struct {
	Data       []T    `json:"data"`
	NextCursor string `json:"next_cursor,omitempty"`
}

type Transaction

type Transaction struct {
	ID          string `json:"id"`
	AccountID   string `json:"account_id"`
	Description string `json:"description"`
	Amount      Money  `json:"amount"`
	PostedOn    string `json:"posted_on"`
	Status      string `json:"status"`
}

type TransactionFilter added in v0.2.0

type TransactionFilter struct {
	CustomerID, AccountID, Query, From, Through, Cursor string
	Limit                                               int
}

Directories

Path Synopsis
cmd
ranjit command
examples
backend command
A single-customer backend example.
A single-customer backend example.
connect command
Run with make example.
Run with make example.
internal
app
Package app assembles configured providers without exposing credentials to the API.
Package app assembles configured providers without exposing credentials to the API.
autostart
Package autostart installs a service for the current user, without elevation.
Package autostart installs a service for the current user, without elevation.
filelock
Package filelock coordinates Ranjit processes during offline maintenance.
Package filelock coordinates Ranjit processes during offline maintenance.
provider
Package provider is the boundary for fetching normalized financial data.
Package provider is the boundary for fetching normalized financial data.
provider/c6
Package c6 reads the operator's own C6 Empresas statement using the bank's own API.
Package c6 reads the operator's own C6 Empresas statement using the bank's own API.
provider/efi
Package efi connects to the operator's own Efí account through the official Pix API.
Package efi connects to the operator's own Efí account through the official Pix API.
provider/inter
Package inter reads the operator's own Inter Empresas account using the Banking API.
Package inter reads the operator's own Inter Empresas account using the Banking API.
provider/santander
Package santander reads the operator's own Santander Empresas account using Bank Account Information.
Package santander reads the operator's own Santander Empresas account using Bank Account Information.
provider/sicoob
Package sicoob reads the operator's own Sicoob account using the Conta Corrente API.
Package sicoob reads the operator's own Sicoob account using the Conta Corrente API.
statement
Package statement reads local bank exports.
Package statement reads local bank exports.
updater
Package updater installs only stable release assets from the Ranjit repository.
Package updater installs only stable release assets from the Ranjit repository.
validation
Package validation checks a connector without adding data to the personal database.
Package validation checks a connector without adding data to the personal database.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL