Skip to content

Comece por aqui

Instalação

Install with pip:

pip install bling-erp-api

Or with uv:

uv add bling-erp-api

Criando um Client

Antes de criar um client, você precisa das credenciais OAuth2 da sua aplicação no Bling ERP (ver Autenticação).

Via variáveis de ambiente (recomendado)

Configure as seguintes variáveis de ambiente:

export BLING_CLIENT_ID="seu_client_id"
export BLING_CLIENT_SECRET="seu_client_secret"
export BLING_REFRESH_TOKEN="seu_refresh_token"

Depois crie um client com from_env():

from bling_erp_api import BlingClient

client = BlingClient.from_env()

Com um token provider personalizado

from bling_erp_api import BlingClient
from bling_jwt_auth import BlingAuth

auth = BlingAuth(
    client_id="seu_client_id",
    client_secret="seu_client_secret",
    refresh_token="seu_refresh_token",
)

client = BlingClient(auth=auth)

Usando context manager

Sempre que possível, use o client como context manager para garantir que os recursos HTTP sejam liberados corretamente:

from bling_erp_api import BlingClient

with BlingClient.from_env() as client:
    # Faça suas chamadas aqui
    pass

Primeira Chamada à API

Listar produtos

from bling_erp_api import BlingClient

with BlingClient.from_env() as client:
    # pt-BR canonical method
    response = client.produtos.listar(limit=5)

    for produto in response.get("data", []):
        print(f'{produto.get("id")}: {produto.get("nome")}')

Ou com o alias em inglês:

with BlingClient.from_env() as client:
    response = client.products.list(limit=5)

    for product in response.get("data", []):
        print(f'{product.get("id")}: {product.get("nome")}')

Obter um contato

with BlingClient.from_env() as client:
    contato = client.contatos.obter(42)
    print(contato)

Trabalhando com modelos tipados

Para endpoints que possuem modelos Pydantic, você recebe objetos tipados:

from bling_erp_api import BlingClient
from bling_erp_api.models.generated.schemas.contatos import ContatoDTO

with BlingClient.from_env() as client:
    contato = client.contatos.obter(42)

    # O payload pode ser acessado com notação de dicionário ou atributos
    if isinstance(contato, dict):
        print(contato.get("data", {}).get("nome"))

Datas de rastreamento

Os campos rastreamento.ultima_alteracao de objetos e remessas usam BlingDatetime. Datas sem fuso, como "2026-10-07 11:24:02", são interpretadas no fuso IANA America/Sao_Paulo, incluindo suas regras históricas de horário de verão. Datas que já possuem fuso mantêm o offset informado pelo Bling. Na serialização JSON, o resultado inclui o offset: "2026-10-07T11:24:02-03:00". A dependência tzdata fornece essas regras também em sistemas sem uma base de fusos instalada.

Sentinelas de data ausente ("0000-00-00 00:00:00", "0000-00-00", "0001-01-01", "0001-01-01 00:00:00"), strings vazias e null são representadas por None. model_dump(mode="json") preserva null; to_json_object() omite esses valores. Outras datas malformadas continuam causando erro de validação, e a chave ultimaAlteracao continua obrigatória no objeto de rastreamento.

Paginação

Endpoints de listagem aceitam page e limit:

with BlingClient.from_env() as client:
    # Página 2, 20 itens por página
    response = client.produtos.listar(page=2, limit=20)

Para autopaginação, veja Paginação.

Tratamento de Erros

Os erros da API são mapeados para exceções tipadas:

from bling_erp_api import BlingClient
from bling_erp_api import (
    BlingAPIError,
    BlingAuthenticationError,
    BlingNotFoundError,
    BlingRateLimitError,
    BlingValidationError,
)

with BlingClient.from_env() as client:
    try:
        produtos = client.produtos.listar()
    except BlingAuthenticationError:
        print("Credenciais inválidas ou expiradas")
    except BlingNotFoundError as exc:
        print(f"Recurso não encontrado: {exc}")
    except BlingValidationError as exc:
        print(f"Erro de validação: {exc}")
    except BlingRateLimitError:
        print("Limite de taxa excedido")
    except BlingAPIError as exc:
        print(f"Erro na API: {exc.status_code} - {exc}")

Veja Erros para a hierarquia completa de exceções.