Metadata-Version: 2.4
Name: brasilnfe
Version: 1.1.0
Summary: SDK oficial Python para integração com a API Brasil NFe - Emissão de NF-e, NFC-e, NFS-e, CT-e, MDF-e, DC-e e mais
Author-email: Brasil NFe LTDA <contato@brasilnfe.com.br>
License: MIT
Project-URL: Homepage, https://www.brasilnfe.com.br
Project-URL: Documentation, https://github.com/BrasilNFe/brasilnfe-python-sdk#readme
Project-URL: Repository, https://github.com/BrasilNFe/brasilnfe-python-sdk
Project-URL: Issues, https://github.com/BrasilNFe/brasilnfe-python-sdk/issues
Keywords: nfe,nfce,nfse,cte,mdfe,dce,nota-fiscal,brasil,sefaz,sped,sintegra,fiscal,api
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: Portuguese (Brazilian)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Accounting
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28.0
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: pytest-mock>=3.11; extra == "dev"
Requires-Dist: responses>=0.24; extra == "dev"
Requires-Dist: mypy>=1.5; extra == "dev"
Requires-Dist: ruff>=0.1; extra == "dev"
Requires-Dist: types-requests>=2.28; extra == "dev"
Dynamic: license-file

# Brasil NFe — SDK Python

SDK oficial em Python para a API [Brasil NFe](https://www.brasilnfe.com.br).
Emissão, cancelamento, consulta e gestão de documentos fiscais eletrônicos
brasileiros (NF-e, NFC-e, NFS-e, CT-e, MDF-e, DC-e, NF3-e), geração de SPED /
SINTEGRA / FCI, e gestão de empresas e certificados digitais — em uma única
biblioteca idiomática, tipada e testada.

Paridade 100% com os SDKs oficiais em **C#**, **PHP** e **Node**.

[![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![typed](https://img.shields.io/badge/typed-yes-brightgreen)](https://peps.python.org/pep-0561/)

---

## Sumário

1. [Instalação](#instalação)
2. [Quickstart](#quickstart)
3. [Autenticação](#autenticação)
4. [Arquitetura](#arquitetura)
5. [Recursos](#recursos)
6. [Exemplos por recurso](#exemplos-por-recurso)
   - [Nota Fiscal (emissão)](#nota-fiscal-emissão)
   - [Eventos](#eventos)
   - [Consultas](#consultas)
   - [Arquivos](#arquivos)
   - [Empresa](#empresa)
7. [Tratamento de erros](#tratamento-de-erros)
8. [Utilitários](#utilitários)
9. [Configuração avançada](#configuração-avançada)
10. [Desenvolvimento](#desenvolvimento)
11. [Tabelas de referência](#tabelas-de-referência)
12. [Suporte](#suporte)

---

## Instalação

```bash
pip install brasilnfe
```

Requisitos:

- Python **3.8+**
- [`requests`](https://pypi.org/project/requests/) (instalado automaticamente)

---

## Quickstart

```python
from brasilnfe import BrasilNFe, StatusSefazEnvio

client = BrasilNFe(token="SEU_TOKEN_AQUI")

resp = client.consultas.status_sefaz(
    StatusSefazEnvio(modelo_documento=55, tipo_ambiente=2)
)

print(resp.status_sefaz.ds_status_resposta_sefaz)  # "Serviço em operação"
```

Parâmetros do cliente:

| Parâmetro    | Tipo               | Obrigatório | Default                                          |
| ------------ | ------------------ | ----------- | ------------------------------------------------ |
| `token`      | `str`              | **sim**     | —                                                |
| `user_token` | `str`              | não         | `""` (necessário para o recurso `empresa`)       |
| `url`        | `str`              | não         | `"https://api.brasilnfe.com.br/services/"`       |
| `timeout`    | `int` (segundos)   | não         | `300`                                            |
| `session`    | `requests.Session` | não         | sessão padrão (permita configurar retries/proxy) |

---

## Autenticação

O SDK usa **dois tokens** enviados nos headers HTTP:

- `Token` — **obrigatório**, identifica a empresa.
- `UserToken` — opcional, identifica o usuário (necessário só para o recurso
  `empresa`).

```python
# Só emissão/consulta:
client = BrasilNFe(token="TOKEN_EMPRESA")

# Com gestão de empresas:
client = BrasilNFe(token="TOKEN_EMPRESA", user_token="TOKEN_USUARIO")
```

Os tokens são obtidos no portal <https://www.brasilnfe.com.br>.

---

## Arquitetura

O SDK segue a mesma estrutura dos SDKs C# (principal), PHP e Node:

```
BrasilNFe                       ← fachada principal
├── .nota_fiscal   (NotaFiscal)  ← emitir NF-e, NFC-e, NFS-e, CT-e, MDF-e, DC-e, NF3-e
├── .eventos       (Eventos)     ← cancelar, CC-e, inutilizar, manifestar, encerrar MDF-e
├── .consultas     (Consultas)   ← status SEFAZ, busca, cadastro, cálculo de impostos
├── .arquivos      (Arquivos)    ← SPED, SINTEGRA, FCI, XML, DANFE
└── .empresa       (Empresa)     ← cadastro de empresas e certificados A1
```

Todos os modelos são `@dataclass` tipados com `snake_case` (PEP 8). O
serializer interno converte automaticamente para o formato da API
(`PascalCase`/`camelCase`) e vice-versa, sem nenhuma configuração adicional.

---

## Recursos

### Tabela de features

| Categoria              | Método                                       | Recurso       |
| ---------------------- | -------------------------------------------- | ------------- |
| **Emissão**            | `enviar_nota_fiscal`                         | `nota_fiscal` |
|                        | `enviar_nota_fiscal_lote`                    | `nota_fiscal` |
|                        | `enviar_nota_fiscal_servico` (NFS-e)         | `nota_fiscal` |
|                        | `enviar_nota_fiscal_complementar`            | `nota_fiscal` |
|                        | `enviar_manifesto_transporte` (MDF-e)        | `nota_fiscal` |
|                        | `enviar_conhecimento_transporte` (CT-e)      | `nota_fiscal` |
|                        | `enviar_declaracao_conteudo` (DC-e)          | `nota_fiscal` |
|                        | `enviar_nf_enercom` (NF3-e/NFCom)            | `nota_fiscal` |
| **Eventos**            | `cancelar_nota_fiscal`                       | `eventos`     |
|                        | `enviar_carta_correcao`                      | `eventos`     |
|                        | `inutilizar_numeracao`                       | `eventos`     |
|                        | `manifestar_nota_fiscal`                     | `eventos`     |
|                        | `encerrar_manifesto_transporte`              | `eventos`     |
| **Consultas**          | `status_sefaz`                               | `consultas`   |
|                        | `calcular_impostos`                          | `consultas`   |
|                        | `pre_visualizar_nota_fiscal`                 | `consultas`   |
|                        | `buscar_nota_fiscal`                         | `consultas`   |
|                        | `buscar_nota_fiscal_servico`                 | `consultas`   |
|                        | `consultar_cadastro_sefaz`                   | `consultas`   |
|                        | `buscar_arquivo_sped`                        | `consultas`   |
| **Arquivos**           | `obter_arquivo_sintegra`                     | `arquivos`    |
|                        | `obter_arquivo_fci`                          | `arquivos`    |
|                        | `obter_arq_enercom`                          | `arquivos`    |
|                        | `obter_arquivo_sped`                         | `arquivos`    |
|                        | `obter_arquivo_sped_unificado`               | `arquivos`    |
|                        | `recriar_arquivo_sped`                       | `arquivos`    |
|                        | `pegar_arquivo` (XML/DANFE → `bytes`)        | `arquivos`    |
|                        | `pegar_arquivo_evento` (→ `bytes`)           | `arquivos`    |
|                        | `obter_arquivos_por_range`                   | `arquivos`    |
| **Empresa**            | `alterar_certificado`                        | `empresa`     |
|                        | `verificar_certificado`                      | `empresa`     |
|                        | `adicionar_empresa`                          | `empresa`     |
|                        | `editar_empresa`                             | `empresa`     |
|                        | `buscar_empresa`                             | `empresa`     |
|                        | `buscar_todas_empresas`                      | `empresa`     |

**Total:** 36 métodos públicos (paridade com C#/PHP/Node).

---

## Exemplos por recurso

### Nota Fiscal (emissão)

#### NF-e (modelo 55)

```python
from datetime import datetime
from brasilnfe import (
    BrasilNFe, Cliente, Contato, Endereco, Imposto, Icms, Pis, Cofins,
    NotaFiscalEnvio, Pagamento, Produto,
)

client = BrasilNFe(token="SEU_TOKEN")

nf = NotaFiscalEnvio(
    modelo_documento=55,
    tipo_ambiente=2,                         # 2 = Homologação
    finalidade=1,                            # 1 = Normal
    natureza_operacao="VENDA DE MERCADORIA",
    data_emissao=datetime.now(),
    indicador_presenca=1,
    consumidor_final=True,
    cliente=Cliente(
        cpf_cnpj="11144477735",
        nm_cliente="Cliente Teste",
        indicador_ie=9,                      # 9 = Não contribuinte
        endereco=Endereco(
            cep="01310100",
            logradouro="Avenida Paulista",
            numero="1000",
            bairro="Bela Vista",
            cod_municipio="3550308",
            municipio="São Paulo",
            uf="SP",
            cod_pais=1058,
            pais="Brasil",
        ),
        contato=Contato(email="cliente@example.com"),
    ),
    produtos=[
        Produto(
            nm_produto="Notebook XPS 13",
            cod_produto_servico="NB-001",
            ean="SEM GTIN",
            ncm="84713012",
            cfop=5102,
            unidade_comercial="UN",
            quantidade=1,
            valor_unitario=5500.00,
            valor_total=5500.00,
            origem_produto=0,
            imposto=Imposto(
                icms=Icms(cod_situacao_tributaria="102"),
                pis=Pis(cod_situacao_tributaria="49"),
                cofins=Cofins(cod_situacao_tributaria="49"),
            ),
        ),
    ],
    pagamentos=[
        Pagamento(indicador_pagamento=0, forma_pagamento="01", vl_pago=5500.00),
    ],
)

resp = client.nota_fiscal.enviar_nota_fiscal(nf, crt=1)   # 1 = Simples Nacional

if resp.ok and resp.return_nf.ok:
    print(f"Chave: {resp.return_nf.chave_nf}")
    print(f"Status: {resp.return_nf.ds_status_resposta_sefaz}")
    # XML e DANFE em base64: resp.base64_xml, resp.base64_file
else:
    print(f"Rejeitada: {resp.error or resp.return_nf.ds_status_resposta_sefaz}")
```

#### NFC-e (modelo 65)

Mesmo `NotaFiscalEnvio`, trocando `modelo_documento=65` e acrescentando
`indicador_presenca=1` (presencial) + um `Pagamento` válido.

#### NFS-e (serviço)

```python
from brasilnfe import (
    BrasilNFe, NotaFiscalServicoEnvio, NFSInfo, Tomador, Servico, Valores,
)

client = BrasilNFe(token="SEU_TOKEN")

nfse = NotaFiscalServicoEnvio(
    tipo_ambiente=2,
    nfs_info=[
        NFSInfo(
            tomador=Tomador(nome="Contratante LTDA", cpf_cnpj="12345678000199"),
            servico=Servico(
                descricao="Consultoria em TI",
                item_lista_servico="01.01",
                valores=Valores(valor_servico=1500.00, aliquota=5.0),
            ),
        )
    ],
)
resp = client.nota_fiscal.enviar_nota_fiscal_servico(nfse)
```

#### CT-e / MDF-e / DC-e

```python
from brasilnfe import CTeEnvio, DCeEnvio, ManifestoTransporteEnvio

client.nota_fiscal.enviar_conhecimento_transporte(CTeEnvio(...))
client.nota_fiscal.enviar_manifesto_transporte(ManifestoTransporteEnvio(...))
client.nota_fiscal.enviar_declaracao_conteudo(DCeEnvio(...))
```

### Eventos

#### Cancelar NF-e / NFC-e / CT-e

```python
from brasilnfe import BrasilNFe, CancelarNotaFiscalEnvio

client = BrasilNFe(token="SEU_TOKEN")

resp = client.eventos.cancelar_nota_fiscal(
    CancelarNotaFiscalEnvio(
        chave_nf="35250312345678901234567890123456789012345678",
        justificativa="Erro de digitação na quantidade.",
        tipo_documento=0,          # 0 = NF/NFC/CT/MDF/DC, 1 = NFS-e
        tipo_ambiente=2,
    )
)
# resp.status: 1=Processado, 2=Aguardando, 3=Erro
```

#### Carta de Correção (CC-e)

```python
from brasilnfe import CartaCorrecaoEnvio

client.eventos.enviar_carta_correcao(
    CartaCorrecaoEnvio(
        chave_nf="3525...",
        correcao="Correção do endereço do destinatário.",
        numero_sequencial=1,
        tipo_ambiente=2,
    )
)
```

#### Inutilização, Manifestação, Encerramento MDF-e

```python
from brasilnfe import (
    InutilizarNumeracaoEnvio, ManifestarNotaFiscalEnvio,
    EncerrarManifestoTransporteEnvio,
)

client.eventos.inutilizar_numeracao(
    InutilizarNumeracaoEnvio(
        modelo_documento=55, serie=1,
        numero_inicial=100, numero_final=105,
        justificativa="Salto de numeração no sistema interno.",
        tipo_ambiente=2, ano=2025,
    )
)

client.eventos.manifestar_nota_fiscal(
    ManifestarNotaFiscalEnvio(
        chave="3525...",
        tipo_manifestacao=1,    # 1=Confirmação, 2=Ciência, 3=Desconhece, 4=Não realizada
    )
)

client.eventos.encerrar_manifesto_transporte(
    EncerrarManifestoTransporteEnvio(chave_mdfe="5825...", uf_encerramento="SP")
)
```

### Consultas

```python
from brasilnfe import (
    StatusSefazEnvio, BuscarNotaFiscalEnvio, ConsultarCadastroEnvio,
    PreVisualizarNotaFiscalEnvio, Produto,
)
from datetime import datetime

# Status SEFAZ
client.consultas.status_sefaz(StatusSefazEnvio(modelo_documento=55, tipo_ambiente=1))

# Buscar NF-e/NFC-e/CT-e emitidas no período (0=entrada, 1=saída)
client.consultas.buscar_nota_fiscal(BuscarNotaFiscalEnvio(
    tipo_documento_fiscal=1,
    dt_inicio=datetime(2025, 3, 1),
    dt_fim=datetime(2025, 3, 31),
))

# Consultar cadastro
client.consultas.consultar_cadastro_sefaz(
    ConsultarCadastroEnvio(cpf_cnpj_ie="12345678000199", uf="SP")
)

# Calcular impostos (sem emitir)
client.consultas.calcular_impostos(produtos=[Produto(...)])

# Pré-visualizar DANFE
client.consultas.pre_visualizar_nota_fiscal(PreVisualizarNotaFiscalEnvio(...))

# Buscar SPED já gerado
client.consultas.buscar_arquivo_sped(codigo="ABC123")
```

### Arquivos

```python
from pathlib import Path
from brasilnfe import PegarArquivoEnvio, SpedEnvio, SintegraEnvio

# Baixar DANFE em PDF
pdf = client.arquivos.pegar_arquivo(
    PegarArquivoEnvio(chaves=["3525..."], file_type=2, tipo_documento_fiscal=1)
)
Path("danfe.pdf").write_bytes(pdf)

# Baixar XML
xml = client.arquivos.pegar_arquivo(
    PegarArquivoEnvio(chaves=["3525..."], file_type=1, tipo_documento_fiscal=1)
)

# Gerar SPED Fiscal
from datetime import datetime
client.arquivos.obter_arquivo_sped(SpedEnvio(
    crt=3, dt_inicio=datetime(2025,3,1), dt_fim=datetime(2025,3,31),
))

# SPED unificado, SINTEGRA, FCI, recriar SPED, range por período
# — mesmos padrões (ver exemplos na pasta examples/).
```

### Empresa

> Requer `user_token` na inicialização.

```python
from brasilnfe import BrasilNFe, CertificadoEnvio, EmpresaEnvio, Endereco
import base64

client = BrasilNFe(token="TOKEN_EMPRESA", user_token="TOKEN_USUARIO")

# Cadastrar empresa
client.empresa.adicionar_empresa(EmpresaEnvio(
    cnpj="12345678000199",
    rz_social="ACME LTDA",
    nm_fantasia="ACME",
    ie="1234567890",
    crt=3,
    endereco=Endereco(cep="01310100", uf="SP", municipio="São Paulo"),
))

# Listar empresas
empresas = client.empresa.buscar_todas_empresas()

# Alterar certificado A1 (.pfx em base64)
pfx = base64.b64encode(open("cert.pfx", "rb").read()).decode()
client.empresa.alterar_certificado(
    CertificadoEnvio(base64_certificate_file=pfx, senha="senha-do-pfx")
)

# Verificar certificado
info = client.empresa.verificar_certificado(
    CertificadoEnvio(base64_certificate_file=pfx, senha="senha-do-pfx")
)
print(info.cn, info.validade)
```

---

## Tratamento de erros

O SDK diferencia três camadas de erro:

```python
from brasilnfe import (
    BrasilNFeError, BrasilNFeRequestError, BrasilNFeResponseError,
    BrasilNFeSerializationError, BrasilNFeAuthenticationError,
)

try:
    resp = client.nota_fiscal.enviar_nota_fiscal(nf)
except BrasilNFeRequestError as e:
    # Falha de rede / timeout / erro HTTP de transporte
    print("erro de rede:", e, "original:", e.original)
except BrasilNFeResponseError as e:
    # Resposta HTTP fora da faixa 2xx
    print("status:", e.status_code, "body:", e.body)
except BrasilNFeSerializationError as e:
    # JSON inválido, base64 inválido, etc
    print("serialização:", e)
else:
    # Rejeições da SEFAZ não lançam exceção — verificar resp.error/resp.return_nf
    if not resp.ok:
        print("rejeitada:", resp.error, resp.avisos)
```

Hierarquia:

```
BrasilNFeError
├── BrasilNFeRequestError          (rede / timeout)
├── BrasilNFeResponseError         (HTTP ≠ 2xx)
├── BrasilNFeSerializationError    (JSON / base64)
├── BrasilNFeAuthenticationError   (tokens ausentes)
└── BrasilNFeValidationError       (validação pré-envio)
```

---

## Utilitários

### Serialização direta

Todos os modelos expõem `.to_dict()` / `.from_dict(data)`:

```python
from brasilnfe import NotaFiscalEnvio
nf = NotaFiscalEnvio(modelo_documento=55, tipo_ambiente=2)
payload = nf.to_dict()               # dict pronto para JSON
nf2 = NotaFiscalEnvio.from_dict(payload)
```

### Rateio de valores (frete / desconto / seguro)

```python
from dataclasses import dataclass
from brasilnfe import BrasilNFeHelper, TipoRateio

@dataclass
class Item:
    valor_total: float
    valor_frete: float = 0.0

itens = [Item(300.0), Item(200.0), Item(500.0)]

BrasilNFeHelper.ratear(
    itens,
    valor_total=50.0,
    seletor=lambda i: i.valor_frete,
    seletor_proporcao=lambda i: i.valor_total,
    tipo_rateio=TipoRateio.SUBSTITUIR,
    atualizar_item=lambda i, v: setattr(i, "valor_frete", v),
)
# Arredondamento correto: soma bate exatamente em 50.00
```

---

## Configuração avançada

### Timeout customizado

```python
client = BrasilNFe(token="...", timeout=600)   # 10 minutos
```

### `requests.Session` com retry

```python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
session.mount("https://", HTTPAdapter(
    max_retries=Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
))

client = BrasilNFe(token="...", session=session)
```

### Apontar para sandbox / URL alternativa

```python
client = BrasilNFe(token="...", url="https://sandbox.brasilnfe.com.br/services/")
```

---

## Desenvolvimento

```bash
git clone https://github.com/BrasilNFe/brasilnfe-python-sdk.git
cd brasilnfe-python-sdk
pip install -e ".[dev]"
pytest -v
```

Lint / type check:

```bash
ruff check brasilnfe tests
mypy brasilnfe
```

---

## Tabelas de referência

### Modelos de documento

| Modelo | Documento                                    |
| ------ | -------------------------------------------- |
| 55     | NF-e (Nota Fiscal Eletrônica)                |
| 57     | CT-e (Conhecimento de Transporte Eletrônico) |
| 58     | MDF-e (Manifesto de Documentos Fiscais)      |
| 65     | NFC-e (Nota Fiscal de Consumidor)            |
| 66     | NF3-e / NFCom                                |

### Ambientes

| Código | Ambiente                         |
| ------ | -------------------------------- |
| 1      | Produção (efeito fiscal real)    |
| 2      | Homologação (testes na SEFAZ)    |

### CRT (Regime Tributário)

| Código | Regime                         |
| ------ | ------------------------------ |
| 1      | Simples Nacional               |
| 2      | Simples Nacional c/ Sublimite  |
| 3      | Regime Normal                  |
| 4      | MEI                            |

### Finalidade da NF-e

| Código | Finalidade   |
| ------ | ------------ |
| 1      | Normal       |
| 2      | Complementar |
| 3      | Ajuste       |
| 4      | Devolução    |

### Status de evento SEFAZ

| Código | Significado              |
| ------ | ------------------------ |
| 1      | Evento processado        |
| 2      | Aguardando processamento |
| 3      | Ocorreu um erro          |

### Headers enviados pelo SDK

| Header            | Valor                      |
| ----------------- | -------------------------- |
| `Token`           | token da empresa           |
| `UserToken`       | token do usuário           |
| `Package-Version` | `1.1.0`                    |
| `Package-Type`    | `python`                   |
| `User-Agent`      | `brasilnfe-python-sdk/...` |

---

## Suporte

- Portal: <https://www.brasilnfe.com.br>
- Documentação da API: <https://www.brasilnfe.com.br/docs>
- Issues: <https://github.com/BrasilNFe/brasilnfe-python-sdk/issues>
- E-mail: contato@brasilnfe.com.br

SDKs em outras linguagens:

- **C# (principal)**: <https://github.com/BrasilNFe/brasil-nfe>
- **PHP**: <https://github.com/BrasilNFe/brasilnfe-php-sdk>
- **Node/TypeScript**: <https://github.com/BrasilNFe/brasilnfe-node-sdk>

---

## Licença

[MIT](LICENSE) © Brasil NFe LTDA
