Pular para o conteúdo
m MARX / docs

/ Notas fiscais

Notas fiscais de serviço (NFS-e) — beta

Com a API de NFS-e a sua empresa emite notas fiscais de serviço eletrônicas no Padrão Nacional a partir da marx: você envia um JSON simples e a marx monta, assina e transmite a nota ao Ambiente Nacional da NFS-e, guarda o XML e gera o PDF (DANFSe).

Importante

Beta, sob liberação. A NFS-e não está disponível publicamente: ela é liberada pelo time marx, por empresa. Sem a liberação, todos os endpoints respondem 403 com "NFS-e is not enabled for this company". Durante o beta, campos podem ser adicionados e mensagens de erro podem mudar; avisaremos antes de qualquer mudança incompatível.

Nota

Funciona para prestadores de municípios que emitem pelo Emissor Nacional (Padrão Nacional da NFS-e). Municípios com sistema próprio de nota ainda não são atendidos. NF-e de produtos não faz parte desta API.

Como funciona

  1. Você cadastra o emissor (o CNPJ que emite as notas), envia o certificado digital A1 desse CNPJ e cadastra os serviços que ele presta.
  2. Cada nota é pedida com POST /api/nfse e um reference seu. A resposta é imediata (202) e a nota segue para a fila de emissão.
  3. O resultado chega por webhook (event_type_nfse_authorized ou event_type_nfse_rejected) e também pode ser consultado na API.
  4. Notas autorizadas têm PDF e XML disponíveis, e podem ser canceladas ou substituídas.

Você nunca envia XML nem códigos do leiaute fiscal: a marx traduz os campos (tabela no fim da página).

Configuração passo a passo

Todas as chamadas usam as mesmas credenciais da API de pagamentos (X-Client-Id e X-Client-Secret, veja Credenciais e autenticação).

1. Cadastre o emissor

POST /api/nfse/issuers

Shell
curl -X POST https://marx.loco.ltd/api/nfse/issuers \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{
    "cnpj": "11.222.333/0001-81",
    "legal_name": "Minha Empresa LTDA",
    "municipal_registration": "0101010101",
    "city_ibge": "4106902",
    "tax_regime": "simples",
    "simples_collection": "das",
    "series": "900",
    "approximate_tax_percent": "6.00",
    "email": "fiscal@minhaempresa.com.br"
  }'
Campo Obrigatório Descrição
cnpj sim CNPJ do prestador (com ou sem pontuação; aceita o CNPJ alfanumérico). O dígito verificador é conferido. Não pode ser alterado depois.
legal_name sim Razão social.
municipal_registration depende do município Inscrição municipal como aparece no campo "Indicador Municipal" do Emissor Nacional (Emissão completa → Emitente). Pode ser diferente do número do cartão da prefeitura.
send_municipal_registration não true (padrão). Use false só se o seu município rejeitar a inscrição na nota.
city_ibge não Código IBGE do município do prestador (7 dígitos). Padrão: 4106902 (Curitiba).
tax_regime não simples (ME/EPP, padrão), mei ou regular (não optante).
simples_collection não Para o Simples: das (tributos federais e ISS pelo DAS, padrão), iss_outside_das ou all_outside_das. Confirme com o seu contador.
special_regime não Regime especial de tributação do município. 0 = nenhum (padrão).
series não Série da DPS, até 89999. Use uma série só para a marx, diferente da usada no portal do Emissor Nacional, para a numeração nunca se repetir.
email não E-mail do prestador na nota.
auto_issue_on_payment não true para emitir a nota automaticamente quando uma cobrança for paga (veja abaixo).
email_customer não true para enviar PDF e XML por e-mail ao tomador quando a nota for autorizada.
iss_withholding_rate não Alíquota (%) usada nas notas com ISS retido pelo tomador. Até 5%.
description_footer não Texto somado ao fim da descrição de toda nota, ex. "Documento emitido por ME ou EPP optante pelo Simples Nacional.".
ibs_cbs a partir de 2027 { "cst", "class_code", "operation_indicator" } padrão do emissor para o grupo IBS/CBS (veja IBS e CBS).
approximate_tax_percent sim para ME/EPP Percentual aproximado de tributos (Lei 12.741) padrão do emissor, ex. "6.00": a alíquota efetiva do Simples. O Ambiente Nacional recusa notas de ME/EPP sem ele (E0712). Cada serviço pode ter o seu.

A resposta (201) traz o emissor com ready: false e a lista do que falta em missing: certificate, service, approximate_tax_percent (ME/EPP sem percentual) e activation. O emissor nasce inativo e em teste.

Dica

Nos caminhos /api/nfse/issuers/{id} você pode usar o id do emissor ou o próprio CNPJ só com números/letras (/api/nfse/issuers/11222333000181).

2. Envie o certificado digital A1

PUT /api/nfse/issuers/{id}/certificate

O certificado e-CNPJ A1 (ICP-Brasil) do próprio CNPJ do emissor assina as notas. Envie o arquivo .pfx (ou .p12) e a senha:

Shell
curl -X PUT https://marx.loco.ltd/api/nfse/issuers/11222333000181/certificate \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -F file=@certificado-a1.pfx -F password="$SENHA_DO_CERTIFICADO"

Ou em JSON, com o arquivo em Base64: {"pfx_base64": "MIIK…", "password": "…"}.

O certificado só é aceito se abrir com a senha, contiver a chave privada, estiver dentro da validade e for um e-CNPJ do mesmo CNPJ do emissor (o Ambiente Nacional recusa notas assinadas com certificado de outro CNPJ, inclusive de contador ou procurador).

  • O arquivo e a senha ficam guardados criptografados e nunca são devolvidos pela API. As respostas trazem só os dados públicos: titular, CNPJ, validade e impressão digital (fingerprint_sha256).
  • GET /api/nfse/issuers/{id}/certificate mostra esses dados; DELETE remove o certificado (o emissor para de emitir até receber outro).
  • Renovação: o A1 vale 1 ano. Envie o novo com o mesmo PUT; ele substitui o anterior na hora. Guarde sempre uma cópia do .pfx e da senha no seu cofre de senhas.

3. Cadastre os serviços

POST /api/nfse/issuers/{id}/services

Shell
curl -X POST https://marx.loco.ltd/api/nfse/issuers/11222333000181/services \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "code": "01.03.01", "nbs": "1.1506.21.00", "description": "Assinatura de software (SaaS)" }'
Campo Obrigatório Descrição
code sim Código de tributação nacional do serviço (6 dígitos; pontuação é ignorada).
nbs sim Código NBS (9 dígitos).
description sim Texto padrão que vai na nota quando o pedido não traz descrição.
municipal_code não Código de tributação municipal (3 dígitos), quando o município exigir.
iss_rate não Alíquota de ISS em %, só quando o ISS não é recolhido pelo Simples.
approximate_tax_percent não Percentual aproximado de tributos deste serviço, quando o anexo do Simples dele é diferente do padrão do emissor.
ibs_cbs não { "cst", "class_code", "operation_indicator" } deste serviço (vazio = padrão do emissor).
default não Serviço padrão do emissor. O primeiro cadastrado já é o padrão.

Os códigos e a NBS de cada serviço são definidos com o seu contador. GET lista os serviços, PATCH /api/nfse/issuers/{id}/services/{service_id} altera e DELETE remove um serviço que ainda não foi usado em nenhuma nota.

4. Ative o emissor

Shell
curl -X PATCH https://marx.loco.ltd/api/nfse/issuers/11222333000181 \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -H "Content-Type: application/json" -d '{"active": true}'

A ativação só é aceita quando não falta mais nada: a resposta passa a trazer "ready": true e "missing": [].

5. Teste e produção

Todo emissor começa em teste ("environment": "test"): as notas vão para o ambiente de produção restrita do Emissor Nacional e não têm valor fiscal. A numeração de teste é separada, então os testes não deixam buracos na numeração real.

Faça os testes que precisar (emitir, consultar, cancelar, substituir). Quando estiver tudo certo, peça ao time marx para mudar o emissor para produção. A partir daí as notas são reais. Cada nota informa em que ambiente foi emitida (environment).

Atenção

Antes da primeira nota em produção, confirme com o seu contador o regime, os códigos de serviço, a NBS, a inscrição municipal e o texto obrigatório da descrição. Uma nota emitida com dados errados precisa ser cancelada ou substituída.

Emitir uma nota

POST /api/nfse

Shell
curl -X POST https://marx.loco.ltd/api/nfse \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "fatura-2026-10-0042",
    "amount": "149.90",
    "competence_date": "2026-10-01",
    "customer": {
      "tax_id": "11.222.333/0001-81",
      "name": "Cliente LTDA",
      "email": "financeiro@cliente.com.br"
    },
    "service": { "code": "010301", "description": "Assinatura Pro — outubro/2026" }
  }'
Campo Obrigatório Descrição
reference sim Seu identificador da nota (fatura, pedido). Único para sempre por empresa: repetir o mesmo reference devolve a nota existente (200) e nunca emite outra. Também aceito no cabeçalho Idempotency-Key.
amount sim Valor do serviço, texto com ponto decimal.
customer.tax_id sim CPF (11) ou CNPJ (14) do tomador; aceita pontuação e CNPJ alfanumérico.
customer.name sim Nome ou razão social do tomador.
customer.email não Recebe o PDF e o XML se o emissor tiver email_customer.
customer.country não Código do país (ISO, 2 letras). Padrão BR. Outro país = tomador no exterior: tax_id passa a ser o identificador fiscal estrangeiro.
customer.address não postal_code, street, number, complement, district, city_ibge.
service.code não Um dos serviços do emissor. Padrão: o serviço padrão.
service.description não Texto da nota. Padrão: a descrição do serviço.
competence_date não Data de competência (AAAA-MM-DD). Padrão: hoje.
issuer_id não id ou CNPJ do emissor, se a sua empresa tiver mais de um. Padrão: o emissor ativo mais antigo.
payment_id não id de uma cobrança marx, para vincular a nota ao pagamento.
approximate_tax_percent não Percentual aproximado de tributos (Lei 12.741) só desta nota. Padrão: o do serviço ou o do emissor.
export sim, tomador no exterior Dados da exportação: veja Exportação de serviços.
iss_withheld / iss_rate não ISS retido pelo tomador: veja ISS retido.
ibs_cbs não Grupo IBS/CBS só desta nota (padrão: serviço → emissor).

Resposta 202:

JSON
{
  "object": "nfse",
  "id": "8f1c2a7e-4b1d-4f43-9b2f-5e8d9a4b1c22",
  "status": "queued",
  "environment": "test",
  "reference": "fatura-2026-10-0042",
  "issuer": { "id": "…", "cnpj": "11222333000181" },
  "number": null,
  "access_key": null,
  "amount": "149.9",
  "competence_date": "2026-10-01",
  "description": "Assinatura Pro — outubro/2026",
  "service": { "code": "010301", "nbs": "115062100" },
  "customer": { "tax_id": "11222333000181", "country": "BR", "name": "Cliente LTDA", "email": "financeiro@cliente.com.br" },
  "errors": [],
  "cancellation": null,
  "replaces_id": null,
  "replaced_by_id": null,
  "links": {},
  "created_at": "2026-10-06T10:00:00-03:00"
}

Se o emissor ainda não estiver pronto, a resposta é 422 com o que falta: {"error": "…", "missing": ["certificate"]}.

Exportação de serviços

Quando o tomador é do exterior (customer.country diferente de BR), a nota é de exportação: o ISS não incide (tribISSQN = 3), o tax_id é o identificador fiscal estrangeiro (NIF) e o grupo de comércio exterior é obrigatório. Envie export:

JSON
{
  "reference": "consultoria-2026-10",
  "amount": "24480.00",
  "customer": { "tax_id": "98-7654321", "country": "US", "name": "Acme Inc" },
  "service": { "code": "010601", "description": "Consultoria em TI — outubro/2026" },
  "export": { "currency": "USD", "amount_in_currency": "4896.00", "mode": "cross_border" }
}
Campo Obrigatório Descrição
currency sim USD, EUR, GBP ou o código numérico da moeda no Banco Central (3 dígitos).
amount_in_currency sim Valor do serviço na moeda estrangeira. amount continua em reais.
mode não cross_border (remoto, padrão), consumption_in_brazil, commercial_presence_abroad, temporary_movement_of_people.
relationship não Vínculo com o tomador: none (padrão), controlled, controlling, affiliate, head_office, branch, other.
provider_support / customer_support não Mecanismo de apoio ao comércio exterior, código da tabela nacional. Padrão 01 (nenhum).
temporary_goods não no (padrão), import_declaration, export_declaration.
share_with_mdic não true para compartilhar a nota com a Secretaria de Comércio Exterior. Padrão false.

Nota

Exportação só vale quando o resultado do serviço acontece no exterior. Se parte do serviço é consumida no Brasil, emita notas separadas. Exportações não podem ter ISS retido. Confirme o enquadramento com o seu contador.

ISS retido pelo tomador

Quando o seu cliente retém o ISS (tpRetISSQN = 2), envie "iss_withheld": true. A alíquota vem de iss_rate na nota, ou da alíquota do serviço, ou de iss_withholding_rate do emissor (até 5%).

A API recusa (422) antes de enviar quando a regra nacional não permite:

Regra Código
Tomador sem CPF/CNPJ E0204
Tomador sem endereço no Brasil (customer.address) E0237
Alíquota acima de 5% E0595
Emissor MEI ou com regime especial de tributação E0583 / E0588
Exportação E0580

Atenção

A retenção também depende das regras do município do tomador. Se o município não prevê retenção para o seu caso, o Ambiente Nacional recusa a nota.

IBS e CBS (Reforma Tributária)

A partir de 01/01/2027, toda NFS-e precisa do grupo IBS/CBS, inclusive de empresas do Simples Nacional. Em 2026 ele é opcional para o Simples. Configure os códigos no emissor (ibs_cbs), em cada serviço ou em uma nota específica:

Campo Descrição
cst Código de Situação Tributária do IBS e da CBS (3 dígitos).
class_code Código de Classificação Tributária, cClassTrib (6 dígitos).
operation_indicator Indicador da operação, cIndOp (6 dígitos). Para serviços em geral, pagos, prestados a clientes no Brasil: 100301.
  • Configurado, o grupo vai em toda nota. Sem configuração ele é omitido até 31/12/2026.
  • A partir de 2027, a API recusa a nota e o emissor aparece com missing: ["ibs_cbs"] enquanto faltar.
  • Os valores de IBS e CBS do Simples são calculados pelo Ambiente Nacional; você informa só os códigos.

Importante

CST e cClassTrib dependem do seu regime e do serviço. Defina-os com o seu contador e teste no ambiente de teste antes de 2027.

Status da nota

status O que significa O que fazer
queued Recebida, na fila de emissão. Aguardar o webhook.
processing Enviada ao Ambiente Nacional. Instabilidades são repetidas automaticamente, sem risco de nota duplicada. Aguardar.
authorized Nota emitida: number, access_key, PDF e XML disponíveis. Entregar ao cliente.
rejected Recusada pelo Ambiente Nacional. Os códigos e mensagens estão em errors. Corrigir os dados e pedir uma nova nota, com outro reference.
cancelled Cancelamento registrado. —
replaced Substituída por outra nota (replaced_by_id). Use a nota nova.
needs_data Nota automática de um pagamento sem CPF/CNPJ completo do pagador. Fale com o time marx ou envie os dados do cliente na cobrança (veja abaixo).

Consultar, listar e baixar

Endpoint O que faz
GET /api/nfse/{id} A nota, no formato acima.
GET /api/nfse Lista, da mais recente para a mais antiga. Filtros: status, issuer_id, reference, payment_id, competence_from, competence_to (AAAA-MM-DD). Paginação: page e per_page (até 100).
GET /api/nfse/{id}/pdf PDF (DANFSe) da nota autorizada. Notas canceladas ou substituídas saem com marca d'água.
GET /api/nfse/{id}/xml XML oficial da nota autorizada.

Antes da autorização, PDF e XML respondem 404.

Cancelar

POST /api/nfse/{id}/cancel

Shell
curl -X POST https://marx.loco.ltd/api/nfse/8f1c2a7e-4b1d-4f43-9b2f-5e8d9a4b1c22/cancel \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "service_not_provided" }'
Campo Descrição
reason error (erro na emissão), service_not_provided (serviço não prestado) ou other (padrão).
description Opcional, de 15 a 255 caracteres. Sem ela, usamos um texto padrão para o motivo.

Responde 202 com cancellation.status = "pending"; quando o cancelamento é registrado, a nota fica cancelled e chega o webhook event_type_nfse_cancelled. Só notas authorized podem ser canceladas.

Atenção

Cada município define o prazo de cancelamento (em Curitiba, 60 dias e antes do pagamento do imposto). Fora do prazo, ou acima de certos valores, o pedido vira análise fiscal na prefeitura e pode ser recusado. Para dados errados numa nota válida, prefira substituir.

Substituir

POST /api/nfse/{id}/replace

Cria uma nota nova que substitui a original. Envie um reference novo e só os campos que mudam; os demais são copiados da original.

Shell
curl -X POST https://marx.loco.ltd/api/nfse/8f1c2a7e-4b1d-4f43-9b2f-5e8d9a4b1c22/replace \
  -H "X-Client-Id: $MARX_CLIENT_ID" -H "X-Client-Secret: $MARX_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "reference": "fatura-2026-10-0042-v2", "service": { "description": "Assinatura Pro — outubro/2026 (contrato 123)" } }'

Importante

ME/EPP do Simples: a nota substituta não pode mudar o valor, a data de competência nem o CPF/CNPJ do tomador (regra nacional, código E0063). A API recusa esses pedidos com 422 e o campo locked. Para corrigir esses dados, cancele a nota e emita outra. Use a substituição para corrigir descrição, endereço, serviço e outros dados.

reason é opcional: other (padrão), rejected_by_customer, simples_exclusion, simples_inclusion, immunity_added ou immunity_removed. A resposta (202) é a nota nova, com replaces_id. Quando ela for autorizada, a original passa a replaced.

Emissão automática no pagamento

Com auto_issue_on_payment: true no emissor, a marx emite uma nota para cada cobrança paga (uma por pagamento, nunca duas). Para a nota sair completa, envie os dados do tomador e, se quiser, o serviço e a descrição no metadata da cobrança:

JSON
{
  "metadata": {
    "nfse": {
      "customer": { "cnpj": "11222333000181", "name": "Cliente LTDA", "email": "financeiro@cliente.com.br" },
      "service_code": "010301",
      "description": "Assinatura Pro — outubro/2026"
    }
  }
}

Sem esses dados, usamos o pagador informado pela rede Pix quando ele vem completo; caso contrário a nota fica em needs_data. Devoluções não cancelam a nota automaticamente.

Webhooks

As notas usam o mesmo envio, assinatura e novas tentativas dos webhooks de pagamento. O payload é a nota (mesmo formato de GET /api/nfse/{id}).

event Quando
event_type_nfse_authorized Nota autorizada.
event_type_nfse_rejected Nota recusada (errors traz os códigos).
event_type_nfse_cancelled Cancelamento registrado.
event_type_nfse_replaced A nota foi substituída: enviado para a nota original quando a substituta é autorizada.
event_type_nfse_cancellation_rejected O Ambiente Nacional recusou o cancelamento (prazo, análise fiscal…). cancellation.status = "rejected" e a nota segue autorizada.
event_type_nfse_needs_data Nota automática de um pagamento aguardando o CPF/CNPJ do tomador.

Erros comuns na emissão

Os códigos vêm do Ambiente Nacional, em errors[].code:

Código Causa provável
E0116 / E0120 Inscrição municipal faltando, diferente do cadastro, ou enviada a um município que não a usa. Use o valor do campo Indicador Municipal do Emissor Nacional (Emissão completa → Emitente), que pode ser diferente do número do cartão da prefeitura.
E0312 O código de serviço não é administrado pelo seu município.
E0602 / E0617 Alíquota ou dados do Simples diferentes do cadastro municipal.
E0712 ME/EPP sem percentual aproximado de tributos: configure approximate_tax_percent no emissor ou no serviço.
E0063 Substituição de nota de ME/EPP alterando valor, competência ou tomador. Cancele e emita outra.
E0330 / E0333 Exportação sem o grupo de comércio exterior, ou com valor "desconhecido". Envie export.
E0204 / E0237 / E0595 / E0580 ISS retido sem documento ou endereço do tomador, alíquota acima de 5%, ou em exportação.
MARX Recusada pela própria marx antes do envio, porque os dados não montam uma nota válida (a mensagem diz o que falta).
E0714 a E0718 Certificado de outro CNPJ ou assinatura inválida. Envie o A1 do próprio emissor.
E0038 / E0039 Empresa não habilitada no Emissor Nacional para o município. Faça o primeiro acesso no portal do Emissor Nacional.

Como os campos viram a nota

Campo da API Campo da DPS (Padrão Nacional)
emissor cnpj, municipal_registration prest/CNPJ, prest/IM
tax_regime / simples_collection / special_regime regTrib/opSimpNac / regApTribSN / regEspTrib
city_ibge cLocEmi, locPrest/cLocPrestacao
series + numeração da marx serie, nDPS, Id da DPS
customer.tax_id toma/CNPJ, toma/CPF ou toma/NIF (exterior)
service.code, nbs, municipal_code cServ/cTribNac, cNBS, cTribMun
service.description cServ/xDescServ
amount vServPrest/vServ
competence_date dCompet
approximate_tax_percent (nota → serviço → emissor) totTrib/pTotTribSN
export serv/comExt (mdPrestacao, vincPrest, tpMoeda, vServMoeda, mecAFComexP, mecAFComexT, movTempBens, mdic)
iss_withheld + alíquota tribMun/tpRetISSQN = 2 + pAliq
ibs_cbs IBSCBS (finNFSe = 0, cIndOp, indDest = 0, gIBSCBS/CST, cClassTrib)
description_footer do emissor somado ao fim de cServ/xDescServ
cancel reason evento de cancelamento cMotivo (error 1, service_not_provided 2, other 9)
replace subst/chSubstda, cMotivo

Checklist antes de produção

  • [ ] Regime, códigos de serviço, NBS e texto da descrição confirmados com o contador.
  • [ ] Inscrição municipal idêntica ao Indicador Municipal do Emissor Nacional (confira também no ambiente de produção).
  • [ ] Percentual aproximado de tributos configurado (obrigatório para ME/EPP).
  • [ ] Códigos de IBS/CBS configurados e testados antes de 01/01/2027.
  • [ ] Exportação: notas de teste com export emitidas, se você tem clientes no exterior.
  • [ ] Série exclusiva da marx (diferente da usada no portal).
  • [ ] Notas de teste emitidas, consultadas, canceladas e substituídas com sucesso.
  • [ ] Webhooks event_type_nfse_* tratados e assinatura validada.
  • [ ] reference único em todo pedido de nota.
  • [ ] Lembrete para renovar o certificado A1 antes do vencimento.
  • [ ] Pedido ao time marx para mudar o emissor para produção.

Dúvidas sobre a integração? Fale com o time marx pelo seu canal de suporte.

© 2026 marx