Skip to content

Open a recovery case from a confirmed finding (ANALYST+, dashboard user)

POST
/recoveries
curl --request POST \
--url https://api.invogi.com/v1/recoveries \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "findingId": "8f1c2b9e-1a2b-4c3d-9e8f-123456789abc", "realization": { "kind": "CASH_REFUND", "reference": "BACS 14 Oct", "note": "Refund on the 14 Oct bank statement.", "applied": { "appliedOn": "2026-10-14" } } }'

The case claims the finding’s payment when it is payment-backed, otherwise its invoice; confirmedAmount defaults to that amount and may not exceed it. Each finding, invoice and payment can belong to one case only (409), and an invoice recorded as a prevented payment cannot also be recovered (409). realization records money that already came back in the same step: a cash refund is realized in full; a credit note or offset counts only for its applied part. API keys cannot open cases.

Media typeapplication/json
object
findingId
required
string format: uuid
confirmedAmount
string
/^\d{1,18}(\.\d{1,6})?$/
taxAmount

Tax component of the confirmed amount; defaults to the invoice’s tax when the whole invoice is claimed

string | null
ownerUserId

Defaults to the caller

string | null format: uuid
nextAction
string | null
<= 500 characters
nextActionDueOn
string | null format: date
realization
object
kind
required
string
Allowed values: CASH_REFUND CREDIT_NOTE OFFSET
reference
required
string
<= 200 characters
issuedOn
string format: date
amount

Defaults to the confirmed amount

string
note
required
string
>= 3 characters <= 2000 characters
applied
object
amount
string
appliedOn
required

On or before today

string format: date
reference
string

Example

{
"findingId": "8f1c2b9e-1a2b-4c3d-9e8f-123456789abc",
"realization": {
"kind": "CASH_REFUND",
"reference": "BACS 14 Oct",
"note": "Refund on the 14 Oct bank statement.",
"applied": {
"appliedOn": "2026-10-14"
}
}
}

The case

Media typeapplication/json
object
id
required
string format: uuid
status
required

CONFIRMED, IN_RECOVERY and AGREED are set by people (the stage); CREDIT_RECEIVED, PARTIALLY_REALIZED and REALIZED are derived from instruments and applications; the CLOSED statuses from closure.

string
Allowed values: CONFIRMED IN_RECOVERY AGREED CREDIT_RECEIVED PARTIALLY_REALIZED REALIZED CLOSED_UNRECOVERED CLOSED_PARTIALLY_RECOVERED MERGED
stage
required
string
Allowed values: CONFIRMED IN_RECOVERY AGREED
currency
required
string
identifiedAmount
required

What the source records suggested

string
confirmedAmount
required

What a person confirmed as recoverable

string
verifiedAmount
required
string
closedAmount
required
string
openAmount
required
string
taxAmount
string | null
vatAdjustment
One of:
null
supplier
object
id
string format: uuid
name
string | null
company
object
id
string format: uuid
name
string | null
owner
object
id
string format: uuid
name
string | null
nextAction
string | null
nextActionDueOn
string | null format: date
promisedResponseOn
string | null format: date
lastContactAt
string | null format: date-time
closeReason
string | null
closedAt
string | null format: date-time
legacy
boolean
paymentBacked
required

The case claims a payment that went out twice

boolean
primaryFindingId
string format: uuid
createdAt
string format: date-time
sources
required

The finding, invoice and payment this case claims. Each belongs to one case only.

object
findings
Array<object>
object
id
string
type
string
severity
string
summary
string
disposition
string
invoices
Array<object>
object
key
additional properties
any
payments
Array<object>
object
key
additional properties
any
supplierCredits

Ledger credits the case claims, with the ledger’s current balance

Array
object
id
required
string format: uuid
provider
required
string
Allowed values: XERO QUICKBOOKS_ONLINE
kind

PREPAYMENT is money paid to the supplier in advance and not yet applied to a bill

string
Allowed values: CREDIT_NOTE PREPAYMENT
creditNumber

The credit’s number; for a prepayment

string | null
supplierName
string | null
issueDate
string | null format: date
currency
required
string
totalAmount
required
string
remainingAmount
required

The ledger’s unused balance at lastSeenAt

string
lastSeenAt
required
string format: date-time
closedAt

Set once the ledger stopped listing the credit as open (used

string | null format: date-time
proposal
One of:
null
supplierRefunds

Refunds from imported payment history the case claims (accepted suggested matches)

Array<object>
object
id
required
string format: uuid
amount
required
string
currency
required
string
>= 3 characters <= 3 characters
receivedOn
required
string format: date
reference
string | null
payeeName

As the payment file named the payee

string | null
related
required

The other side of the duplicate pair, as evidence

object
invoices
Array<object>
object
key
additional properties
any
payments
Array<object>
object
key
additional properties
any
instruments
required
Array<object>
object
id
string format: uuid
kind
string
Allowed values: CASH_REFUND CREDIT_NOTE OFFSET LEGACY_OUTCOME
reference
string
issuedOn
string | null format: date
faceAmount
string
currency
string
appliedAmount
string
unappliedAmount

Not counted as recovered

string
applications
required
Array<object>
object
id
string format: uuid
instrumentId
string format: uuid
amount
string
currency
string
appliedOn
string format: date
reference
string
note
string
verificationBasis
string
Allowed values: USER_ATTESTED LEGACY_OUTCOME
verifiedBy
object
id
string
name
string | null
active
boolean
reversedOn
string | null format: date
reversalReason
string | null
events
required

Append-only timeline, newest first

Array<object>
object
key
additional properties
any
prevention

What should stop this loss happening again (§6.6)

object
suggestions
Array<object>
object
action
string
Allowed values: MONITOR_NEW_BILLS IMPORT_PAYMENTS VERIFY_BANK_ACCOUNT KEEP_LEDGER_CONNECTED LOAD_PURCHASE_ORDERS
title
string
detail
string
href

App path where it is set up

string
inPlace

Whether the workspace’s data shows it in place now

boolean
decision
One of:
null
offsetCandidates
required

Recent bills from the same supplier, in the case currency, with no recorded payment — open cases only

Array<object>
object
id
string
invoiceNumber
string
issueDate
string | null
dueDate
string | null
currency
string
grossAmount
string
mergedInto
One of:
null
mergeCandidates

Open cases in the same currency (and supplier, where both have one) that this case could merge into or move a source to

Array<object>
object
id
string format: uuid
reference
string
status
string
confirmedAmount
string
currency
string
createdAt
string format: date-time
findingType
string
supplierContacts

The supplier’s contacts, primary first

Array<object>
object
id
required
string format: uuid
supplierId
required
string format: uuid
name
required
string
email
string | null format: email
phone
string | null
role

E.g. Accounts receivable

string | null
isPrimary
required
boolean
updatedAt
string format: date-time
suggestedMatches

Open cases only. Money that may answer this case: an unused ledger credit no case claims yet, or a refund from imported payment history, from the same supplier in the case currency, dated no more than 30 days before the case opened, and no larger than what the case is still waiting for (open less unapplied credit). Each credit or refund is offered to one case — the one it covers exactly, else the oldest. Accept or dismiss with /recoveries/{caseId}/matches/*.

Array<object>
object
kind
required
string
Allowed values: LEDGER_CREDIT REFUND
evidenceId
required

The supplier credit or supplier refund

string format: uuid
fit
required

EXACT covers what the case is waiting for; PARTIAL is less

string
Allowed values: EXACT PARTIAL
amount
required

The credit’s unused balance

string
currency
required
string
>= 3 characters <= 3 characters
on
required

Issue date of the credit

string format: date
reference
string | null
source
required
string
Allowed values: XERO QUICKBOOKS_ONLINE PAYMENT_IMPORT
creditKind

For LEDGER_CREDIT

string | null
Allowed values: CREDIT_NOTE PREPAYMENT
supplierName

As the ledger or payment file named the supplier

string | null

Example

{
"status": "CONFIRMED",
"stage": "CONFIRMED",
"vatAdjustment": {
"status": "REQUIRED"
},
"sources": {
"supplierCredits": [
{
"provider": "XERO",
"kind": "CREDIT_NOTE"
}
]
},
"instruments": [
{
"kind": "CASH_REFUND"
}
],
"applications": [
{
"verificationBasis": "USER_ATTESTED"
}
],
"prevention": {
"suggestions": [
{
"action": "MONITOR_NEW_BILLS"
}
],
"decision": {
"decision": "DONE"
}
},
"suggestedMatches": [
{
"kind": "LEDGER_CREDIT",
"fit": "EXACT",
"source": "XERO",
"creditKind": "CREDIT_NOTE"
}
]
}

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"
}
}