Expense reports
Group expenses into reports, manage report lifecycle, and submit expense reports for approval using the Expense API.
Group expenses into reports, manage the report lifecycle, and submit reports for approval using either dynamic Fields or direct JSON payloads.
Overview
Expense reports collect one or more expense records into a single submission unit. Users typically create a report, add eligible expenses, review totals and required fields, then submit the report for approval.
Report lifecycle
Expense reports move through a lifecycle as users submit them and approvers process them:
| Lifecycle stage | Typical status | Description |
|---|---|---|
| Draft | NEW, NORMAL | The user is still creating or editing the report. Expenses can be added or removed if capabilities allow it. |
| Submitted | APPROVAL | The report has been submitted and is waiting for approval. |
| Approved / processing | APPROVED, READY_TO_SEND, TRANSFER, SEND | The report has passed approval and is moving toward export or payment. |
| Completed | SENT, PAID | The report has been exported, sent, or paid. |
| Rejected | REJECTED | An approver rejected the report or one or more included expenses. The user may need to edit and resubmit. |
Use processStatus to query broad lifecycle groups:
processStatus | Includes |
|---|---|
DRAFT | Draft reports such as NEW and NORMAL |
PROCESSING | Submitted and in-progress reports such as APPROVAL, APPROVED, READY_TO_SEND, TRANSFER, and SEND |
PROCESSED | Completed reports such as SENT and PAID |
REJECTED | Rejected reports |
API endpoints
| Operation | Method | Endpoint |
|---|---|---|
| List expense reports | GET | /v1/expense/expensereports |
| Get expense report | GET | /v1/expense/expensereports/{expenseReportId} |
| Create report with Fields | POST | /v1/expense/expensereports?format=fields&organizationId={id} |
| Update report with Fields | PUT | /v1/expense/expensereports/{expenseReportId}?format=fields |
| Create report with JSON | POST | /v1/expense/expensereports |
| Update report with JSON | PUT | /v1/expense/expensereports/{expenseReportId} |
| Submit report | PUT | /v1/expense/expensereports/{expenseReportId}?action=send |
| Delete report | DELETE | /v1/expense/expensereports/{expenseReportId} |
| Initialize report fields | GET | /v1/expense/me/organizations/{id}/expensereports/fields |
Step 1: List reports
List reports for an organization by processStatus:
curl -X GET "https://stage-api.findity.com/api/v1/expense/expensereports?organizationId={orgId}&processStatus=DRAFT&include=meta.abbreviation,meta.capabilities,expenseRecords" \
-H "Authorization: Bearer {access_token}"Use this to build report tabs such as Draft, Submitted, Approved, and Rejected.
Common include values:
| Include | Description |
|---|---|
meta.abbreviation | Pre-formatted display values for list views |
meta.capabilities | Available user actions, such as whether the report can be edited, deleted, or submitted |
expenseRecords | Included expenses |
expenseRecords.meta.abbreviation | Pre-formatted display values for included expenses |
meta.violations | Report-level validation or policy issues |
meta.approval | Approval-related metadata |
Step 2: Initialize report fields
Use the report fields endpoint when your application renders the report form dynamically:
curl -X GET "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensereports/fields" \
-H "Authorization: Bearer {access_token}"To edit an existing report, pass the report ID:
curl -X GET "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensereports/fields?expenseReportId={expenseReportId}" \
-H "Authorization: Bearer {access_token}"The response contains fields such as:
| Field property | controlType | Description |
|---|---|---|
id | TEXT | Report ID (hidden, system field) |
name | TEXT | Report name |
description | MULTI_LINE_TEXT | Report description or comment |
recipientList | RECIPIENT_LIST | Optional email recipients |
expenseRecords | LIST | Expenses included in the report. Usually multi-select. |
| Custom dimension fields | LIST or TEXT | Organization-specific report-level dimensions |
previewURL | URL | Preview link for the report, when available |
Always send the complete fields array when updating report fields — including hidden fields and fields the user did not modify.
Step 3: Add expenses to a report
A report groups expense records by ID. In a Fields-based UI, users typically select expenses through the expenseRecords field. In JSON format, you provide the expense record IDs directly.
To list expenses that can be added to a report, use the canBeAddedToReport filter:
curl -X GET "https://stage-api.findity.com/api/v1/expense/expenses?organizationId={orgId}&filter=canBeAddedToReport&include=meta.abbreviation,meta.capabilities" \
-H "Authorization: Bearer {access_token}"JSON example
curl -X POST "https://stage-api.findity.com/api/v1/expense/expensereports" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"organizationId": "ff808181963979e20196397a2098004b",
"name": "March expenses",
"comment": "Expenses from March customer visits",
"expenseRecords": [
{ "id": "expense-record-id-1" },
{ "id": "expense-record-id-2" }
]
}'Fields example
curl -X POST "https://stage-api.findity.com/api/v1/expense/expensereports?format=fields&organizationId={orgId}" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{ "fields": [...complete report fields array...] }'Step 4: Manage report lifecycle
Use meta.capabilities to decide which actions to show in your UI. Capabilities may change based on report status, organization settings, and whether the report contains validation errors.
Common capabilities include:
| Capability | Description |
|---|---|
canBeEdited | The report can be edited |
canBeDeleted | The report can be deleted |
canBeSentIn | The report can be submitted |
canBeRetracted | The report can be retracted from approval, if supported by the current workflow state |
canAddExpenses | Expenses can be added to the report |
canRemoveExpenses | Expenses can be removed from the report |
Update a report
Using Fields:
curl -X PUT "https://stage-api.findity.com/api/v1/expense/expensereports/{expenseReportId}?format=fields" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{ "fields": [...complete report fields array...] }'Using JSON:
curl -X PUT "https://stage-api.findity.com/api/v1/expense/expensereports/{expenseReportId}" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated March expenses",
"comment": "Updated after review",
"expenseRecords": [
{ "id": "expense-record-id-1" },
{ "id": "expense-record-id-2" }
]
}'Delete a draft report
curl -X DELETE "https://stage-api.findity.com/api/v1/expense/expensereports/{expenseReportId}" \
-H "Authorization: Bearer {access_token}"Step 5: Submit for approval
Submit the report when it is complete:
curl -X PUT "https://stage-api.findity.com/api/v1/expense/expensereports/{expenseReportId}?action=send" \
-H "Authorization: Bearer {access_token}"Do not send a request body when using
action=send. The API returns400 BODY_NOT_ALLOWEDif the submit request includes a body.
After submission, the report enters the approval workflow configured for the organization. The report status typically changes to APPROVAL, and approvers can review, approve, or reject the included expenses.
Check
meta.capabilities.canBeSentInbefore showing a submit button. If submission fails, the API may return validation errors that explain which expense or report field must be corrected.
Retract a submitted report
If the workflow state allows it, retract a submitted report from approval:
curl -X PUT "https://stage-api.findity.com/api/v1/expense/expensereports/{expenseReportId}?action=retract" \
-H "Authorization: Bearer {access_token}"Only show this action when meta.capabilities.canBeRetracted is true. Retracting a report returns it from the approval flow so the user can make changes before submitting it again.
Best practices
Prefer Fields for report forms
Use Dynamic Fields when users create or edit reports in your application. Report-level custom dimensions, recipient fields, and expense selection rules can vary by organization, and Fields keeps your UI aligned with those settings.
Use processStatus for navigation
Build report tabs using processStatus instead of maintaining your own status grouping. For example, use DRAFT for editable reports, PROCESSING for submitted reports, PROCESSED for completed reports, and REJECTED for rejected reports.
Use meta.abbreviation for list views
meta.abbreviation contains formatted values for dates, amounts, and labels. Use these values in report lists to match Findity's formatting and localization.
Handle rejected reports clearly
When a report is rejected, show the rejection reason and let the user edit the report or included expenses if capabilities allow it. Re-fetch the report fields before editing so you display the latest validation state.
Updated 3 days ago
