# Integrações

Cadastro e consulta de chaves `x-api-key`.

Cada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica). Use `allowed_ips` para restringir o acesso por IP/CIDR.

O workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL.

## Listar integrações

> Lista integrações do workspace da chave autenticada com suporte a paginação por cursor.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode listar todo o workspace ou filtrar por \`company\_id\`.\
> \- Chave de empresa lista somente integrações da própria empresa.\
> \- Quando a chave for de empresa, \`company\_id\` divergente na query retorna \`403\`.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Integrações","description":"Cadastro e consulta de chaves `x-api-key`.\n\nCada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica).\nUse `allowed_ips` para restringir o acesso por IP/CIDR.\n\nO workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL."}],"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":{"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"IntegrationListResponse":{"type":"object","additionalProperties":false,"required":["items","paginate"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationResponse"}},"paginate":{"$ref":"#/components/schemas/CursorPaginateMeta"}}},"IntegrationResponse":{"type":"object","additionalProperties":false,"required":["id","workspace_id","name","active"],"properties":{"id":{"$ref":"#/components/schemas/ObjectId"},"workspace_id":{"$ref":"#/components/schemas/ObjectId"},"name":{"type":"string"},"active":{"type":"boolean"},"allowed_ips":{"type":["array","null"],"description":"IPs e faixas CIDR permitidos para autenticar chamadas dessa integração.","items":{"type":"string"}},"api_key":{"type":["string","null"],"description":"Retornado em valor completo na criação e na regeneração, e mascarado em leituras e listagens."},"company_id":{"oneOf":[{"$ref":"#/components/schemas/ObjectId"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"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":{"/integrations":{"get":{"operationId":"listIntegrations","tags":["Integrações"],"summary":"Listar integrações","description":"Lista integrações do workspace da chave autenticada com suporte a paginação por cursor.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode listar todo o workspace ou filtrar por `company_id`.\n- Chave de empresa lista somente integrações da própria empresa.\n- Quando a chave for de empresa, `company_id` divergente na query retorna `403`.","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"},{"name":"company_id","in":"query","required":false,"description":"Filtra por empresa. Em integração com chave de empresa, este valor é imposto automaticamente.","schema":{"$ref":"#/components/schemas/ObjectId"}},{"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 integrações","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationListResponse"}}}},"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 integração

> Cria uma integração no workspace da chave autenticada.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode criar em nível de workspace ou associar a uma empresa via \`company\_id\` ou \`tax\_id\`.\
> \- \`company\_id\` precisa pertencer ao mesmo workspace da chave usada na requisição.\
> \- \`tax\_id\` resolve a empresa somente dentro do mesmo workspace da chave usada na requisição.\
> \- Se \`company\_id\` e \`tax\_id\` vierem juntos, ambos precisam apontar para a mesma empresa.\
> \- Chave de empresa ignora \`company\_id\` e \`tax\_id\` do payload e associa a integração automaticamente à empresa da própria chave.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Integrações","description":"Cadastro e consulta de chaves `x-api-key`.\n\nCada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica).\nUse `allowed_ips` para restringir o acesso por IP/CIDR.\n\nO workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL."}],"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":{"IntegrationCreateRequest":{"type":"object","additionalProperties":false,"required":["name","active"],"properties":{"name":{"type":"string","minLength":3,"maxLength":200},"active":{"type":"boolean"},"allowed_ips":{"type":["array","null"],"description":"Lista opcional de IPs ou blocos CIDR autorizados a consumir a integração via `x-api-key`.\n\nQuando preenchida, a API compara o IP resolvido por `request.ip` com cada item antes de executar a rota.","items":{"type":"string","description":"IP exato ou faixa CIDR permitida para consumir a integração."}},"company_id":{"oneOf":[{"$ref":"#/components/schemas/ObjectId"},{"type":"null"}],"description":"Empresa alvo dentro do mesmo workspace da `x-api-key`.\n\nRegras:\n- Em chave de workspace, associa a integração a essa empresa específica.\n- Em chave de empresa, este campo é ignorado e substituído automaticamente pela empresa da própria chave."},"tax_id":{"type":["string","null"],"minLength":14,"maxLength":14,"description":"CNPJ da empresa alvo (somente dígitos), resolvido dentro do mesmo workspace da `x-api-key`.\n\nRegras:\n- Em chave de workspace, resolve o `company_id` correspondente antes da persistência.\n- Em chave de empresa, este campo é ignorado e substituído automaticamente pela empresa da própria chave."}}},"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"IntegrationResponse":{"type":"object","additionalProperties":false,"required":["id","workspace_id","name","active"],"properties":{"id":{"$ref":"#/components/schemas/ObjectId"},"workspace_id":{"$ref":"#/components/schemas/ObjectId"},"name":{"type":"string"},"active":{"type":"boolean"},"allowed_ips":{"type":["array","null"],"description":"IPs e faixas CIDR permitidos para autenticar chamadas dessa integração.","items":{"type":"string"}},"api_key":{"type":["string","null"],"description":"Retornado em valor completo na criação e na regeneração, e mascarado em leituras e listagens."},"company_id":{"oneOf":[{"$ref":"#/components/schemas/ObjectId"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"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":{"/integrations":{"post":{"operationId":"createIntegration","tags":["Integrações"],"summary":"Criar integração","description":"Cria uma integração no workspace da chave autenticada.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode criar em nível de workspace ou associar a uma empresa via `company_id` ou `tax_id`.\n- `company_id` precisa pertencer ao mesmo workspace da chave usada na requisição.\n- `tax_id` resolve a empresa somente dentro do mesmo workspace da chave usada na requisição.\n- Se `company_id` e `tax_id` vierem juntos, ambos precisam apontar para a mesma empresa.\n- Chave de empresa ignora `company_id` e `tax_id` do payload e associa a integração automaticamente à empresa da própria chave.","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationCreateRequest"}}}},"responses":{"201":{"description":"Integração criada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Erro de validação ou de referência de empresa","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 não encontrada no workspace da chave","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Ler integração

> Retorna os dados de uma integração por ID.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode ler integrações do próprio workspace.\
> \- Chave de empresa só pode ler integrações da própria empresa.\
> \- Integrações em nível de workspace ou de outra empresa retornam \`403\` para chave de empresa.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Integrações","description":"Cadastro e consulta de chaves `x-api-key`.\n\nCada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica).\nUse `allowed_ips` para restringir o acesso por IP/CIDR.\n\nO workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL."}],"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":{"IntegrationId":{"name":"integration_id","in":"path","required":true,"description":"ID da integração no workspace.","schema":{"$ref":"#/components/schemas/ObjectId"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"IntegrationResponse":{"type":"object","additionalProperties":false,"required":["id","workspace_id","name","active"],"properties":{"id":{"$ref":"#/components/schemas/ObjectId"},"workspace_id":{"$ref":"#/components/schemas/ObjectId"},"name":{"type":"string"},"active":{"type":"boolean"},"allowed_ips":{"type":["array","null"],"description":"IPs e faixas CIDR permitidos para autenticar chamadas dessa integração.","items":{"type":"string"}},"api_key":{"type":["string","null"],"description":"Retornado em valor completo na criação e na regeneração, e mascarado em leituras e listagens."},"company_id":{"oneOf":[{"$ref":"#/components/schemas/ObjectId"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"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":{"/integrations/{integration_id}":{"get":{"operationId":"getIntegration","tags":["Integrações"],"summary":"Ler integração","description":"Retorna os dados de uma integração por ID.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode ler integrações do próprio workspace.\n- Chave de empresa só pode ler integrações da própria empresa.\n- Integrações em nível de workspace ou de outra empresa retornam `403` para chave de empresa.","parameters":[{"$ref":"#/components/parameters/IntegrationId"},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"Integração encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Integração não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Editar integração

> Atualiza uma integração existente.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode mover a integração para uma empresa específica via \`company\_id\` ou \`tax\_id\`, ou removê-la do escopo da empresa enviando \`company\_id: null\`.\
> \- \`company\_id\` e \`tax\_id\` são validados dentro do workspace da chave.\
> \- Se \`company\_id\` e \`tax\_id\` vierem juntos, ambos precisam apontar para a mesma empresa.\
> \- Chave de empresa ignora \`company\_id\` e \`tax\_id\` do payload e mantém a integração associada à própria empresa.\
> \- Chave de empresa não pode atualizar integração em nível de workspace ou de outra empresa.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Integrações","description":"Cadastro e consulta de chaves `x-api-key`.\n\nCada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica).\nUse `allowed_ips` para restringir o acesso por IP/CIDR.\n\nO workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL."}],"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":{"IntegrationId":{"name":"integration_id","in":"path","required":true,"description":"ID da integração no workspace.","schema":{"$ref":"#/components/schemas/ObjectId"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"IntegrationCreateRequest":{"type":"object","additionalProperties":false,"required":["name","active"],"properties":{"name":{"type":"string","minLength":3,"maxLength":200},"active":{"type":"boolean"},"allowed_ips":{"type":["array","null"],"description":"Lista opcional de IPs ou blocos CIDR autorizados a consumir a integração via `x-api-key`.\n\nQuando preenchida, a API compara o IP resolvido por `request.ip` com cada item antes de executar a rota.","items":{"type":"string","description":"IP exato ou faixa CIDR permitida para consumir a integração."}},"company_id":{"oneOf":[{"$ref":"#/components/schemas/ObjectId"},{"type":"null"}],"description":"Empresa alvo dentro do mesmo workspace da `x-api-key`.\n\nRegras:\n- Em chave de workspace, associa a integração a essa empresa específica.\n- Em chave de empresa, este campo é ignorado e substituído automaticamente pela empresa da própria chave."},"tax_id":{"type":["string","null"],"minLength":14,"maxLength":14,"description":"CNPJ da empresa alvo (somente dígitos), resolvido dentro do mesmo workspace da `x-api-key`.\n\nRegras:\n- Em chave de workspace, resolve o `company_id` correspondente antes da persistência.\n- Em chave de empresa, este campo é ignorado e substituído automaticamente pela empresa da própria chave."}}},"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":{"/integrations/{integration_id}":{"put":{"operationId":"updateIntegration","tags":["Integrações"],"summary":"Editar integração","description":"Atualiza uma integração existente.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode mover a integração para uma empresa específica via `company_id` ou `tax_id`, ou removê-la do escopo da empresa enviando `company_id: null`.\n- `company_id` e `tax_id` são validados dentro do workspace da chave.\n- Se `company_id` e `tax_id` vierem juntos, ambos precisam apontar para a mesma empresa.\n- Chave de empresa ignora `company_id` e `tax_id` do payload e mantém a integração associada à própria empresa.\n- Chave de empresa não pode atualizar integração em nível de workspace ou de outra empresa.","parameters":[{"$ref":"#/components/parameters/IntegrationId"},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationCreateRequest"}}}},"responses":{"204":{"description":"Integração atualizada"},"400":{"description":"Erro de validação ou de referência de empresa","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":"Integração ou empresa não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Remover integração

> Remove uma integração existente.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode excluir integrações do próprio workspace.\
> \- Chave de empresa só pode excluir integrações da própria empresa.\
> \- Integrações em nível de workspace ou de outra empresa retornam \`403\` para chave de empresa.\
> \- A integração precisa estar inativa antes da exclusão.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Integrações","description":"Cadastro e consulta de chaves `x-api-key`.\n\nCada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica).\nUse `allowed_ips` para restringir o acesso por IP/CIDR.\n\nO workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL."}],"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":{"IntegrationId":{"name":"integration_id","in":"path","required":true,"description":"ID da integração no workspace.","schema":{"$ref":"#/components/schemas/ObjectId"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"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":{"/integrations/{integration_id}":{"delete":{"operationId":"deleteIntegration","tags":["Integrações"],"summary":"Remover integração","description":"Remove uma integração existente.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode excluir integrações do próprio workspace.\n- Chave de empresa só pode excluir integrações da própria empresa.\n- Integrações em nível de workspace ou de outra empresa retornam `403` para chave de empresa.\n- A integração precisa estar inativa antes da exclusão.","parameters":[{"$ref":"#/components/parameters/IntegrationId"},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"204":{"description":"Integração removida"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Integração não encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Integração precisa estar inativa para exclusão","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/ServiceUnderMaintenance"}}}}}}
```

## Gerar nova chave de API

> Gera uma nova \`api\_key\` para a integração existente e invalida imediatamente a chave anterior.\
> \
> O novo valor é retornado em texto puro apenas neste response. Leituras subsequentes de integração retornam somente o preview mascarado em \`api\_key\`.\
> \
> Regras de escopo com \`x-api-key\`:\
> \- Chave de workspace pode gerar nova chave para integrações do próprio workspace.\
> \- Chave de empresa só pode gerar nova chave para integrações da própria empresa.\
> \- Integrações em nível de workspace ou de outra empresa retornam \`403\` para chave de empresa.

```json
{"openapi":"3.1.1","info":{"title":"API IXC E-Docs - Integração x-api-key","version":"0.1.0"},"tags":[{"name":"Integrações","description":"Cadastro e consulta de chaves `x-api-key`.\n\nCada integração pode ter escopo de workspace (acesso a todas as empresas) ou de empresa (acesso restrito a uma empresa específica).\nUse `allowed_ips` para restringir o acesso por IP/CIDR.\n\nO workspace é resolvido automaticamente pela chave autenticada — não é necessário informá-lo na URL."}],"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":{"IntegrationId":{"name":"integration_id","in":"path","required":true,"description":"ID da integração no workspace.","schema":{"$ref":"#/components/schemas/ObjectId"}},"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Idioma preferencial para mensagens de erro (ex.: pt-BR).","schema":{"type":"string"}}},"schemas":{"ObjectId":{"type":"string","description":"Identificador no formato ObjectId."},"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":{"/integrations/{integration_id}/api-key/regenerate":{"post":{"operationId":"regenerateIntegrationApiKey","tags":["Integrações"],"summary":"Gerar nova chave de API","description":"Gera uma nova `api_key` para a integração existente e invalida imediatamente a chave anterior.\n\nO novo valor é retornado em texto puro apenas neste response. Leituras subsequentes de integração retornam somente o preview mascarado em `api_key`.\n\nRegras de escopo com `x-api-key`:\n- Chave de workspace pode gerar nova chave para integrações do próprio workspace.\n- Chave de empresa só pode gerar nova chave para integrações da própria empresa.\n- Integrações em nível de workspace ou de outra empresa retornam `403` para chave de empresa.","parameters":[{"$ref":"#/components/parameters/IntegrationId"},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"Nova chave de API gerada","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["api_key"],"properties":{"api_key":{"type":"string","description":"Chave de API em texto puro, exibida somente neste response."}}}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Integração 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/integracoes.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.
