Skip to content

Correct invoice data and re-analyse it (signed-in ANALYST+, not API keys)

PATCH
/invoices/{invoiceId}
curl --request PATCH \
--url https://api.invogi.com/v1/invoices/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "reason": "OCR read 1190.00 instead of 1190.50", "expected_revision": 1, "fields": { "gross_amount": "1190.50", "invoice_number": "INV-2026-0042" } }'

For data the extraction got wrong. The invoice is re-analysed in full as a new revision; earlier revisions, runs, decisions and findings are kept. Findings of earlier analyses become SUPERSEDED and can no longer be reviewed. Only the keys present in fields change; a nullable field is cleared with null, and lines replaces the whole list.

Made by a signed-in user: API keys are refused with FORBIDDEN. Analysts can correct the invoice’s own values; changing supplier (including its bank account) needs an Admin or Owner. A correction that would clear a finding is an override and needs an Admin or Owner, except that an analyst may clear data-quality findings (EXTRACTION_LOW_CONFIDENCE, INVALID_TOTALS, CURRENCY_UNKNOWN, STRUCTURED_INVOICE_INVALID) on an invoice that has its source document, with verified_against_document set.

Rejected with CONFLICT when a payment references the invoice, it was submitted to KSeF, a financial outcome is recorded for it, one of its findings is CONFIRMED, expected_revision is not the current revision, or the invoice has reached its revision limit (19 corrections for analysts, more for Admins and Owners). Duplicate and anomaly checks also look at every supplier the invoice has been matched to, and an account the invoice was flagged for stays flagged on it until it is verified with the supplier, however the data is edited.

invoiceId
required
string
Media typeapplication/json
object
reason
required
string
>= 1 characters <= 1000 characters
expected_revision

The revision the caller was looking at; a different current revision is a CONFLICT

integer
>= 1
verified_against_document

The person compared the corrected values with the invoice’s source document. Required for an analyst to clear data-quality findings; recorded on the revision

boolean
fields
required
object
>= 1 properties
invoice_number
string
issue_date
string format: date
due_date
string | null format: date
currency

ISO 4217

string
net_amount

Decimal string

string | null
tax_amount

Decimal string

string | null
gross_amount

Decimal string

string
purchase_order_ref
string | null
buyer
object
name
string
tax_id
string
supplier
object
name
string
tax_id
string
company_number

UK Companies House number. Setting it re-checks the corrected number against the register.

string
bank_account
object
iban
string
sort_code
string
account_number
string
lines

Replaces the whole line list

Array<object>
object
description
string
quantity
string
unit_price
string
tax_rate
string
line_net_amount
string

Example

{
"reason": "OCR read 1190.00 instead of 1190.50",
"expected_revision": 1,
"fields": {
"gross_amount": "1190.50",
"invoice_number": "INV-2026-0042"
}
}

Corrected and re-analysed

Media typeapplication/json
object
id
required
string format: uuid
revision
required
integer
>= 2
decision
required
string
Allowed values: PASS REVIEW BLOCK
previous_decision
required
string | null
Allowed values: PASS REVIEW BLOCK
risk_score
required
integer
<= 100
changed_fields
required
Array<string>
superseded_finding_ids
required

Findings of earlier analyses that this correction replaced

Array<string>
cleared_findings
required

Findings the correction clears, as TYPE or TYPE (of N invoices) for findings that point at other invoices

Array<string>
added_findings
required

Findings the corrected data raises that the invoice did not have

Array<string>
blockers
required

What stops the caller from saving this correction. Only a preview returns blockers (saving refuses with the first one instead). Empty when saving would succeed.

Array<object>
object
kind
required
string
Allowed values: ADMIN_REQUIRED ATTESTATION_REQUIRED SOURCE_DOCUMENT_REQUIRED
message
required
string
findings
required
Array<object>
object
versions
required
object

Example

{
"decision": "PASS",
"previous_decision": "PASS",
"blockers": [
{
"kind": "ADMIN_REQUIRED"
}
]
}

Invalid request

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: NOT_FOUND UNAUTHORIZED FORBIDDEN INVALID_REQUEST CONFLICT RATE_LIMITED USAGE_LIMIT_EXCEEDED PROCESSING_FAILED
message
required
string
request_id
required
string

Example

{
"error": {
"code": "NOT_FOUND"
}
}

Missing or invalid API key

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: NOT_FOUND UNAUTHORIZED FORBIDDEN INVALID_REQUEST CONFLICT RATE_LIMITED USAGE_LIMIT_EXCEEDED PROCESSING_FAILED
message
required
string
request_id
required
string

Example

{
"error": {
"code": "NOT_FOUND"
}
}

API key lacks required scope/role

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: NOT_FOUND UNAUTHORIZED FORBIDDEN INVALID_REQUEST CONFLICT RATE_LIMITED USAGE_LIMIT_EXCEEDED PROCESSING_FAILED
message
required
string
request_id
required
string

Example

{
"error": {
"code": "NOT_FOUND"
}
}

Resource not found

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: NOT_FOUND UNAUTHORIZED FORBIDDEN INVALID_REQUEST CONFLICT RATE_LIMITED USAGE_LIMIT_EXCEEDED PROCESSING_FAILED
message
required
string
request_id
required
string

Example

{
"error": {
"code": "NOT_FOUND"
}
}

Conflicting idempotency key or resource processing state

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: NOT_FOUND UNAUTHORIZED FORBIDDEN INVALID_REQUEST CONFLICT RATE_LIMITED USAGE_LIMIT_EXCEEDED PROCESSING_FAILED
message
required
string
request_id
required
string

Example

{
"error": {
"code": "NOT_FOUND"
}
}