Invoice Approvals
Overview
Ottimate’s approval system allows you to manage invoice approvers programmatically through the API. While approval policies are configured in the Ottimate UI, the API enables you to:
- View all approvers assigned to an invoice, and inspect the full policy chain
- Add manual approvers to invoices
- Remove approvers from the approval chain
- Approve an invoice, in bulk or at a specific policy tier
- Revoke an approval that has already been given
- List the invoices awaiting your own approval
For information on how to configure approval policies in Ottimate, see Approval Policy Configuration.
Note: The Approval API manages approvers and approval actions only. Approval policies themselves must be configured through the Ottimate user interface.
How Invoice Approvals Work
When an invoice enters the approval workflow, it receives a pending-approval status. The invoice must be approved by all assigned approvers before it can proceed to export. Approvers can be assigned either:
- Policy-based approvers: Automatically assigned based on approval policies configured in Ottimate
- Manual approvers: Added individually via the API or UI for ad-hoc review requirements
API endpoints
List Invoice Approvers
To view all approvers assigned to an invoice, including their approval status:
Where {id} is the Ottimate-generated invoice ID.
Response Details
The response includes an array of approvers, where each approver object contains:
id: The approval record ID (e.g.,pbjappr_xxx) - use this ID when removing an approver via the DELETE endpointapprover: User details including ID, email, and display namepolicy: The associated approval policy. Policy-based approvers carry the policy’sidandname; manual approvers carry an object with both fields as empty stringscreated_date: When this approver was added to the invoice
Example Response
Identifying Manual vs. Policy-Based Approvers: policy is always an object — never null. Manual approvers have policy.id and policy.name as empty strings; policy-based approvers have both populated. Test policy.id for emptiness rather than checking whether policy itself is null.
Status codes
Add a Manual Approver
Add an ad-hoc approver to an invoice using:
Request body
The body is required and takes a single field:
Where approver is the integer user ID of the Ottimate user to add. This is the approver.id value returned by GET /v1/invoices/{id}/approvers, or a user ID from your account’s user list.
Response
Important Behavior
When you add a manual approver:
- The approver must be an authorized user of the location with permission to access the invoice.
- The approver receives a pending-approval email notification.
- Approval policies are re-applied to the invoice.
Adding an approver to an already-approved invoice resets it to pending-approval. If the invoice had an approved_date, that date and the recorded approving user are cleared, so an invoice sitting at ready-for-export drops back into the approval queue. Do not use this endpoint to attach a reviewer for audit purposes on an approved invoice — it will pull the invoice out of the export path.
Status codes
A duplicate approver returns:
Omitting approver returns:
message is not always a string. Ottimate’s error envelope carries the underlying error in message, which may be a string or a nested object depending on the failure. Parse it defensively rather than assuming a string.
Remove an Approver
Remove a specific approver from an invoice:
Parameters
id: The invoice IDapproval_id: The approval record ID to remove (e.g.,pbjappr_xxx) - this is theidfield from the approver object returned byGET /v1/invoices/{id}/approvers
Omitting approval_id removes every approver on the invoice. The parameter is documented as required, but a request without it deletes the invoice’s entire approver list rather than returning an error. Always send approval_id.
Approve an Invoice
Approve an invoice to mark it ready for export and payment:
Features
- Marks the invoice with an
approved_date - Automatically verifies the invoice if not already verified
- Updates invoice status to
ready-for-exportwhen all approvals are complete
Force Approval
For authorized users, you can bypass the normal approval chain:
Approve at a Specific Policy Tier
When an invoice is routed through Advanced Approval Policies, you can approve it at one specific tier rather than approving the whole chain:
policy_id is required — omitting it returns a 400. Use GET /v1/invoices/{id}/approval-chain to find the tier you want to approve.
force_approve is not supported here. Sending force_approve: true to this endpoint returns a 400 error. Use POST /v1/invoices/{id}/approve if you need to bypass the approval chain.
Revoke an Approval
Undo an approval step that has already been given:
approval_id is required and is the id of the approval record from GET /v1/invoices/{id}/approvers. Omitting it returns a 400:
Bulk Approve
Approve many invoices in one asynchronous request:
invoice_idsis required and must be a non-empty JSON array — a comma-separated string is rejected- Maximum 100 invoices per request
force_approveis optional and defaults tofalse
The endpoint returns 202 Accepted with a batch path you can poll:
Poll GET /v1/batch/{id}/progress for status and GET /v1/batch/{id}/results for per-invoice outcomes.
Inspecting the Approval Chain
Two read endpoints expose the approval state in different shapes:
Approval summary
Returns manual_user_approvers, a policies array with per-tier min_users_for_approval / num_approved / num_pending counts, and a users map keyed by user ID. Use this to answer “how many more approvals does this tier need?”.
Approval chain
Returns the ordered policy chain as an array, where each tier carries status, min_approver, approved, its approvers[], and a children array for nested tiers. Use this to render the approval hierarchy.
Pass sync_approval=true to re-apply approval policies before returning the chain. It has no effect on an invoice that has already been exported.
Invoices Awaiting Your Approval
Returns the invoices that the authenticated API user is themselves an approver on and has not yet approved. Supports page, limit, ottimate_location_ids, ottimate_vendor_id, date_from, and date_to.
This is scoped to the authenticated user, not to your account. An account-scoped integration whose API user is not an assigned approver on anything will get an empty list — use GET /v1/invoices?status=pending-approval to see every invoice awaiting approval across the account.

