The API key lacks the scope required for this endpoint.
Grant the missing scope in the dashboard or use a key that already has it.
auth.team_suspended
403
The account (team) this API key belongs to is suspended; all of the team's keys are rejected while the suspension is active.
Contact support — access is restored automatically when the account is reactivated.
billing.suspended
403
Paid processing is suspended for this team after an unresolved billing problem (chargeback or failed payment). Distinct from auth.team_suspended: reads keep working, only work that costs credits is refused.
Contact support and quote the case reference in the message — buying credits does not lift a suspension.
auth.ip_not_allowed
403
The request originated from an IP not in the key's allowlist.
Add the caller's IP to the key's allowlist or call from an allowed network.
plan.api_access_disabled
403
Your team's plan does not include API access.
Upgrade the team plan to one that includes public API access.
client.not_found
404
The X-Client-Id header references a client that does not exist.
Verify the client ID and that it has not been deleted.
client.not_in_team
403
The referenced client does not belong to your team.
Use a client ID owned by the authenticated team.
client.scope_mismatch
403
This key is scoped to a specific client and X-Client-Id must match it.
Send the scoped client's ID, or use a team-scoped key.
The team does not have enough processing credits for this request.
Purchase credits, then retry. Do not retry without buying — the balance will not change on its own.
credits.insufficient returns 402, not 403. Clients that treat every 403
as "out of credits" must branch on code instead: 403 now means an
authorization failure, and a failure of the credit check itself surfaces as a
5xx.
Verify the invoice ID and that the authenticated team owns it.
job.not_found
404
No processing job matches the supplied ID for this team.
Verify the job_... ID returned by POST /invoices. Jobs are retained for 30 days after terminal state.
contact.not_found
404
No contact matches the supplied ID for this team.
Verify the contact ID and that the authenticated team owns it.
auth.key_suspended
403
Ops has administratively suspended this API key.
Contact support — partners cannot self-restore a suspended key.
invoice.reprocess_unavailable
409
The original source file is no longer retained for this invoice, so it cannot be reprocessed.
Re-upload the source file to create a new invoice.
invoice.not_ready_for_export
409
The invoice is still queued or processing.
Poll the invoice until status is completed, then retry the export.
invoice.export_unavailable_failed
409
Processing failed, so the invoice cannot be exported.
Re-upload the source file or fix the parsing issue before exporting.
invoice.export_unavailable_preprocessing
409
Export preprocessing skipped the invoice — a required goods mapping is missing, a currency rate could not be resolved, or a cumulative line carries no code. The detail names the reason.
Fix the invoice data named in detail (map the goods code, set the missing line code) and retry the export.
invoice.not_editable
409
Invoice is still being processed and cannot be edited yet.
Poll GET /invoices/{id}/status until the invoice reaches a terminal state (processed or failed), then retry the update.
Returned by POST /invoices/{id}/assignment/{approve,move,discard} when resolving an invoice blocked by the client-assignment gate (assignment.status = "needs_review").
Code
Status
Description
Remediation
invoice.assignment_not_reviewable
409
The invoice is not awaiting assignment review (it was confirmed, exempt, or never assessed).
Only invoices with assignment.status = "needs_review" accept review actions.
invoice.assignment_conflict
409
A different review action was already applied to this invoice. The problem body carries the previously applied state.
Treat the returned state as the authoritative resolution; repeating the same action returns 200.
invoice.assignment_move_needs_review
409
Reassessment against the destination client still requires review. The problem body carries the destination assessment (status, reasonCodes).
Inspect the assessment; repeat the move with "force": true to move anyway, or pick a different destination.
invoice.assignment_destination_same_client
400
The move destination equals the invoice's current client.
Approve instead of moving, or choose a different destination client.
These codes are emitted when an underlying exception didn't carry its own
machine-readable identifier (rare — most public-API errors map to a
specific code above). Branch on these only as a last-resort default.