Bling ERP Skill

SkillCommerce & finance

This connects your AI to your Bling ERP account, so you can ask questions about products, sales orders, contacts, fiscal invoices (NF-e), and stock in plain language. Once added, your AI can look up and manage that information for you, giving you quick answers about your business without digging through Bling yourself.

Available today. Use it from your connected AI after setup.

After adding this, connect your Bling account, then ask your AI about your products, orders, contacts, invoices, or stock.

Then ask your AI: use the Bling ERP Skill skill

What your AI can do with it

  • Look up products and product details in Bling
  • Check and manage sales orders
  • Find and update contact information
  • Look up fiscal invoices (NF-e)
  • Check stock and inventory levels

What this skill tells your AI

The instructions your AI receives, as published by evolution-foundation/evo-nexus in .claude/skills/int-bling/SKILL.md and read by ahel’s review.

Integration with Bling ERP via REST API v3 (OAuth2 Bearer).

When to use

  • List or create products, services, or kits in Bling
  • Create or query sales orders
  • Manage contacts (customers/suppliers)
  • Issue or list fiscal invoices (NF-e)
  • Check or update stock levels

Setup

This skill uses a Python client (scripts/bling_client.py) that handles OAuth2 Bearer auth with automatic refresh on 401. You do OAuth once via the CLI, then the skill refreshes tokens transparently forever.

One-time OAuth setup

  1. Create an app at https://developer.bling.com.br → "Meus Apps"
  2. Set the app's redirect URI to: http://localhost:8787/callback
  3. Copy the Client ID and Client Secret into .env:
    BLING_CLIENT_ID=...
    BLING_CLIENT_SECRET=...
    
  4. Run the login helper:
    make bling-auth
    
    This opens your browser, captures the authorization code via a local callback server, exchanges it for access_token + refresh_token, and persists both to .env.

After this step, .env contains:

BLING_CLIENT_ID=...
BLING_CLIENT_SECRET=...
BLING_ACCESS_TOKEN=...
BLING_REFRESH_TOKEN=...

How the auto-refresh works

scripts/bling_client.py is the single entry point for all API calls. On any HTTP 401, it:

  1. Exchanges BLING_REFRESH_TOKEN for a new access_token + refresh_token at https://www.bling.com.br/Api/v3/oauth/token (Basic auth with Client ID/Secret)
  2. Persists both back to .env and os.environ
  3. Retries the original request once

Bling rotates the refresh token on every refresh, so always use this client — never call the API with raw curl unless you're debugging, otherwise you risk the .env tokens going stale.

Calling the client

python3 .claude/skills/int-bling/scripts/bling_client.py GET /produtos --params page=1 limit=50
python3 .claude/skills/int-bling/scripts/bling_client.py POST /contatos --body '{"nome":"Acme","tipo":"J","numeroDocumento":"12345678000100"}'
python3 .claude/skills/int-bling/scripts/bling_client.py PUT /produtos/123 --body '{"preco":99.90}'

The client prints the JSON response to stdout and logs errors to stderr.


Base URL

https://www.bling.com.br/Api/v3

Products

List products

curl -s -X GET \
  "https://www.bling.com.br/Api/v3/produtos?pagina=1&limite=100" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}"

Query params:

ParamTypeDescription
paginanumberPage number (default 1)
limitenumberItems per page (default 100, max 100)
nomestringFilter by product name
codigostringFilter by SKU/code
tipostringP=Product, S=Service, K=Kit

Create product

curl -s -X POST \
  "https://www.bling.com.br/Api/v3/produtos" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "nome": "Widget Pro",
    "codigo": "WGT-001",
    "preco": 99.90,
    "precoCusto": 45.00,
    "tipo": "P",
    "formato": "S",
    "situacao": "A",
    "unidade": "UN"
  }'

Body fields:

FieldTypeRequiredDescription
nomestringyesProduct name
preconumberyesSale price
tipostringyesP=Product, S=Service, K=Kit
formatostringyesS=Simple, E=With variations, V=Variation
codigostringnoSKU/code
precoCustonumbernoCost price
situacaostringnoA=Active, I=Inactive
unidadestringnoUnit (UN, KG, etc.)
pesoLiquidonumbernoNet weight in kg
pesoBrutonumbernoGross weight in kg

Sales Orders

List orders

curl -s -X GET \
  "https://www.bling.com.br/Api/v3/pedidos/vendas?pagina=1&limite=100&dataInicial=2026-01-01&dataFinal=2026-04-10" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}"

Query params:

ParamTypeDescription
paginanumberPage number
limitenumberItems per page
idsSituacoes[]numberFilter by status ID
dataInicialstringStart date YYYY-MM-DD
dataFinalstringEnd date YYYY-MM-DD

Create order

curl -s -X POST \
  "https://www.bling.com.br/Api/v3/pedidos/vendas" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "contato": { "id": 123456 },
    "data": "2026-04-10",
    "observacoes": "Test order",
    "itens": [
      {
        "produto": { "id": 789 },
        "quantidade": 2,
        "valor": 99.90,
        "desconto": 0
      }
    ]
  }'

Body fields:

FieldTypeRequiredDescription
contato.idnumberyesContact (customer) ID
itensarrayyesOrder line items
itens[].produto.idnumberyesProduct ID
itens[].quantidadenumberyesQuantity
itens[].valornumberyesUnit price
itens[].descontonumbernoDiscount amount
datastringnoOrder date YYYY-MM-DD
observacoesstringnoNotes

Contacts

List contacts

curl -s -X GET \
  "https://www.bling.com.br/Api/v3/contatos?pagina=1&limite=100&tipoPessoa=J" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}"

Query params:

ParamTypeDescription
paginanumberPage number
limitenumberItems per page
nomestringFilter by name
tipoPessoastringF=Individual (CPF), J=Legal entity (CNPJ)

Create contact

curl -s -X POST \
  "https://www.bling.com.br/Api/v3/contatos" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "nome": "Empresa Exemplo LTDA",
    "tipo": "J",
    "numeroDocumento": "12345678000199",
    "email": "contato@empresa.com",
    "telefone": "31999990000"
  }'

Body fields:

FieldTypeRequiredDescription
nomestringyesContact name
tipostringyesF=Individual, J=Legal entity
numeroDocumentostringnoCPF or CNPJ
emailstringnoEmail address
telefonestringnoPhone number
celularstringnoMobile phone

Fiscal Invoices (NF-e)

List invoices

curl -s -X GET \
  "https://www.bling.com.br/Api/v3/nfe?pagina=1&limite=100" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}"

Query params:

ParamTypeDescription
paginanumberPage number
limitenumberItems per page
situacaonumberFilter by status code

Create invoice (from order)

curl -s -X POST \
  "https://www.bling.com.br/Api/v3/nfe" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "pedidoVendaId": 456,
    "tipo": 1,
    "naturezaOperacao": "Venda de mercadoria"
  }'

Body fields:

FieldTypeRequiredDescription
pedidoVendaIdnumberyesSales order ID to generate invoice from
tiponumbernoInvoice type: 1=Output (Saída), 0=Input (Entrada)
naturezaOperacaostringnoOperation nature description

Stock

Get stock for a product

curl -s -X GET \
  "https://www.bling.com.br/Api/v3/estoques/saldos?idsProdutos[]=789" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}"

Update stock

curl -s -X POST \
  "https://www.bling.com.br/Api/v3/estoques" \
  -H "Authorization: Bearer ${BLING_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "produto": { "id": 789 },
    "deposito": { "id": 1 },
    "operacao": "E",
    "quantidade": 50,
    "observacoes": "Stock received from supplier"
  }'

Body fields:

FieldTypeRequiredDescription
produto.idnumberyesProduct ID
deposito.idnumberyesWarehouse/deposit ID
operacaostringyesB=Balance (set), E=Entry (add), S=Exit (subtract)
quantidadenumberyesQuantity
observacoesstringnoNotes

Auth Model

  • Type: OAuth2 Bearer Token
  • Header: Authorization: Bearer <token>
  • Token lifetime: short-lived; must be refreshed using the OAuth2 refresh token flow
  • Scopes: defined per app in the Bling developer portal

Pagination

All list endpoints use:

  • pagina — page number (1-indexed)
  • limite — items per page (default 100, max 100)

Date filters use YYYY-MM-DD format.

Rate Limits

Bling API v3 does not publish a hard rate limit publicly. Observed safe throughput is ~10 requests/second. Back off on HTTP 429 responses. For detailed limits, see https://developer.bling.com.br.

Notes

  • This skill is based on the MCP implementation at workspace/projects/mcp-dev-brasil/packages/erp/bling/src/index.ts (mcp-dev-brasil project)
  • For advanced endpoints not listed here (product variations, fiscal settings, categories, etc.), consult the official docs at https://developer.bling.com.br
  • The OAuth2 token management (refresh flow) is not automated by this skill — ensure BLING_ACCESS_TOKEN is fresh before making calls

Signals

GitHub stars
533
Forks
177
Last commit
May 2026
Advanced
Catalog kind
skill
Gateway key
int-bling
Source
github.com/evolution-foundation/evo-nexus