# Empresas

Cadastro, consulta de empresas emissoras e configuração NFS-e.

Use `POST /companies` para criar uma empresa (somente chave de workspace). Use `GET /companies` para listar empresas do escopo da chave. Use `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara. Use `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).

**Campos extras (`meta_fields`) — campos personalizados por empresa:**

Campos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`. Eles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.

**Exemplo prático:** Um ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook. O administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`). Ao cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa. Quando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP. Campos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive. Uma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.

**Fluxo de uso via API:**

1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).
2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.
3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace).

## Listar empresas

> Lista as empresas visíveis no contexto autenticado.\
> \
> Regras:\
> \- A chave de workspace lista as empresas do próprio workspace.\
> \- A chave de empresa recebe apenas a empresa vinculada à própria integração.\
> \- O parâmetro \`fields\` pode restringir a resposta a um subconjunto dos campos documentados no schema.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"CompanyListResponse":{"type":"object","additionalProperties":false,"required":["items","paginate"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CompanyResponse"}},"paginate":{"$ref":"#/components/schemas/CursorPaginateMeta"}}},"CompanyResponse":{"type":"object","additionalProperties":false,"required":["id","workspace_id","name","legal_name","tax_id","email","active"],"properties":{"id":{"$ref":"#/components/schemas/ObjectId"},"workspace_id":{"$ref":"#/components/schemas/ObjectId"},"name":{"type":"string"},"legal_name":{"type":"string"},"tax_id":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"municipal_registration":{"type":["string","null"]},"simple_national":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Enquadramento canônico da empresa no Simples Nacional usado pela emissão NFS-e. Providers ABRASF traduzem este campo para `OptanteSimplesNacional`; não confundir com `simple_national_apportionment`.\n- `1` — Não optante pelo Simples Nacional.\n- `2` — MEI optante pelo Simples Nacional.\n- `3` — ME/EPP optante pelo Simples Nacional."},"simple_national_apportionment":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Regime de apuração do Simples Nacional usado por layouts que serializam `regApTribSN`. Não substitui `simple_national` e não define `OptanteSimplesNacional`.\n- `1` — Tributos federais e municipal pelo Simples Nacional.\n- `2` — Tributos federais pelo Simples Nacional e ISSQN pela NFS-e municipal.\n- `3` — Tributos federais e municipal fora do Simples Nacional."},"special_tax_regime":{"type":["integer","null"],"enum":[null,0,1,2,3,4,5,6,9],"description":"Regime especial de tributação canônico usado pela emissão NFS-e quando o layout do provider exigir."},"tax_incentive":{"type":["integer","null"],"enum":[null,1,2],"description":"Indicador canônico de incentivo fiscal municipal: `1` para sim e `2` para não."},"certificate_id":{"type":["string","null"],"description":"Certificado digital fiscal da empresa. Para NFS-e, este é o vínculo ativo usado por provedores que exigem mTLS e/ou assinatura XML."},"address":{"$ref":"#/components/schemas/CompanyAddress"},"meta_fields":{"$ref":"#/components/schemas/CompanyMetaFields"},"is_headquarters":{"type":"boolean"},"nfse_config":{"type":"object","oneOf":[{"$ref":"#/components/schemas/CompanyNfseConfigResponse"},{"type":"null"}]},"active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"CompanyAddress":{"type":"object","additionalProperties":false,"required":["city","municipality_code","neighborhood","number","postal_code","state","street"],"properties":{"city":{"type":"string","description":"Cidade/localidade textual do endereço. Campo canônico de empresa."},"municipality":{"type":"string","description":"**Compatibilidade.** (Compatibility) Alias permanente de `city` aceito na borda pública e retornado nas respostas para integrações legadas."},"complement":{"type":["string","null"]},"country":{"type":"string"},"country_code":{"type":"string"},"municipality_code":{"type":"string","minLength":7,"maxLength":7},"neighborhood":{"type":"string"},"number":{"type":"string"},"postal_code":{"type":"string"},"state":{"type":"string","maxLength":2},"street":{"type":"string"}}},"CompanyMetaFields":{"type":"object","description":"Valores dos campos extras dinâmicos configurados no workspace para a empresa.\n\nRegras:\n- chave: texto não vazio (até 128 caracteres).\n- valor: texto não vazio (1 a 2048 caracteres).\n- Campos sensíveis são retornados mascarados (`********`) nas rotas de leitura.\n- Envio por webhook depende da definição do campo em `meta_fields.send_webhook`.","additionalProperties":{"type":"string","minLength":1,"maxLength":2048}},"CompanyNfseConfigResponse":{"oneOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfigResponse"},{"$ref":"#/components/schemas/CompanyNationalNfseConfigResponse"}]},"CompanyMunicipalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyMunicipalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração municipal de NFS-e devolvida pela API, incluindo campos derivados e metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","profile_id","provider","environment","numbering"],"properties":{"integration":{"type":"string","enum":["municipal"]},"profile_id":{"type":"string"},"provider":{"type":"string","readOnly":true,"description":"Provedor municipal derivado automaticamente do perfil municipal escolhido."},"municipal_registration":{"type":["string","null"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"danfse_generation_mode":{"type":"string","enum":["automatic","custom"]},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"NfseCompanyNumbering":{"type":"object","additionalProperties":false,"required":["number","series"],"properties":{"number":{"type":"integer","minimum":1},"series":{"type":"string"}}},"CompanyNfseRuntimeMetadata":{"type":"object","required":["docs_version"],"description":"Metadados de runtime devolvidos ao consumir a configuração NFS-e da empresa.\nA validação estrutural do envelope acontece no momento da emissão (Zod estático no schema canônico);\ncampos fiscais variáveis dependem do template anotado e de rejeição oficial do provedor — não há\nmapa dinâmico de campos.","properties":{"docs_version":{"type":["string","null"],"description":"Versão do conjunto de artefatos oficiais associado ao profile resolvido."},"setup_spec":{"oneOf":[{"$ref":"#/components/schemas/NfseProviderSetupSpec"},{"type":"null"}],"description":"Especificação dinâmica do provider usada pelo front para montar campos de empresa, certificado e credenciais."}}},"NfseProviderSetupSpec":{"type":"object","description":"Especificação declarativa do provider usada para montar a configuração da empresa.\n\nCampos relevantes para a configuração NFS-e:\n- `certificate.required`: define se a empresa precisa selecionar certificado.\n- `authorization`: declara os tipos de autorização técnica aceitos pelo provider.\n- `profile_settings`: declara campos dinâmicos do perfil municipal/provedor.\n- `company_settings`: declara os campos dinâmicos top-level aceitos na configuração da empresa.\n- `profile_settings[].template.visible` e `company_settings[].template.visible`: quando `true`, expõem o campo no editor de templates como `provider_settings.<key>` ou como o `template.path` literal declarado pelo provider.\n- `numbering.series_format`: indica se a série fiscal usa formato `numeric` ou `alphanumeric`.","additionalProperties":true,"properties":{"certificate":{"type":"object","additionalProperties":true},"profile_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"company_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"authorization":{"type":"object","additionalProperties":true,"description":"Tipos de autorização técnica aceitos pelo provider. Quando houver um único tipo, a API pode inferir o `type` no payload da empresa."},"numbering":{"type":"object","additionalProperties":false,"properties":{"series_format":{"type":"string","enum":["numeric","alphanumeric"],"description":"Formato canônico da série fiscal usada em `numbering[].series`."}}}}},"NfseProviderSetupField":{"type":"object","additionalProperties":true,"required":["key","type","required"],"properties":{"key":{"type":"string","description":"Chave declarada pelo provider. Quando exposta em template, vira `provider_settings.<key>`."},"type":{"type":"string","enum":["boolean","number","password","radio","select","text","url"]},"required":{"type":"boolean"},"sensitive":{"type":"boolean"},"template":{"type":"object","additionalProperties":false,"description":"Metadado de UI para campos já existentes no contrato do provider. Não cria campo fiscal novo.","properties":{"visible":{"type":"boolean","description":"Quando `true`, permite selecionar `provider_settings.<key>` no editor de templates."},"path":{"type":"string","description":"Path literal usado no template físico quando o contexto do provider não usa `provider_settings.<key>`."},"description":{"type":"string","description":"Descrição opcional exibida no seletor de campos do editor de templates."}}}}},"CompanyNationalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyNationalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyNationalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração de NFS-e Nacional devolvida pela API, incluindo metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","environment","numbering"],"properties":{"integration":{"type":"string","enum":["national"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"include_municipal_registration":{"type":"boolean"},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"CursorPaginateMeta":{"type":"object","additionalProperties":false,"required":["limit","has_next_page","has_previous_page","start_cursor","end_cursor"],"properties":{"limit":{"type":"integer","minimum":10,"maximum":100},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"start_cursor":{"type":["string","null"]},"end_cursor":{"type":["string","null"]}}},"ValidationErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"}],"description":"Erro de validação (Zod ou validador de domínio). No `POST /nfse`, `error.code` é `NFSE_VALIDATION_FAILED`; `error.details[]` carrega cada campo inválido com códigos catalogados ou `VALIDATION_*` e `params.field`."},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/companies":{"get":{"operationId":"listCompanies","tags":["Empresas"],"summary":"Listar empresas","description":"Lista as empresas visíveis no contexto autenticado.\n\nRegras:\n- A chave de workspace lista as empresas do próprio workspace.\n- A chave de empresa recebe apenas a empresa vinculada à própria integração.\n- O parâmetro `fields` pode restringir a resposta a um subconjunto dos campos documentados no schema.","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"},{"name":"q","in":"query","required":false,"description":"Busca textual por nome, razão social ou CNPJ.","schema":{"type":"string"}},{"name":"city","in":"query","required":false,"description":"Filtro por cidade/localidade textual do endereço cadastrado.","schema":{"type":"string"}},{"name":"municipality","in":"query","required":false,"description":"**Compatibilidade.** (Compatibility) Alias legado de `city` para filtro por endereço de empresa.","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"description":"Filtro por UF do endereço cadastrado.","schema":{"type":"string","minLength":2,"maxLength":2}},{"name":"municipality_code","in":"query","required":false,"description":"Filtro por código IBGE do município da empresa.","schema":{"type":"string","minLength":7,"maxLength":7}},{"name":"integration","in":"query","required":false,"description":"Filtro pela integração NFS-e configurada para a empresa.","schema":{"type":"string"}},{"name":"active","in":"query","required":false,"description":"Filtro por empresas ativas (`true`) ou inativas (`false`).","schema":{"type":"boolean"}},{"name":"cursor","in":"query","required":false,"description":"Cursor opaco de paginação.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Quantidade de itens por página (10 a 100).","schema":{"type":"integer","minimum":10,"maximum":100,"default":10}},{"name":"fields","in":"query","required":false,"description":"Seleção de campos separados por vírgula.","schema":{"type":"string"}}],"responses":{"200":{"description":"Lista de empresas","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListResponse"}}}},"400":{"description":"Erro de validação","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Criar empresa

> Cria uma empresa no workspace da chave autenticada.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Somente chave de \*\*workspace\*\* pode criar empresas.\
> \- Chave de empresa retorna \`403\`.\
> \
> \*\*Campos extras (\`meta\_fields\`):\*\*\
> O workspace pode ter campos extras obrigatórios configurados pelo painel administrativo.\
> Use \`GET /meta-fields\` para descobrir quais campos são obrigatórios antes de enviar o payload.\
> Campos obrigatórios com \`use\_company\_crud: true\` e \`required: true\` devem ser preenchidos em \`meta\_fields\`.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"CompanyCreateRequest":{"type":"object","additionalProperties":false,"required":["name","legal_name","tax_id","email","address"],"properties":{"name":{"type":"string","minLength":2,"maxLength":120},"legal_name":{"type":"string","minLength":2,"maxLength":120},"tax_id":{"type":"string","description":"CNPJ sem máscara (14 dígitos).","pattern":"^\\d{14}$"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"municipal_registration":{"type":["string","null"],"maxLength":60},"simple_national":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Enquadramento canônico da empresa no Simples Nacional usado pela emissão NFS-e. Providers ABRASF traduzem este campo para `OptanteSimplesNacional`; não confundir com `simple_national_apportionment`.\n- `1` — Não optante pelo Simples Nacional.\n- `2` — MEI optante pelo Simples Nacional.\n- `3` — ME/EPP optante pelo Simples Nacional."},"simple_national_apportionment":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Regime de apuração do Simples Nacional usado por layouts que serializam `regApTribSN`. Não substitui `simple_national` e não define `OptanteSimplesNacional`.\n- `1` — Tributos federais e municipal pelo Simples Nacional.\n- `2` — Tributos federais pelo Simples Nacional e ISSQN pela NFS-e municipal.\n- `3` — Tributos federais e municipal fora do Simples Nacional."},"special_tax_regime":{"type":["integer","null"],"enum":[null,0,1,2,3,4,5,6,9],"description":"Regime especial de tributação canônico usado pela emissão NFS-e quando o layout do provider exigir."},"tax_incentive":{"type":["integer","null"],"enum":[null,1,2],"description":"Indicador canônico de incentivo fiscal municipal: `1` para sim e `2` para não."},"address":{"$ref":"#/components/schemas/CompanyAddress"},"is_headquarters":{"type":"boolean","default":false},"active":{"type":"boolean","default":false},"meta_fields":{"$ref":"#/components/schemas/CompanyMetaFields"}}},"CompanyAddress":{"type":"object","additionalProperties":false,"required":["city","municipality_code","neighborhood","number","postal_code","state","street"],"properties":{"city":{"type":"string","description":"Cidade/localidade textual do endereço. Campo canônico de empresa."},"municipality":{"type":"string","description":"**Compatibilidade.** (Compatibility) Alias permanente de `city` aceito na borda pública e retornado nas respostas para integrações legadas."},"complement":{"type":["string","null"]},"country":{"type":"string"},"country_code":{"type":"string"},"municipality_code":{"type":"string","minLength":7,"maxLength":7},"neighborhood":{"type":"string"},"number":{"type":"string"},"postal_code":{"type":"string"},"state":{"type":"string","maxLength":2},"street":{"type":"string"}}},"CompanyMetaFields":{"type":"object","description":"Valores dos campos extras dinâmicos configurados no workspace para a empresa.\n\nRegras:\n- chave: texto não vazio (até 128 caracteres).\n- valor: texto não vazio (1 a 2048 caracteres).\n- Campos sensíveis são retornados mascarados (`********`) nas rotas de leitura.\n- Envio por webhook depende da definição do campo em `meta_fields.send_webhook`.","additionalProperties":{"type":"string","minLength":1,"maxLength":2048}},"CompanyResponse":{"type":"object","additionalProperties":false,"required":["id","workspace_id","name","legal_name","tax_id","email","active"],"properties":{"id":{"$ref":"#/components/schemas/ObjectId"},"workspace_id":{"$ref":"#/components/schemas/ObjectId"},"name":{"type":"string"},"legal_name":{"type":"string"},"tax_id":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"municipal_registration":{"type":["string","null"]},"simple_national":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Enquadramento canônico da empresa no Simples Nacional usado pela emissão NFS-e. Providers ABRASF traduzem este campo para `OptanteSimplesNacional`; não confundir com `simple_national_apportionment`.\n- `1` — Não optante pelo Simples Nacional.\n- `2` — MEI optante pelo Simples Nacional.\n- `3` — ME/EPP optante pelo Simples Nacional."},"simple_national_apportionment":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Regime de apuração do Simples Nacional usado por layouts que serializam `regApTribSN`. Não substitui `simple_national` e não define `OptanteSimplesNacional`.\n- `1` — Tributos federais e municipal pelo Simples Nacional.\n- `2` — Tributos federais pelo Simples Nacional e ISSQN pela NFS-e municipal.\n- `3` — Tributos federais e municipal fora do Simples Nacional."},"special_tax_regime":{"type":["integer","null"],"enum":[null,0,1,2,3,4,5,6,9],"description":"Regime especial de tributação canônico usado pela emissão NFS-e quando o layout do provider exigir."},"tax_incentive":{"type":["integer","null"],"enum":[null,1,2],"description":"Indicador canônico de incentivo fiscal municipal: `1` para sim e `2` para não."},"certificate_id":{"type":["string","null"],"description":"Certificado digital fiscal da empresa. Para NFS-e, este é o vínculo ativo usado por provedores que exigem mTLS e/ou assinatura XML."},"address":{"$ref":"#/components/schemas/CompanyAddress"},"meta_fields":{"$ref":"#/components/schemas/CompanyMetaFields"},"is_headquarters":{"type":"boolean"},"nfse_config":{"type":"object","oneOf":[{"$ref":"#/components/schemas/CompanyNfseConfigResponse"},{"type":"null"}]},"active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"CompanyNfseConfigResponse":{"oneOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfigResponse"},{"$ref":"#/components/schemas/CompanyNationalNfseConfigResponse"}]},"CompanyMunicipalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyMunicipalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração municipal de NFS-e devolvida pela API, incluindo campos derivados e metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","profile_id","provider","environment","numbering"],"properties":{"integration":{"type":"string","enum":["municipal"]},"profile_id":{"type":"string"},"provider":{"type":"string","readOnly":true,"description":"Provedor municipal derivado automaticamente do perfil municipal escolhido."},"municipal_registration":{"type":["string","null"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"danfse_generation_mode":{"type":"string","enum":["automatic","custom"]},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"NfseCompanyNumbering":{"type":"object","additionalProperties":false,"required":["number","series"],"properties":{"number":{"type":"integer","minimum":1},"series":{"type":"string"}}},"CompanyNfseRuntimeMetadata":{"type":"object","required":["docs_version"],"description":"Metadados de runtime devolvidos ao consumir a configuração NFS-e da empresa.\nA validação estrutural do envelope acontece no momento da emissão (Zod estático no schema canônico);\ncampos fiscais variáveis dependem do template anotado e de rejeição oficial do provedor — não há\nmapa dinâmico de campos.","properties":{"docs_version":{"type":["string","null"],"description":"Versão do conjunto de artefatos oficiais associado ao profile resolvido."},"setup_spec":{"oneOf":[{"$ref":"#/components/schemas/NfseProviderSetupSpec"},{"type":"null"}],"description":"Especificação dinâmica do provider usada pelo front para montar campos de empresa, certificado e credenciais."}}},"NfseProviderSetupSpec":{"type":"object","description":"Especificação declarativa do provider usada para montar a configuração da empresa.\n\nCampos relevantes para a configuração NFS-e:\n- `certificate.required`: define se a empresa precisa selecionar certificado.\n- `authorization`: declara os tipos de autorização técnica aceitos pelo provider.\n- `profile_settings`: declara campos dinâmicos do perfil municipal/provedor.\n- `company_settings`: declara os campos dinâmicos top-level aceitos na configuração da empresa.\n- `profile_settings[].template.visible` e `company_settings[].template.visible`: quando `true`, expõem o campo no editor de templates como `provider_settings.<key>` ou como o `template.path` literal declarado pelo provider.\n- `numbering.series_format`: indica se a série fiscal usa formato `numeric` ou `alphanumeric`.","additionalProperties":true,"properties":{"certificate":{"type":"object","additionalProperties":true},"profile_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"company_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"authorization":{"type":"object","additionalProperties":true,"description":"Tipos de autorização técnica aceitos pelo provider. Quando houver um único tipo, a API pode inferir o `type` no payload da empresa."},"numbering":{"type":"object","additionalProperties":false,"properties":{"series_format":{"type":"string","enum":["numeric","alphanumeric"],"description":"Formato canônico da série fiscal usada em `numbering[].series`."}}}}},"NfseProviderSetupField":{"type":"object","additionalProperties":true,"required":["key","type","required"],"properties":{"key":{"type":"string","description":"Chave declarada pelo provider. Quando exposta em template, vira `provider_settings.<key>`."},"type":{"type":"string","enum":["boolean","number","password","radio","select","text","url"]},"required":{"type":"boolean"},"sensitive":{"type":"boolean"},"template":{"type":"object","additionalProperties":false,"description":"Metadado de UI para campos já existentes no contrato do provider. Não cria campo fiscal novo.","properties":{"visible":{"type":"boolean","description":"Quando `true`, permite selecionar `provider_settings.<key>` no editor de templates."},"path":{"type":"string","description":"Path literal usado no template físico quando o contexto do provider não usa `provider_settings.<key>`."},"description":{"type":"string","description":"Descrição opcional exibida no seletor de campos do editor de templates."}}}}},"CompanyNationalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyNationalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyNationalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração de NFS-e Nacional devolvida pela API, incluindo metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","environment","numbering"],"properties":{"integration":{"type":"string","enum":["national"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"include_municipal_registration":{"type":"boolean"},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"ValidationErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"}],"description":"Erro de validação (Zod ou validador de domínio). No `POST /nfse`, `error.code` é `NFSE_VALIDATION_FAILED`; `error.details[]` carrega cada campo inválido com códigos catalogados ou `VALIDATION_*` e `params.field`."},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/companies":{"post":{"operationId":"createCompany","tags":["Empresas"],"summary":"Criar empresa","description":"Cria uma empresa no workspace da chave autenticada.\n\nRegras de escopo com `x-api-key`:\n- Somente chave de **workspace** pode criar empresas.\n- Chave de empresa retorna `403`.\n\n**Campos extras (`meta_fields`):**\nO workspace pode ter campos extras obrigatórios configurados pelo painel administrativo.\nUse `GET /meta-fields` para descobrir quais campos são obrigatórios antes de enviar o payload.\nCampos obrigatórios com `use_company_crud: true` e `required: true` devem ser preenchidos em `meta_fields`.","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyCreateRequest"}}}},"responses":{"201":{"description":"Empresa criada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyResponse"}}}},"400":{"description":"Erro de validação","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Consultar empresa por referência

> Retorna os dados completos da empresa resolvida por \`\_id\` ou CNPJ sem máscara.\
> \
> Regras:\
> \- aceita \`ObjectId\` válido;\
> \- aceita CNPJ puro com 14 dígitos;\
> \- rejeita CPF;\
> \- rejeita CNPJ mascarado;\
> \- rejeita espaços em branco na referência;\
> \- chave de empresa retorna \`403\` quando a referência aponta para outra empresa do mesmo workspace.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"CompanyReference":{"name":"company_reference","in":"path","required":true,"description":"ObjectId da empresa ou CNPJ sem máscara com 14 dígitos. CPF, máscara e espaços não são aceitos.","schema":{"type":"string"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"CompanyResponse":{"type":"object","additionalProperties":false,"required":["id","workspace_id","name","legal_name","tax_id","email","active"],"properties":{"id":{"$ref":"#/components/schemas/ObjectId"},"workspace_id":{"$ref":"#/components/schemas/ObjectId"},"name":{"type":"string"},"legal_name":{"type":"string"},"tax_id":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"municipal_registration":{"type":["string","null"]},"simple_national":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Enquadramento canônico da empresa no Simples Nacional usado pela emissão NFS-e. Providers ABRASF traduzem este campo para `OptanteSimplesNacional`; não confundir com `simple_national_apportionment`.\n- `1` — Não optante pelo Simples Nacional.\n- `2` — MEI optante pelo Simples Nacional.\n- `3` — ME/EPP optante pelo Simples Nacional."},"simple_national_apportionment":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Regime de apuração do Simples Nacional usado por layouts que serializam `regApTribSN`. Não substitui `simple_national` e não define `OptanteSimplesNacional`.\n- `1` — Tributos federais e municipal pelo Simples Nacional.\n- `2` — Tributos federais pelo Simples Nacional e ISSQN pela NFS-e municipal.\n- `3` — Tributos federais e municipal fora do Simples Nacional."},"special_tax_regime":{"type":["integer","null"],"enum":[null,0,1,2,3,4,5,6,9],"description":"Regime especial de tributação canônico usado pela emissão NFS-e quando o layout do provider exigir."},"tax_incentive":{"type":["integer","null"],"enum":[null,1,2],"description":"Indicador canônico de incentivo fiscal municipal: `1` para sim e `2` para não."},"certificate_id":{"type":["string","null"],"description":"Certificado digital fiscal da empresa. Para NFS-e, este é o vínculo ativo usado por provedores que exigem mTLS e/ou assinatura XML."},"address":{"$ref":"#/components/schemas/CompanyAddress"},"meta_fields":{"$ref":"#/components/schemas/CompanyMetaFields"},"is_headquarters":{"type":"boolean"},"nfse_config":{"type":"object","oneOf":[{"$ref":"#/components/schemas/CompanyNfseConfigResponse"},{"type":"null"}]},"active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"CompanyAddress":{"type":"object","additionalProperties":false,"required":["city","municipality_code","neighborhood","number","postal_code","state","street"],"properties":{"city":{"type":"string","description":"Cidade/localidade textual do endereço. Campo canônico de empresa."},"municipality":{"type":"string","description":"**Compatibilidade.** (Compatibility) Alias permanente de `city` aceito na borda pública e retornado nas respostas para integrações legadas."},"complement":{"type":["string","null"]},"country":{"type":"string"},"country_code":{"type":"string"},"municipality_code":{"type":"string","minLength":7,"maxLength":7},"neighborhood":{"type":"string"},"number":{"type":"string"},"postal_code":{"type":"string"},"state":{"type":"string","maxLength":2},"street":{"type":"string"}}},"CompanyMetaFields":{"type":"object","description":"Valores dos campos extras dinâmicos configurados no workspace para a empresa.\n\nRegras:\n- chave: texto não vazio (até 128 caracteres).\n- valor: texto não vazio (1 a 2048 caracteres).\n- Campos sensíveis são retornados mascarados (`********`) nas rotas de leitura.\n- Envio por webhook depende da definição do campo em `meta_fields.send_webhook`.","additionalProperties":{"type":"string","minLength":1,"maxLength":2048}},"CompanyNfseConfigResponse":{"oneOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfigResponse"},{"$ref":"#/components/schemas/CompanyNationalNfseConfigResponse"}]},"CompanyMunicipalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyMunicipalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração municipal de NFS-e devolvida pela API, incluindo campos derivados e metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","profile_id","provider","environment","numbering"],"properties":{"integration":{"type":"string","enum":["municipal"]},"profile_id":{"type":"string"},"provider":{"type":"string","readOnly":true,"description":"Provedor municipal derivado automaticamente do perfil municipal escolhido."},"municipal_registration":{"type":["string","null"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"danfse_generation_mode":{"type":"string","enum":["automatic","custom"]},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"NfseCompanyNumbering":{"type":"object","additionalProperties":false,"required":["number","series"],"properties":{"number":{"type":"integer","minimum":1},"series":{"type":"string"}}},"CompanyNfseRuntimeMetadata":{"type":"object","required":["docs_version"],"description":"Metadados de runtime devolvidos ao consumir a configuração NFS-e da empresa.\nA validação estrutural do envelope acontece no momento da emissão (Zod estático no schema canônico);\ncampos fiscais variáveis dependem do template anotado e de rejeição oficial do provedor — não há\nmapa dinâmico de campos.","properties":{"docs_version":{"type":["string","null"],"description":"Versão do conjunto de artefatos oficiais associado ao profile resolvido."},"setup_spec":{"oneOf":[{"$ref":"#/components/schemas/NfseProviderSetupSpec"},{"type":"null"}],"description":"Especificação dinâmica do provider usada pelo front para montar campos de empresa, certificado e credenciais."}}},"NfseProviderSetupSpec":{"type":"object","description":"Especificação declarativa do provider usada para montar a configuração da empresa.\n\nCampos relevantes para a configuração NFS-e:\n- `certificate.required`: define se a empresa precisa selecionar certificado.\n- `authorization`: declara os tipos de autorização técnica aceitos pelo provider.\n- `profile_settings`: declara campos dinâmicos do perfil municipal/provedor.\n- `company_settings`: declara os campos dinâmicos top-level aceitos na configuração da empresa.\n- `profile_settings[].template.visible` e `company_settings[].template.visible`: quando `true`, expõem o campo no editor de templates como `provider_settings.<key>` ou como o `template.path` literal declarado pelo provider.\n- `numbering.series_format`: indica se a série fiscal usa formato `numeric` ou `alphanumeric`.","additionalProperties":true,"properties":{"certificate":{"type":"object","additionalProperties":true},"profile_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"company_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"authorization":{"type":"object","additionalProperties":true,"description":"Tipos de autorização técnica aceitos pelo provider. Quando houver um único tipo, a API pode inferir o `type` no payload da empresa."},"numbering":{"type":"object","additionalProperties":false,"properties":{"series_format":{"type":"string","enum":["numeric","alphanumeric"],"description":"Formato canônico da série fiscal usada em `numbering[].series`."}}}}},"NfseProviderSetupField":{"type":"object","additionalProperties":true,"required":["key","type","required"],"properties":{"key":{"type":"string","description":"Chave declarada pelo provider. Quando exposta em template, vira `provider_settings.<key>`."},"type":{"type":"string","enum":["boolean","number","password","radio","select","text","url"]},"required":{"type":"boolean"},"sensitive":{"type":"boolean"},"template":{"type":"object","additionalProperties":false,"description":"Metadado de UI para campos já existentes no contrato do provider. Não cria campo fiscal novo.","properties":{"visible":{"type":"boolean","description":"Quando `true`, permite selecionar `provider_settings.<key>` no editor de templates."},"path":{"type":"string","description":"Path literal usado no template físico quando o contexto do provider não usa `provider_settings.<key>`."},"description":{"type":"string","description":"Descrição opcional exibida no seletor de campos do editor de templates."}}}}},"CompanyNationalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyNationalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyNationalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração de NFS-e Nacional devolvida pela API, incluindo metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","environment","numbering"],"properties":{"integration":{"type":"string","enum":["national"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"include_municipal_registration":{"type":"boolean"},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/companies/{company_reference}":{"get":{"operationId":"getCompany","tags":["Empresas"],"summary":"Consultar empresa por referência","description":"Retorna os dados completos da empresa resolvida por `_id` ou CNPJ sem máscara.\n\nRegras:\n- aceita `ObjectId` válido;\n- aceita CNPJ puro com 14 dígitos;\n- rejeita CPF;\n- rejeita CNPJ mascarado;\n- rejeita espaços em branco na referência;\n- chave de empresa retorna `403` quando a referência aponta para outra empresa do mesmo workspace.","parameters":[{"$ref":"#/components/parameters/CompanyReference"},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"Empresa encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyResponse"}}}},"400":{"description":"Referência da empresa em formato inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Empresa não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Atualizar empresa por referência

> Atualiza os dados cadastrais da empresa resolvida por \`\_id\` ou CNPJ sem máscara.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode atualizar empresas do próprio workspace por ObjectId ou CNPJ sem máscara.\
> \- Chave de empresa só pode atualizar a própria empresa por ObjectId ou CNPJ sem máscara.\
> \- Chave de empresa retorna \`403\` quando a referência aponta para outra empresa do mesmo workspace.\
> \- Referência de outro workspace retorna \`404\`.\
> \
> \*\*Campos extras (\`meta\_fields\`):\*\*\
> O workspace pode ter campos extras obrigatórios configurados pelo painel administrativo.\
> Use \`GET /meta-fields\` para descobrir quais campos são obrigatórios antes de enviar o payload.\
> Campos obrigatórios com \`use\_company\_crud: true\` e \`required: true\` devem ser preenchidos em \`meta\_fields\`.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"CompanyReference":{"name":"company_reference","in":"path","required":true,"description":"ObjectId da empresa ou CNPJ sem máscara com 14 dígitos. CPF, máscara e espaços não são aceitos.","schema":{"type":"string"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"CompanyCreateRequest":{"type":"object","additionalProperties":false,"required":["name","legal_name","tax_id","email","address"],"properties":{"name":{"type":"string","minLength":2,"maxLength":120},"legal_name":{"type":"string","minLength":2,"maxLength":120},"tax_id":{"type":"string","description":"CNPJ sem máscara (14 dígitos).","pattern":"^\\d{14}$"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"municipal_registration":{"type":["string","null"],"maxLength":60},"simple_national":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Enquadramento canônico da empresa no Simples Nacional usado pela emissão NFS-e. Providers ABRASF traduzem este campo para `OptanteSimplesNacional`; não confundir com `simple_national_apportionment`.\n- `1` — Não optante pelo Simples Nacional.\n- `2` — MEI optante pelo Simples Nacional.\n- `3` — ME/EPP optante pelo Simples Nacional."},"simple_national_apportionment":{"type":["integer","null"],"enum":[null,1,2,3],"description":"Regime de apuração do Simples Nacional usado por layouts que serializam `regApTribSN`. Não substitui `simple_national` e não define `OptanteSimplesNacional`.\n- `1` — Tributos federais e municipal pelo Simples Nacional.\n- `2` — Tributos federais pelo Simples Nacional e ISSQN pela NFS-e municipal.\n- `3` — Tributos federais e municipal fora do Simples Nacional."},"special_tax_regime":{"type":["integer","null"],"enum":[null,0,1,2,3,4,5,6,9],"description":"Regime especial de tributação canônico usado pela emissão NFS-e quando o layout do provider exigir."},"tax_incentive":{"type":["integer","null"],"enum":[null,1,2],"description":"Indicador canônico de incentivo fiscal municipal: `1` para sim e `2` para não."},"address":{"$ref":"#/components/schemas/CompanyAddress"},"is_headquarters":{"type":"boolean","default":false},"active":{"type":"boolean","default":false},"meta_fields":{"$ref":"#/components/schemas/CompanyMetaFields"}}},"CompanyAddress":{"type":"object","additionalProperties":false,"required":["city","municipality_code","neighborhood","number","postal_code","state","street"],"properties":{"city":{"type":"string","description":"Cidade/localidade textual do endereço. Campo canônico de empresa."},"municipality":{"type":"string","description":"**Compatibilidade.** (Compatibility) Alias permanente de `city` aceito na borda pública e retornado nas respostas para integrações legadas."},"complement":{"type":["string","null"]},"country":{"type":"string"},"country_code":{"type":"string"},"municipality_code":{"type":"string","minLength":7,"maxLength":7},"neighborhood":{"type":"string"},"number":{"type":"string"},"postal_code":{"type":"string"},"state":{"type":"string","maxLength":2},"street":{"type":"string"}}},"CompanyMetaFields":{"type":"object","description":"Valores dos campos extras dinâmicos configurados no workspace para a empresa.\n\nRegras:\n- chave: texto não vazio (até 128 caracteres).\n- valor: texto não vazio (1 a 2048 caracteres).\n- Campos sensíveis são retornados mascarados (`********`) nas rotas de leitura.\n- Envio por webhook depende da definição do campo em `meta_fields.send_webhook`.","additionalProperties":{"type":"string","minLength":1,"maxLength":2048}},"ValidationErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"}],"description":"Erro de validação (Zod ou validador de domínio). No `POST /nfse`, `error.code` é `NFSE_VALIDATION_FAILED`; `error.details[]` carrega cada campo inválido com códigos catalogados ou `VALIDATION_*` e `params.field`."},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/companies/{company_reference}":{"put":{"operationId":"updateCompany","tags":["Empresas"],"summary":"Atualizar empresa por referência","description":"Atualiza os dados cadastrais da empresa resolvida por `_id` ou CNPJ sem máscara.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode atualizar empresas do próprio workspace por ObjectId ou CNPJ sem máscara.\n- Chave de empresa só pode atualizar a própria empresa por ObjectId ou CNPJ sem máscara.\n- Chave de empresa retorna `403` quando a referência aponta para outra empresa do mesmo workspace.\n- Referência de outro workspace retorna `404`.\n\n**Campos extras (`meta_fields`):**\nO workspace pode ter campos extras obrigatórios configurados pelo painel administrativo.\nUse `GET /meta-fields` para descobrir quais campos são obrigatórios antes de enviar o payload.\nCampos obrigatórios com `use_company_crud: true` e `required: true` devem ser preenchidos em `meta_fields`.","parameters":[{"$ref":"#/components/parameters/CompanyReference"},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyCreateRequest"}}}},"responses":{"204":{"description":"Empresa atualizada sem corpo de resposta"},"400":{"description":"Payload inválido ou referência da empresa em formato inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Empresa não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Consultar configuração NFS-e da empresa

> Retorna a configuração NFS-e atual da empresa.\
> Quando a NFS-e estiver desativada para a empresa, o retorno será \`null\`.\
> Campos declarados como \`setup\_spec.company\_settings\[\*].sensitive=true\` podem voltar com o valor criptografado persistido (\`enc::v\*::...\`) para preservar o formulário de edição sem expor o segredo em texto puro.\
> \
> O parâmetro \`company\_reference\` aceita ObjectId ou CNPJ sem máscara (14 dígitos).

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"CompanyReference":{"name":"company_reference","in":"path","required":true,"description":"ObjectId da empresa ou CNPJ sem máscara com 14 dígitos. CPF, máscara e espaços não são aceitos.","schema":{"type":"string"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"CompanyNfseConfigResponse":{"oneOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfigResponse"},{"$ref":"#/components/schemas/CompanyNationalNfseConfigResponse"}]},"CompanyMunicipalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyMunicipalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração municipal de NFS-e devolvida pela API, incluindo campos derivados e metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","profile_id","provider","environment","numbering"],"properties":{"integration":{"type":"string","enum":["municipal"]},"profile_id":{"type":"string"},"provider":{"type":"string","readOnly":true,"description":"Provedor municipal derivado automaticamente do perfil municipal escolhido."},"municipal_registration":{"type":["string","null"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"danfse_generation_mode":{"type":"string","enum":["automatic","custom"]},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"NfseCompanyNumbering":{"type":"object","additionalProperties":false,"required":["number","series"],"properties":{"number":{"type":"integer","minimum":1},"series":{"type":"string"}}},"CompanyNfseRuntimeMetadata":{"type":"object","required":["docs_version"],"description":"Metadados de runtime devolvidos ao consumir a configuração NFS-e da empresa.\nA validação estrutural do envelope acontece no momento da emissão (Zod estático no schema canônico);\ncampos fiscais variáveis dependem do template anotado e de rejeição oficial do provedor — não há\nmapa dinâmico de campos.","properties":{"docs_version":{"type":["string","null"],"description":"Versão do conjunto de artefatos oficiais associado ao profile resolvido."},"setup_spec":{"oneOf":[{"$ref":"#/components/schemas/NfseProviderSetupSpec"},{"type":"null"}],"description":"Especificação dinâmica do provider usada pelo front para montar campos de empresa, certificado e credenciais."}}},"NfseProviderSetupSpec":{"type":"object","description":"Especificação declarativa do provider usada para montar a configuração da empresa.\n\nCampos relevantes para a configuração NFS-e:\n- `certificate.required`: define se a empresa precisa selecionar certificado.\n- `authorization`: declara os tipos de autorização técnica aceitos pelo provider.\n- `profile_settings`: declara campos dinâmicos do perfil municipal/provedor.\n- `company_settings`: declara os campos dinâmicos top-level aceitos na configuração da empresa.\n- `profile_settings[].template.visible` e `company_settings[].template.visible`: quando `true`, expõem o campo no editor de templates como `provider_settings.<key>` ou como o `template.path` literal declarado pelo provider.\n- `numbering.series_format`: indica se a série fiscal usa formato `numeric` ou `alphanumeric`.","additionalProperties":true,"properties":{"certificate":{"type":"object","additionalProperties":true},"profile_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"company_settings":{"type":"array","items":{"$ref":"#/components/schemas/NfseProviderSetupField"}},"authorization":{"type":"object","additionalProperties":true,"description":"Tipos de autorização técnica aceitos pelo provider. Quando houver um único tipo, a API pode inferir o `type` no payload da empresa."},"numbering":{"type":"object","additionalProperties":false,"properties":{"series_format":{"type":"string","enum":["numeric","alphanumeric"],"description":"Formato canônico da série fiscal usada em `numbering[].series`."}}}}},"NfseProviderSetupField":{"type":"object","additionalProperties":true,"required":["key","type","required"],"properties":{"key":{"type":"string","description":"Chave declarada pelo provider. Quando exposta em template, vira `provider_settings.<key>`."},"type":{"type":"string","enum":["boolean","number","password","radio","select","text","url"]},"required":{"type":"boolean"},"sensitive":{"type":"boolean"},"template":{"type":"object","additionalProperties":false,"description":"Metadado de UI para campos já existentes no contrato do provider. Não cria campo fiscal novo.","properties":{"visible":{"type":"boolean","description":"Quando `true`, permite selecionar `provider_settings.<key>` no editor de templates."},"path":{"type":"string","description":"Path literal usado no template físico quando o contexto do provider não usa `provider_settings.<key>`."},"description":{"type":"string","description":"Descrição opcional exibida no seletor de campos do editor de templates."}}}}},"CompanyNationalNfseConfigResponse":{"allOf":[{"$ref":"#/components/schemas/CompanyNationalNfseConfig"},{"$ref":"#/components/schemas/CompanyNfseRuntimeMetadata"}]},"CompanyNationalNfseConfig":{"type":"object","additionalProperties":true,"description":"Configuração de NFS-e Nacional devolvida pela API, incluindo metadados públicos de runtime. Campos `company_settings` sensíveis podem aparecer como ciphertext `enc::v*::...` apenas na rota administrativa de edição.","required":["integration","environment","numbering"],"properties":{"integration":{"type":"string","enum":["national"]},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"]},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa quando o provedor efetivo opera com envio em lote."},"send_template_id":{"type":["string","null"]},"include_municipal_registration":{"type":"boolean"},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/nfse/config/companies/{company_reference}":{"get":{"operationId":"getCompanyNfseConfig","tags":["Empresas"],"summary":"Consultar configuração NFS-e da empresa","description":"Retorna a configuração NFS-e atual da empresa.\nQuando a NFS-e estiver desativada para a empresa, o retorno será `null`.\nCampos declarados como `setup_spec.company_settings[*].sensitive=true` podem voltar com o valor criptografado persistido (`enc::v*::...`) para preservar o formulário de edição sem expor o segredo em texto puro.\n\nO parâmetro `company_reference` aceita ObjectId ou CNPJ sem máscara (14 dígitos).","parameters":[{"$ref":"#/components/parameters/CompanyReference"},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"Configuração encontrada","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CompanyNfseConfigResponse"},{"type":"null"}]}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Empresa não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Configurar empresa para uso de NFS-e

> Define o tipo de integração NFS-e da empresa.\
> \
> O parâmetro \`company\_reference\` aceita ObjectId ou CNPJ sem máscara (14 dígitos).\
> \
> Regras:\
> \- \`integration=national\`: gera DANFSe local no layout NT 008, aceita \`send\_template\_id\` do provedor \`national\` e não usa campos de configuração municipal como \`profile\_id\` nem \`danfse\_generation\_mode\`.\
> \- \`integration=municipal\`: exige \`profile\_id\` apontando para um perfil municipal cadastrado para o código IBGE da empresa.\
> \- A referência fiscal do documento é operacional e não é enviada no payload de emissão.\
> \- Na configuração da empresa, use \`numbering\` para declarar séries e numeração inicial quando a integração exigir.\
> \- Contadores e agrupamentos operacionais são internos; a API pública recebe somente \`numbering\` para séries e próximo número fiscal.\
> \- \`danfse\_generation\_mode\` vale apenas para integração municipal; em \`automatic\`, a API tenta a DANFSe oficial da prefeitura e usa geração local como fallback.\
> \- Campos fiscais variáveis devem ser enviados no top-level do payload, conforme \`setup\_spec.company\_settings\`.\
> \- Campos sensíveis de \`company\_settings\` podem ser reenviados como \`enc::v\*::...\` apenas quando o valor é idêntico ao ciphertext já persistido naquela empresa/campo. Texto novo sem prefixo é cifrado como novo segredo; ciphertext diferente é rejeitado.\
> \- Credenciais técnicas dinâmicas devem ser enviadas em \`authorization\`, conforme o provider. Quando o provider declara um único tipo de autorização, envie apenas os campos externos exigidos; a API infere o \`type\` pelo \`setup\_spec\`.\
> \- Para desativar a NFS-e, use \`DELETE /nfse/config/companies/{company\_reference}\`.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"CompanyReference":{"name":"company_reference","in":"path","required":true,"description":"ObjectId da empresa ou CNPJ sem máscara com 14 dígitos. CPF, máscara e espaços não são aceitos.","schema":{"type":"string"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"CompanyNfseConfigRequest":{"oneOf":[{"$ref":"#/components/schemas/CompanyMunicipalNfseConfigRequest"},{"$ref":"#/components/schemas/CompanyNationalNfseConfigRequest"}]},"CompanyMunicipalNfseConfigRequest":{"type":"object","additionalProperties":true,"description":"Payload de configuração municipal de NFS-e.\nA API aceita campos fixos deste schema e campos top-level declarados em `setup_spec.company_settings` do provider efetivo; metadados de runtime, referências operacionais e aliases de cadastro fiscal continuam rejeitados pela validação semântica.\nCampos `company_settings` sensíveis podem receber texto novo ou o ciphertext `enc::v*::...` idêntico ao valor já persistido na empresa; ciphertext diferente é inválido.","required":["integration","profile_id","environment","numbering"],"properties":{"integration":{"type":"string","enum":["municipal"],"description":"Integração municipal."},"profile_id":{"type":"string","description":"Perfil municipal escolhido pela empresa; é a chave primária da configuração municipal."},"municipal_registration":{"type":["string","null"],"description":"Inscrição Municipal da empresa quando o provider municipal declarar esse campo no setup efetivo."},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"],"description":"Estratégia de seleção automática da série quando o envio não informar `series` na raiz.\n\n- `manual`: usa a série única cadastrada; quando houver múltiplas séries, o envio deve informar `series`.\n- `automatic`: distribui entre as séries cadastradas em rotação (round-robin)."},"danfse_generation_mode":{"type":"string","enum":["automatic","custom"],"description":"Define como a empresa municipal prefere obter a DANFSe.\n\n- `automatic`: tenta usar a DANFSe oficial da prefeitura; quando o provedor não entrega ou retorna conteúdo inválido, usa a DANFSe local do e-docs.\n- `custom`: usa diretamente a geração local de DANFSe do e-docs."},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa. Obrigatório quando o provedor efetivo declara `capabilities.send.max_batch_size > 1`; rejeitado para provedores de envio unitário."},"send_template_id":{"type":["string","null"],"description":"Template de envio customizado da empresa. Pode apontar para rascunho ou publicado do provedor derivado do `profile_id` e da operação `send`; `null` usa o template do perfil, depois o padrão do provedor e, por fim, o XML físico do pacote. Templates arquivados não podem ser vinculados."},"numbering":{"type":"array","minItems":1,"description":"Séries fiscais e próximo número inicial da empresa.","items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"Autorização técnica do provedor, quando aplicável. Quando o provider declara um único tipo de autorização, envie apenas os campos externos exigidos; a API infere o `type` pelo `setup_spec`. Campos de `setup_spec.company_settings` são enviados no top-level."}}},"NfseCompanyNumbering":{"type":"object","additionalProperties":false,"required":["number","series"],"properties":{"number":{"type":"integer","minimum":1},"series":{"type":"string"}}},"CompanyNationalNfseConfigRequest":{"type":"object","description":"Payload de configuração de empresa no Ambiente Nacional.\nA API aceita campos fixos deste schema e campos top-level declarados em `setup_spec.company_settings` do Ambiente Nacional; metadados de runtime e referências operacionais continuam rejeitados pela validação semântica.\n`send_template_id` é permitido quando aponta para template rascunho ou publicado do provedor `national` e da operação `send`.\nO DANFSe Nacional é sempre gerado localmente no layout NT 008.\nCampos `company_settings` sensíveis podem receber texto novo ou o ciphertext `enc::v*::...` idêntico ao valor já persistido na empresa; ciphertext diferente é inválido.","additionalProperties":true,"required":["integration","environment","numbering"],"properties":{"integration":{"type":"string","enum":["national"],"description":"Integração com o Ambiente Nacional."},"environment":{"type":"string","enum":["production","homologation"]},"series_selection_mode":{"type":"string","enum":["manual","automatic"],"description":"Estratégia de seleção automática da série quando o envio não informar `series` na raiz.\n\n- `manual`: usa a série única cadastrada; quando houver múltiplas séries, o envio deve informar `series`.\n- `automatic`: distribui entre as séries cadastradas em rotação (round-robin)."},"numbering":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/NfseCompanyNumbering"}},"batch":{"type":"integer","minimum":1,"description":"Próximo número de lote da empresa. Obrigatório quando o provedor efetivo declara `capabilities.send.max_batch_size > 1`; rejeitado para provedores de envio unitário."},"send_template_id":{"type":["string","null"],"description":"Template de envio customizado da empresa no Ambiente Nacional. Deve pertencer ao provedor `national` e à operação `send`; `null` usa o padrão do provedor e, se não houver, o XML físico do pacote."},"include_municipal_registration":{"type":"boolean","description":"Quando `true`, permite enviar a Inscrição Municipal do cadastro da empresa no layout nacional, se existir."},"authorization":{"oneOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"Autorização técnica do Ambiente Nacional, quando aplicável."}}},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}},"ValidationErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"}],"description":"Erro de validação (Zod ou validador de domínio). No `POST /nfse`, `error.code` é `NFSE_VALIDATION_FAILED`; `error.details[]` carrega cada campo inválido com códigos catalogados ou `VALIDATION_*` e `params.field`."}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/nfse/config/companies/{company_reference}":{"put":{"operationId":"updateCompanyNfseConfig","tags":["Empresas"],"summary":"Configurar empresa para uso de NFS-e","description":"Define o tipo de integração NFS-e da empresa.\n\nO parâmetro `company_reference` aceita ObjectId ou CNPJ sem máscara (14 dígitos).\n\nRegras:\n- `integration=national`: gera DANFSe local no layout NT 008, aceita `send_template_id` do provedor `national` e não usa campos de configuração municipal como `profile_id` nem `danfse_generation_mode`.\n- `integration=municipal`: exige `profile_id` apontando para um perfil municipal cadastrado para o código IBGE da empresa.\n- A referência fiscal do documento é operacional e não é enviada no payload de emissão.\n- Na configuração da empresa, use `numbering` para declarar séries e numeração inicial quando a integração exigir.\n- Contadores e agrupamentos operacionais são internos; a API pública recebe somente `numbering` para séries e próximo número fiscal.\n- `danfse_generation_mode` vale apenas para integração municipal; em `automatic`, a API tenta a DANFSe oficial da prefeitura e usa geração local como fallback.\n- Campos fiscais variáveis devem ser enviados no top-level do payload, conforme `setup_spec.company_settings`.\n- Campos sensíveis de `company_settings` podem ser reenviados como `enc::v*::...` apenas quando o valor é idêntico ao ciphertext já persistido naquela empresa/campo. Texto novo sem prefixo é cifrado como novo segredo; ciphertext diferente é rejeitado.\n- Credenciais técnicas dinâmicas devem ser enviadas em `authorization`, conforme o provider. Quando o provider declara um único tipo de autorização, envie apenas os campos externos exigidos; a API infere o `type` pelo `setup_spec`.\n- Para desativar a NFS-e, use `DELETE /nfse/config/companies/{company_reference}`.","parameters":[{"$ref":"#/components/parameters/CompanyReference"},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyNfseConfigRequest"}}}},"responses":{"204":{"description":"Configuração atualizada (sem corpo)"},"400":{"description":"Erro de validação ou configuração","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ValidationErrorResponse"}]}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Empresa ou perfil do município não encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Remover configuração NFS-e da empresa

> Remove a configuração NFS-e atual da empresa.\
> \
> O parâmetro \`company\_reference\` aceita ObjectId ou CNPJ sem máscara (14 dígitos).\
> A operação é idempotente: empresas sem configuração permanecem sem configuração.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Empresas","description":"Cadastro, consulta de empresas emissoras e configuração NFS-e.\n\nUse `POST /companies` para criar uma empresa (somente chave de workspace).\nUse `GET /companies` para listar empresas do escopo da chave.\nUse `GET /companies/{company_reference}` para consultar uma empresa por ObjectId ou CNPJ sem máscara.\nUse `PUT /nfse/config/companies/{company_reference}` para ativar/configurar a emissão de NFS-e (aceita ObjectId ou CNPJ).\n\n**Campos extras (`meta_fields`) — campos personalizados por empresa:**\n\nCampos extras permitem que o workspace defina campos que cada empresa pode preencher em `meta_fields`.\nEles só são enviados em webhooks quando a definição estiver com `send_webhook: true`.\n\n**Exemplo prático:**\nUm ERP precisa receber um token de autenticação diferente para cada empresa no header do webhook.\nO administrador do workspace cria um campo extra `token_erp` (obrigatório, criptografado, destino: header, `send_webhook: true`).\nAo cadastrar cada empresa, a integração preenche `meta_fields.token_erp` com o token daquela empresa.\nQuando um webhook é disparado, o eDocs inclui o token automaticamente no header HTTP.\nCampos extras com `target=header` são aplicados por último e sobrescrevem headers internos de forma case-insensitive.\nUma chave `authorization`, por exemplo, substitui `Authorization` sem duplicar o header.\n\n**Fluxo de uso via API:**\n1. `GET /meta-fields` — descubra quais campos o workspace exige (somente chave de workspace).\n2. `POST /companies` — preencha os campos obrigatórios em `meta_fields` ao criar a empresa.\n3. `POST /meta-fields`, `PUT /meta-fields/{meta_field_id}` ou `DELETE /meta-fields/{meta_field_id}` — gerencie a configuração de campos (somente chave de workspace)."}],"servers":[{"url":"https://sandbox.api.edocs.ixcsoft.com.br","description":"Sandbox — simulação interna, aceita certificado self-signed, sem comunicação com a prefeitura."},{"url":"https://api.edocs.ixcsoft.com.br","description":"Produção / Homologação — ambiente real, controlado por `nfse_config.environment`."}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Chave de API enviada no header `x-api-key`.\n\nExistem dois níveis de chave:\n- Workspace: permite emitir NFS-e para várias empresas do mesmo workspace e pode associar webhooks/integrações via `company_id` ou `tax_id`.\n- Empresa: permite emitir NFS-e e gerir certificados apenas para a raiz do CNPJ vinculado e autoassocia webhooks/integrações à própria empresa.\n- Se a integração tiver `allowed_ips`, o acesso só é liberado quando o IP resolvido por `request.ip` estiver dentro da allowlist configurada.\n\nPara gerar a chave de workspace, crie uma integração no painel\n(sem `company_id`) e utilize o `api_key` retornado."}},"parameters":{"CompanyReference":{"name":"company_reference","in":"path","required":true,"description":"ObjectId da empresa ou CNPJ sem máscara com 14 dígitos. CPF, máscara e espaços não são aceitos.","schema":{"type":"string"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"responses":{"UnauthorizedError":{"description":"Não autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Não autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Erro interno inesperado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnderMaintenance":{"description":"Sistema em manutenção programada","headers":{"Retry-After":{"description":"Data e hora prevista para o fim da manutenção no formato HTTP-date (RFC 7231).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","status"],"properties":{"code":{"type":"string","description":"Código machine-readable do erro. Detalhes em `docs/ERRORS.md`."},"message":{"type":"string","description":"Mensagem traduzida conforme Accept-Language."},"status":{"type":"integer","description":"HTTP status code."},"params":{"type":"object","description":"Dados estruturados do erro (campos referenciados, identificadores, contexto técnico). Reflete a interpolação `{{var}}` aplicada ao template da mensagem.","additionalProperties":true},"details":{"type":"array","description":"Lista de falhas estruturadas adicionais (presente quando há múltiplas falhas, ex.: validação Zod, múltiplas empresas inválidas).","items":{"$ref":"#/components/schemas/ErrorDetail"}}}}}},"ErrorDetail":{"type":"object","additionalProperties":false,"required":["code","message"],"properties":{"code":{"type":"string","description":"Código machine-readable do detalhe."},"message":{"type":"string","description":"Mensagem traduzida do detalhe conforme Accept-Language."},"params":{"type":"object","description":"Dados estruturados do detalhe (campo referenciado, identificadores, etc.).","additionalProperties":true}}}}},"paths":{"/nfse/config/companies/{company_reference}":{"delete":{"operationId":"deleteCompanyNfseConfig","tags":["Empresas"],"summary":"Remover configuração NFS-e da empresa","description":"Remove a configuração NFS-e atual da empresa.\n\nO parâmetro `company_reference` aceita ObjectId ou CNPJ sem máscara (14 dígitos).\nA operação é idempotente: empresas sem configuração permanecem sem configuração.","parameters":[{"$ref":"#/components/parameters/CompanyReference"},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"204":{"description":"Configuração removida (sem corpo)"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Empresa não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ixc-soft.gitbook.io/e-docs/empresas.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
