Pular para o conteúdo principal

Receber Nota Fiscal

Descrição: Recebe o XML de uma Nota Fiscal eletrônica (NF-e) e vincula-a a uma negociação existente. A finalidade da NF é classificada automaticamente pela Matriz CFOP a partir do conteúdo do XML e — quando aplicável — alimenta o saldo de caixa logística da negociação.

O endpoint é o ponto de entrada para integradores externos (ERPs, sistemas cooperativos) registrarem NFs eletrônicas no fluxo da Merx. Toda a lógica de parse do XML, classificação CFOP, validações cross-field e impacto em saldo é executada de forma síncrona — a resposta 200 OK confirma o aceite da NF.

Endpoint

POST/api/v1/integration/invoices

Exemplo de Requisição

Exemplo de Requisição
curl -X POST \
-H "Authorization: [[apiKey]]" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
"https://api.merx.tech/api/v1/integration/invoices" \
--data '{
"commitment_id": "17b75d09-bcca-43d1-a656-cb6226b74a83",
"xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><nfeProc>...</nfeProc>",
"external_id": "ERP-NF-000122",
"silo_id": "e168db8c-4fa2-4728-9ec3-945207fa474c"
}'

Parâmetros

Parâmetros de Cabeçalho

NomeDescriçãoTipoObrigatório
AuthorizationToken de autenticaçãoStringSim
Content-Typeapplication/jsonStringSim

Parâmetros do Corpo

NomeDescriçãoTipoObrigatórioValidações
commitment_idIdentificador da negociação na plataforma MerxUUIDSim-
xmlConteúdo do XML da NF-e (string)StringSimNão pode ser vazio
external_idIdentificador externo do integrador. Usado para deduplicação — duas NFs com o mesmo external_id por cooperativa serão rejeitadasStringNão-
silo_idSilo de destino quando a nota movimenta saldo de caixa logísticaUUIDNãoQuando informado, deve pertencer à unidade logística da negociação
id_report_esgID de um relatório ESG pré-gerado para reaproveitar na rastreabilidade automáticaUUIDNãoQuando informado, id_report_eudr também deve ser informado
id_report_eudrID de um relatório EUDR pré-gerado para reaproveitar na rastreabilidade automáticaUUIDNãoQuando informado, id_report_esg também deve ser informado

Importante: a finalidade da NF é classificada automaticamente pela Matriz CFOP a partir do CFOP extraído do XML (e do finNFe, quando aplicável). O integrador não declara a finalidade — basta enviar o XML e o sistema resolve a classificação durante a validação.

Finalidades classificadas pela Matriz CFOP

Cada finalidade cobre um conjunto de CFOPs e tem um impacto específico no saldo da caixa logística da negociação. Esta tabela é informativa — a classificação é feita automaticamente pelo backend.

FinalidadeCFOPs típicosImpacto na caixaDescrição
VENDA_PRODUTOR5101/5102, 6101/6102, 5401/6401SOMANF de venda emitida pelo produtor
CONTRANOTA1101/1102, 2101/2102, 1401/2401, 1403/2403SOMANF de compra emitida pela cooperativa/cerealista após pesagem
COMPLEMENTAR1949/2949, 1101/2101, 1102/2102 (com finNFe=2)SOMA*Ajuste de valor/preço da NF original
DEVOLUCAO5201/5202/5411, 6201/6202/6411SUBTRAIDevolução de mercadoria não conforme
DEVOLUCAO_SIMBOLICA_ARMAZENAGEM1906/2906SUBTRAIReversão simbólica antes da contranota
REMESSA_ARMAZENAGEM5905/6905SOMARemessa real para armazém-geral
RETORNO_ARMAZENAGEM1906/2906SOMAEspelho da REMESSA_ARMAZENAGEM no retorno
TRANSFERENCIA1151/1152/1154, 2151/2152/2154SOMAMovimentação entre filiais da mesma empresa
REMESSA_SIMBOLICA5907/6907NEUTROVenda quando a mercadoria já está no armazém do comprador
RETORNO_SIMBOLICO1907/2907NEUTROEspelho de REMESSA_SIMBOLICA
REMESSA_INDUSTRIALIZACAO5901/6901NEUTROEsmagamento por encomenda — saída sem titularidade
RETORNO_INDUSTRIALIZACAO1902/2902SOMAFarelo/óleo retornando após esmagamento

CFOPs fora do escopo V1:

  • 3xxx (importação)3101, 3102 são rejeitados com message.invoice.cfop.import-not-supported
  • 7xxx (exportação direta)7101, 7102 são rejeitados com message.invoice.cfop.export-not-supported
  • CFOPs não presentes na Matriz são rejeitados com message.invoice.cfop.not-mapped

Respostas

  • 200 - Ok
{
"nf_import_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
NomeDescriçãoTipo
nf_import_idIdentificador único da NF importada na plataforma MerxUUID
  • 400 - Bad Request
{
"messages": [
"message.invoice.commitment-id.mandatory"
]
}

As mensagens retornadas pelo backend são chaves de internacionalização (i18n) — o cliente deve resolvê-las para a string final exibida ao usuário. A interpolação de valores dinâmicos (CFOP, finalidade etc.) é feita no log do servidor e na resolução i18n no cliente, não no body da resposta.

Validações de campos do request (camada de gateway):

CenárioMensagem retornada
commitment_id ausentemessage.invoice-import.commitment-id.mandatory
xml ausente ou vaziomessage.invoice-import.xml.mandatory

Validações de negociação:

CenárioMensagem retornada
commitment_id informado não existemessage.invoice.commitment.not-found
commitment_id não pertence à cooperativa do tokenmessage.invoice.commitment.not-belongs-to-cooperative
Negociação não está em status OPENmessage.invoice.commitment.not-open
Cooperativa não tem o configurador de NF cadastradomessage.invoice.settings.not-configured

Validações de duplicidade:

CenárioMensagem retornada
NF duplicada (mesmo external_id para a mesma cooperativa)message.invoice.duplicate.external-id
NF duplicada (mesmo XML — xml_hash) para a mesma negociaçãomessage.invoice.duplicate.xml-hash
Race condition de persistência (constraint única violada em concorrência)message.invoice.duplicate.persistence
Para BOTH: negociação já tem VENDA_PRODUTOR e veio CONTRANOTAmessage.invoice.both.commitment-has-producer-note
Para BOTH: negociação já tem CONTRANOTA e veio VENDA_PRODUTORmessage.invoice.both.commitment-has-counter-note
COMPLEMENTAR recebida sem NF de entrada prévia para a negociaçãomessage.invoice.complement.no-prior-entry-for-both

Exclusividade do configurador de NF: os modos PRODUCER_NOTE ("Nota do Produtor") e COUNTER_NOTE ("Contranota") são mutuamente exclusivos. Uma cooperativa em modo puro só aceita CFOPs da família correspondente — CFOPs da família oposta são rejeitados antes de qualquer impacto na caixa logística.

CenárioMensagem retornada
Cooperativa em PRODUCER_NOTE recebeu NF classificada como CONTRANOTA (CFOP 1101/1102/1401/1403/2101/2102/2401/2403)message.invoice.contranota.not-allowed-for-producer-note
Cooperativa em COUNTER_NOTE recebeu NF classificada como VENDA_PRODUTOR (CFOP 5101/5102/5401/6101/6102/6401)message.invoice.venda-produtor.not-allowed-for-counter-note

Validações de XML / parse:

CenárioMensagem retornada
XML mal formado / não parseávelmessage.invoice.xml.parse-error
Tag obrigatória ausente no XML (ex.: det/prod/CFOP)message.invoice.xml.missing-required-tag
Quantidade (qCom) ausente ou não numéricamessage.invoice.xml.volume.invalid
Unidade de medida (uCom) não suportada (≠ KG/TON/SC)message.invoice.xml.unit-not-supported

Validações de Matriz CFOP / finalidade:

CenárioMensagem retornada
finNFe=AJUSTE (ajuste fiscal) — não suportado no V1message.invoice.finnfe.ajuste-not-supported
finNFe=DEVOLUCAO ou finNFe=COMPLEMENTAR incompatível com o CFOP do itemmessage.invoice.finnfe.incompatible-with-cfop
CFOP ausente no XMLmessage.invoice.cfop.not-found
CFOP 3xxx (importação direta) — fora do escopo V1message.invoice.cfop.import-not-supported
CFOP 7xxx (exportação direta) — fora do escopo V1message.invoice.cfop.export-not-supported
CFOP não cadastrado na Matriz CFOPmessage.invoice.cfop.not-mapped
CFOP mapeia múltiplas finalidades sem regra de desambiguaçãomessage.invoice.cfop.ambiguous-purposes

Validações específicas de DEVOLUCAO (finalidade 4): NFs de devolução só podem subtrair volume que já foi entregue à negociação (ou ao silo informado).

CenárioMensagem retornada
DEVOLUCAO recebida em negociação sem volume entregue (ou silo sem volume entregue)message.invoice.devolucao.no-delivered-volume
DEVOLUCAO cujo volume excede o volume entregue à negociação (ou ao silo informado)message.invoice.devolucao.exceeds-delivered-volume

Validações de partes (CNPJ/CPF/IE):

CenárioMensagem retornada
Emitente do XML não bate com o produtor (VENDA_PRODUTOR) ou a cooperativa (CONTRANOTA)message.invoice.party.emit-document-mismatch
Destinatário do XML não bate com a cooperativa (VENDA_PRODUTOR) ou o produtor (CONTRANOTA)message.invoice.party.dest-document-mismatch
Rastreabilidade automática habilitada e IE ausente no XMLmessage.invoice.ie.mandatory-when-automatic-traceability
Rastreabilidade automática habilitada e IE do XML não encontrada nas fazendas do produtormessage.invoice.ie.not-found-in-farms

Validações de caixa logística / silo:

CenárioMensagem retornada
Volume da NF excede a capacidade atual da caixa logísticamessage.invoice.logistics-box.capacity-exceeded
silo_id não pertence à unidade logística da negociaçãomessage.invoice.silo.not-belongs-to-logistics-box
Volume da NF excede a capacidade atual do silo informadomessage.invoice.silo.capacity-exceeded

Validações de relatórios pré-gerados (id_report_esg / id_report_eudr):

CenárioMensagem retornada
Apenas um entre id_report_esg e id_report_eudr informado (validação de payload)message.invoice-import.reports.must-provide-both-or-neither
Apenas um entre id_report_esg e id_report_eudr informado (validação de domínio)message.invoice.report.both-required
id_report_esg informado mas relatório ESG não encontrado no Carbonmessage.invoice.report.esg.not-found
id_report_eudr informado mas relatório EUDR não encontrado no Carbonmessage.invoice.report.eudr.not-found
Relatório ESG não corresponde ao CAR da fazenda resolvida pela IEmessage.invoice.report.esg.car-mismatch
Relatório EUDR não corresponde ao CAR da fazenda resolvida pela IEmessage.invoice.report.eudr.car-mismatch
  • 401 - Unauthorized

Token ausente ou inválido.

  • 404 - Not Found
{
"messages": [
"message.invoice.commitment.not-found"
]
}

Negociação informada em commitment_id não encontrada.

  • 500 - Internal Server Error

Erro interno na comunicação com os serviços de domínio.

Observações

  • O endpoint é síncrono: a resposta 200 OK indica que a NF foi recebida, classificada, validada e (quando aplicável) já refletiu impacto em saldo. Não há fluxo de aceite posterior nem polling.
  • Os campos id_report_esg e id_report_eudr são utilizados em conjunto com o fluxo de rastreabilidade automática para reaproveitar relatórios socioambientais e EUDR já gerados anteriormente, evitando reprocessamento. Quando um deles é informado, o outro também precisa ser. Consulte o endpoint de Criar Rastreabilidade para detalhes do fluxo com relatórios pré-gerados.
  • Cada NF aceita gera um registro com status inicial RECEIVED. O nf_import_id retornado pode ser utilizado para correlacionar a NF nos webhooks e relatórios subsequentes.