- Project uses ruff for linting and formatting and basedpyright for type checking.
- Don't run real requests to the Bling API in the tests, unless explicitly stated.
- Use
uvto run the commands. - Only flexbilize ruff and basedpyright rules if absolutely necessary.
- After any change, run the tests to ensure the code is working as expected:
make check- Each endpoint is considered "done" when it has:
- a canonical public method in Portuguese in the resource;
- an English compatibility alias when the resource already exposes one;
- path/method/params/body matching the OpenAPI specification;
- a request model, if there is a body;
- a response model, if the response is important;
- a unit test for mapping;
- a fixture or model test;
- typed error handling covered when applicable;
- an example/docs if it is a commonly used endpoint.
- Find the operation in
specs/bling-openapi-reference.json. - Record
path, HTTP method,x-api-resource, andx-api-action. - Record path params, query params, request schema, and response schema.
- Add the resource to
RESOURCESinscripts/generate_openapi_contracts.pyif missing. - Add the action to
ACTION_TO_SDK_METHODinscripts/generate_openapi_contracts.pyif missing. - Add each Bling parameter to
PARAMETER_TO_SDK_NAMEinscripts/generate_openapi_contracts.pyif missing. - Run
uv run python scripts/generate_openapi_contracts.py. - Check the generated contract in
src/bling_erp_api/contracts/generated/<resource>.py. - Check the generated docs in
docs/resources/<resource>.md. - Add or update
tests/unit/test_<resource>_contracts.py. - In the contract test, compare generated operations with OpenAPI operations.
- Regenerate models with
uv run python scripts/generate_models.pywhen schemas or resource model exports need to change. - Check
src/bling_erp_api/models/generated/<resource>.pyandsrc/bling_erp_api/models/generated/schemas/<schema_module>.py. - Add request models for body schemas.
- Add response models for important responses.
- Keep public model fields in Python
snake_case; Bling names must exist only as Pydantic validation/serialization aliases. - Use
validation_alias=AliasChoices("<snake_case>", "<BlingName>")plusserialization_alias="<BlingName>"for generated fields whose Bling name is not already snake_case. - Keep
extra="allow"throughBlingModel; do not bypass its alias normalization or duplicate-alias conflict validation. - Export stable models from
src/bling_erp_api/models/aliases.py. - Create or update
src/bling_erp_api/resources/<resource>.py. - Add the canonical pt-BR method named from
x-api-action. - Add explicit keyword params; never use
**filters. - Convert SDK param names to Bling param names in a helper.
- Use
compact_params()for optional query params. - Use
to_json_object()for request model payloads. - Add an English alias only when preserving compatibility.
- Expose a new resource namespace in
src/bling_erp_api/client.pyif needed. - Add the resource class to
src/bling_erp_api/resources/__init__.pyif new. - Add mapping tests in
tests/unit/test_resources.py. - Mapping tests must assert method, path, params, and body.
- Add a fixture in
tests/fixtures/responses/for important responses. - Add model tests in
tests/unit/test_<resource>_models.py. - Add tests that verify model constructors/signatures expose snake_case, aliases parse Bling payloads,
to_json_object()serializes Bling names, and conflicting snake_case/Bling keys are rejected. - Add docs example only in generated docs or
examples/when commonly used; examples must instantiate models with snake_case fields and typed nested models. - Run
make check.
- OpenAPI source:
specs/bling-openapi-reference.json. - Contract generator:
scripts/generate_openapi_contracts.py. - Generated contracts:
src/bling_erp_api/contracts/generated/. - Generated docs:
docs/resources/. - Generated models:
src/bling_erp_api/models/generated/. - Public model aliases:
src/bling_erp_api/models/aliases.py. - Resource methods:
src/bling_erp_api/resources/. - Resource exports:
src/bling_erp_api/resources/__init__.py. - Client namespaces:
src/bling_erp_api/client.py. - Mapping tests:
tests/unit/test_resources.py. - Contract tests:
tests/unit/test_<resource>_contracts.py. - Model tests:
tests/unit/test_<resource>_models.py. - Response fixtures:
tests/fixtures/responses/. - Examples:
examples/.
- Use pt-BR as canonical public API.
- Use snake_case for SDK params.
- Keep exact Bling names only in payload aliases and query mapping.
- Use
listarforObterMultiplos. - Use
obterforObter. - Use
criarforCriar. - Use
alterarfor fullPUTupdates. - Use
alterar_parcialmentefor partialPATCHupdates. - Use
removerforRemover. - Use
remover_variosforRemoverMultiplos. - Use
alterar_situacaoforAlterarSituacao. Nota: este método só deve ser usado quando o OpenAPI spec daquele recurso declarar a operaçãoAlterarSituacao(recursos comocategorias_receitas_despesasnão possuem esta operação, por exemplo). - Keep English aliases thin and secondary.
- Public Python model fields and constructor kwargs must be snake_case, including nested request models and examples.
- Bling field names such as
descricaoCurta,dataValidade, andidsProdutosare wire-format names only. - Generated Pydantic models must accept Bling field names for parsing API responses and compatibility payloads, but they must not expose those names as the preferred constructor signature.
- Generated fields with a non-snake-case Bling name must use
validation_alias=AliasChoices("<snake_case>", "<BlingName>")andserialization_alias="<BlingName>"; do not use plainalias="<BlingName>". BlingModelowns alias normalization and duplicate-key protection. Do not bypass it with ad hoc dict munging in resources.- If a user payload provides both a Python field name and its Bling alias with different values, validation must fail instead of serializing both keys.
- Resource write methods (
POST,PUT,PATCH) should accept request models when an OpenAPI body schema exists, and must serialize them throughto_json_object(). - Raw
JsonObjectbodies are acceptable only for endpoints not yet modeled or deliberately flexible payloads; when using raw dicts, the caller is responsible for Bling wire-format keys. - Examples should prefer normal model constructors over
model_construct()so type checking and validation catch field-name drift.
Every resource method MUST include a Google-style docstring with the following structure:
- First line: Brief description in pt-BR for canonical methods. For EN aliases:
Compatibility alias formetodo_pt().followed by a blank line and the description. - Endpoint line:
Endpoint: GET|POST|PUT|PATCH|DELETE /path/{param}documenting the exact Bling API path. - Description paragraph: 1-2 sentences explaining what the method does.
- Args section: One line per parameter with:
- SDK parameter name (snake_case)
- Description including the Bling parameter name in backticks (e.g.,
Bling:idProduto, integer, obrigatório) - For path params, mark as
obrigatório; for query params,opcional
- Returns section:
Bling API response. Response schemas: <codes with DTO names>- List each possible response code with the corresponding schema DTO name (e.g.,
200: ContatosDadosBaseDTO; 404: ErrorResponse) - For 204 responses with no body, use
204: NoContent
- List each possible response code with the corresponding schema DTO name (e.g.,
- Class docstring: Must be descriptive including:
- What endpoints the class maps
- Mention that canonical methods are in pt-BR and EN aliases available for compatibility
Reference ProductsResource in src/bling_erp_api/resources/products.py as the canonical example.
def obter(self, id_produto: int) -> JsonObject:
"""Obtém um produto.
Endpoint: GET /produtos/{idProduto}
Obtém um produto pelo ID.
Args:
id_produto: ID do produto (Bling: ``idProduto``, integer, obrigatório)
Returns:
Bling API response. Response schemas: 200: ProdutosDadosBaseDTO; 404: ErrorResponse
"""
return self._get(f"/produtos/{id_produto}")English alias example:
def get(self, product_id: int) -> JsonObject:
"""Compatibility alias for ``obter()``.
Obtém um produto.
Endpoint: GET /produtos/{idProduto}
Obtém um produto pelo ID.
Args:
product_id: ID do produto (Bling: ``idProduto``, integer, obrigatório)
Returns:
Bling API response. Response schemas: 200: ProdutosDadosBaseDTO; 404: ErrorResponse
"""
return self.obter(id_produto=product_id)- Keep the transport rate limiter enabled by default.
- Default local limit is 3 requests per second.
- Retry 429 responses through the transport.
- Respect
Retry-Afterwhen Bling returns it. - Keep integration tests gated behind explicit env vars.
PedidosVenda: resource methods, pt-BR canonical API, English aliases.PedidosVenda: OpenAPI contracts and generated docs.PedidosVenda: semi-generated models and fixtures.Produtos: main/produtosresource methods.Produtos: pt-BR canonical API and English aliases.Produtos: explicit list filters from OpenAPI.Produtos: semi-generated models and fixtures.- Product subgroups: contracts and docs generated.
ProdutosEstruturas: resource methods (client.produtos_estruturas/client.product_structures).ProdutosFornecedores: resource methods (client.produtos_fornecedores/client.product_suppliers).ProdutosLojas: resource methods (client.produtos_lojas/client.product_stores).Lotes: resource methods (client.lotes/client.product_batches).LotesLancamentos: resource methods (client.lotes_lancamentos/client.product_batch_entries).ProdutosVariacoes: resource methods (client.produtos_variacoes/client.product_variations).- Transport accepts JSON arrays as request bodies where Bling expects them (
JsonPayload). - Transport: local rate limiter and 429 retry.
- Client namespaces:
client.pedidos_vendas,client.produtos,client.contatos, product sub-resources e inglês onde há alias (client.contacts, etc.). Contatos: resource methods (client.contatos/client.contacts), contratos OpenAPI, docs gerados e modelos semi-gerados.NotasFiscais(NF-e): resource methods (client.notas_fiscais/client.invoices), 12 pt-BR canonical methods.NotasFiscais(NFC-e): resource methods (client.notas_fiscais_consumidor/client.consumer_invoices), 10 pt-BR canonical methods.NFSe(NFS-e): resource methods (client.notas_servicos/client.service_invoices), pt-BR canonical methods.NotasFiscais: OpenAPI contracts and generated docs.NFSe: OpenAPI contracts and generated docs.NotasFiscais: semi-generated models and fixtures.NFSe: semi-generated models and fixtures.Anuncios: resource methods (client.anuncios/client.ads), 7 pt-BR canonical methods, OpenAPI contracts, generated docs, semi-generated models and fixtures.AnunciosCategorias: resource methods (client.anuncios_categorias/client.ad_categories), 2 pt-BR canonical methods, OpenAPI contracts, generated docs, semi-generated models.Borderos: resource methods (client.borderos), 2 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.CaixasBancos: resource methods (client.caixas_bancos/client.cash_entries), 5 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.CategoriasLojas: resource methods (client.categorias_lojas/client.store_categories), 5 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.CategoriasProdutos: resource methods (client.categorias_produtos/client.product_categories), 5 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.CategoriasReceitasDespesas: resource methods (client.categorias_receitas_despesas/client.income_expense_categories), 6 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.ContasPagar: resource methods (client.contas_pagar/client.accounts_payable), 6 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.ContasReceber: resource methods (client.contas_receber/client.accounts_receivable), 8 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.ContasContabeis: resource methods (client.contas_contabeis/client.financial_accounts), 2 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.Depositos: resource methods (client.depositos/client.warehouses), 4 pt-BR canonical methods. Nota: Não há métodoremover— a API do Bling não expõe um endpoint de exclusão para depósitos. OpenAPI contracts, generated docs, models and fixtures.Empresas: resource methods (client.empresas/client.companies), 1 pt-BR canonical method, OpenAPI contracts, generated docs, models and fixtures.Estoques: resource methods (client.estoques/client.stock), 3 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.FormasPagamentos: resource methods (client.formas_pagamentos/client.payment_methods), 7 pt-BR canonical methods, OpenAPI contracts, models and fixtures.GruposProdutos: resource methods (client.grupos_produtos/client.product_groups), 6 pt-BR canonical methods, OpenAPI contracts, models and fixtures.Homologacao: resource methods (client.homologacao/client.homologation), 5 pt-BR canonical methods, OpenAPI contracts, models and fixtures.Logisticas: resource methods (client.logisticas/client.logistics), 5 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.LogisticasServicos: resource methods (client.logisticas_servicos/client.logistics_services), 5 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.LogisticasObjetos: resource methods (client.logisticas_objetos/client.logistics_objects), 4 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.LogisticasEtiquetas: resource methods (client.logisticas_etiquetas/client.logistics_labels), 1 pt-BR canonical method, OpenAPI contracts, generated docs, models and fixtures.LogisticasRemessas: resource methods (client.logisticas_remessas/client.logistics_shipments), 5 pt-BR canonical methods, OpenAPI contracts, generated docs, models and fixtures.NaturezasOperacoes: resource methods (client.naturezas_operacoes/client.tax_natures), 2 pt-BR canonical methods, OpenAPI contracts, generated docs, semi-generated models and fixtures.Notificacoes: resource methods (client.notificacoes/client.notifications), 3 pt-BR canonical methods, OpenAPI contracts, generated docs, semi-generated models and fixtures.OrdensProducao: resource methods (client.ordens_producao/client.production_orders), 7 pt-BR canonical methods, OpenAPI contracts, generated docs, semi-generated models and fixtures.PedidosCompras: resource methods (client.pedidos_compras/client.purchase_orders), 11 pt-BR canonical methods.PedidosCompras: OpenAPI contracts and generated docs.PedidosCompras: semi-generated models and fixtures.PropostasComerciais: resource methods (client.propostas_comerciais/client.commercial_proposals), 7 pt-BR canonical methods.PropostasComerciais: OpenAPI contracts and generated docs.PropostasComerciais: semi-generated models and fixtures.Situacoes: resource methods (client.situacoes/client.situations), 4 pt-BR canonical methods.SituacoesModulos: resource methods (client.situacoes_modulos/client.situation_modules), 4 pt-BR canonical methods.SituacoesTransicoes: resource methods (client.situacoes_transicoes/client.situation_transitions), 4 pt-BR canonical methods.Situacoes: OpenAPI contracts and generated docs.Situacoes: semi-generated models and fixtures.Vendedores: resource methods (client.vendedores/client.sellers), 2 pt-BR canonical methods.Vendedores: OpenAPI contracts and generated docs.Vendedores: semi-generated models and fixtures.Usuarios: resource methods (client.usuarios/client.users), 3 pt-BR canonical methods.
- Expand model generation beyond semi-generated models.
- Continue vertical slices for accounts, stocks, categories, logistics, and ads.