---
title: "Associar UMA fatura a vários movimentos"
method: POST
path: "/api/financeiro/movements/invoices-batch"
tags: ["Financeiro (Protected)"]
---

# Associar UMA fatura a vários movimentos

`POST /api/financeiro/movements/invoices-batch`

## Request

- Base URL: `https://api.multigest.pt` (the document declares no server; this is the origin it was published from)
- URL: `https://api.multigest.pt/api/financeiro/movements/invoices-batch`
- Auth: API key in header `x-api-token` and API key in header `x-origin-verify`

Associa a MESMA fatura a vários movimentos de uma só vez (#916).

Cada movimento leva `min(o que ainda pode justificar, o que falta associar
na fatura)`; quando a fatura esgota, os restantes ficam associados a 0,00 €
— só referência. Movimentos de origem de centro de custo (despesa) são
tudo-ou-nada. `dry_run: true` devolve exatamente a mesma repartição sem
escrever nada: é o que o diálogo mostra antes de confirmar.

Âmbito: empresa **e** ponto de venda do utilizador, como os outros dois
endpoints em lote (`/mark-paid`, `/movements/comprovativo-batch`) — as duas
listas que alimentam a seleção já são do PV do utilizador.

## Headers

- `x-api-token` string, nullable

## Request body

- MovementInvoicesBatchRequest: Attach ONE invoice to N movements (#916). The 200-id cap is NOT declared here on purpose: a pydantic bound answers 422 with a schema error, and the sibling batch endpoint answers 400 with a sentence a user can read (routes/financials.py::attach_comprovativo_batch). The service enforces it after de-duplication, since the cap protects the `IN (...)` parameter count, which counts unique ids.
  - `movement_ids` integer[], required
  - `fatura_id` integer, required: Faturas.ID a associar
  - `dry_run` boolean: Pré-visualizar a repartição sem escrever nada. Mesma classificação e mesmos valores; não bloqueia a fatura nem regista auditoria.

## Response `200`

Successful Response

- MovementInvoicesBatchResponse: Result (or preview) of attaching one invoice to a batch of movements.
  - `dry_run` boolean, required
  - `fatura_id` integer, required
  - `invoice_numero` string, nullable
  - `invoice_total` number, required
  - `room_before` number, required: Por associar na fatura antes deste lote
  - `room_after` number, required: Por associar depois deste lote
  - `requested_total` number, required: Soma do que os movimentos elegíveis podiam associar
  - `capped` boolean, required: Algum movimento ficou com valor parcial ou a zero
  - `shortfall` object: Contagens: total / parcial / zero / ignorados
  - `warning` string, nullable
  - `attached` MovementInvoicesBatchAttached[]
    - `movement_id` integer, required
    - `movement_total` number, required: abs(ValorTotal) BRUTO — o tecto que a repartição usou
    - `amount` number, required: Valor associado (0 = só referência)
    - `reference_only` boolean, required
    - `atcud_set` boolean, required: Movimentos.ATCUD estava livre e passou a apontar para esta fatura
    - `ignora_atcud` boolean, required: Movimento marcado IgnoraAtcud: fora da justificação
    - `is_cost_center_parent` boolean, required: Movimento de origem de um grupo de centro de custo (despesa)
  - `skipped` MovementInvoicesBatchSkipped[]
    - `movement_id` integer, required
    - `reason` string, required
  - `counterparty_warnings` object[]
  - `invoice_split_sync` object, nullable

## Other responses

- `422`: Validation Error

## Changes

- **2026-09-10** `a53c2f2bc1fd`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/multigest/apis/multigest-protected-api/changes/api/financeiro/movements/invoices-batch/post.md)

---

[API](https://skmtc.dev/multigest/apis/multigest-protected-api.md) - [All operations](https://skmtc.dev/multigest/apis/multigest-protected-api/llms.txt) - [OpenAPI document](https://skmtc.dev/multigest/apis/multigest-protected-api/revisions/75574126948d?raw)
