Overview
A dimension is a custom field attached to expenses or expense reports that maps to your organization’s accounting structure. Dimensions are fully configurable — there are no fixed categories. The typical lifecycle is: (1) define the dimension, (2) populate its list values if it’s a list type, and (3) optionally assign approvers to specific values so expense routing follows the value chosen. Each dimension has two parts:- A definition — the field’s name, type, and behavior (visible on every expense vs. on the report header, free-text vs. list, auto-filled or not).
- A set of list values — the specific options users can pick from, when the dimension’s
controlTypeis a list.
Prerequisites
- Complete Authentication and obtain an admin-scoped access token.
- Create or identify the customer organization (see Admin API — Organizations) and have its
externalIdready. - Decide which dimensions the organization needs and what list values each one should hold. You can also sync these from your ERP — see Common integration patterns below.
Key concepts
API endpoints
All dimension endpoints use the Admin API base URL. Examples in this guide use the stage environment — switch to the production host (https://expense.findity.com/api/admin) only when you’re ready to go live.
Required headers
Include these on every request:Step 1 — Create or update dimension definitions
Send aPUT with an array of definition objects. The endpoint is an upsert: definitions with an existing externalSourceId are updated, new ones are created.
PUT /organizations/externalid/{externalId}/customdimensions/
Request body — definition fields
cURL
Cost center searchable list auto-filled from the user’s department but overridable, a Project searchable list with no preset, and an Invoice reference free-text field on the report header.
Example response
JSON
Step 2 — Populate list values
Dimensions withcontrolType: LIST_SEARCHABLE need list values for users to select. Send a PUT with the values wrapped in a values array — a bare top-level array will fail with a 400.
PUT /organizations/externalid/{externalId}/customdimensions/{definitionExternalId}/list/
Query parameters
Request body — list value fields
cURL
Website redesign is available only during 2026; Mobile app v2 becomes available from March 2026 onward with no end date; Internal tools has no date restrictions. clearBeforeUpdate=true replaces all existing values with these three.
clearBeforeUpdate=true removes all existing values before inserting. Send your complete value set in a single request — anything not in the payload will be deleted.JSON
listKey for the dimension’s value list and the timestamp of the update. It does not echo the submitted values — to read them back, use the corresponding GET endpoint.
Step 3 — Assign approvers to list values
Assign approvers to specific list values so expense reports route automatically based on the dimension value chosen. Samevalues wrapper as Step 2; each value carries an approvers array.
PUT /organizations/externalid/{externalId}/customdimensions/{definitionExternalId}/list/approvers/
Request body — approver fields
Top-level shape:JSON
The approver must be a real user on the organization. If no user with the supplied
personExternalSourceId
exists, the request returns 400 "failed to update custom field list" and no assignment is created.cURL
Website redesign, and a two-step chain for Mobile app v2: John Doe first, then Carol Park.
Example response
JSON
listKey and an update timestamp. To confirm the assignments persisted and read them back, call the corresponding GET on the same path:
GET /organizations/externalid/{externalId}/customdimensions/{definitionExternalId}/list/approvers/
JSON
Understanding presets
Presets auto-fill dimension values from existing data so users don’t have to pick. The three preset fields work together:
When a preset is configured:
userOverridable: true— auto-filled but the user can change it. Use this when the preset is a sensible default but exceptions are common.userOverridable: false— auto-filled and locked. Use this to enforce accounting rules.visibleIfNoPreset: true— if no preset value exists for the user / department / category, the dimension still appears and the user enters a value manually.visibleIfNoPreset: false— if no preset value exists, the dimension is hidden entirely.
Common integration patterns
Full sync from your ERP. UseclearBeforeUpdate=true to mirror the ERP’s current state exactly — deleted values in the ERP are also removed from Findity. Recommended for nightly batch syncs.
- Fetch dimension definitions from your ERP →
PUT /customdimensions/ - For each list dimension, fetch values from your ERP →
PUT /customdimensions/{definitionExternalId}/list/?clearBeforeUpdate=true - Fetch approver mappings →
PUT /customdimensions/{definitionExternalId}/list/approvers/
clearBeforeUpdate=false to add or update individual values without touching the rest. Send only the changed values in the request body. Useful when a new project is created, a value’s display name changes, or you want to set an endDate to deactivate a value without removing its history.
Multi-organization rollouts. Set cascade=true as a query parameter on the list-values PUT to push the same value set to every sub-organization under the target. Use this when you manage a shared catalogue (cost centers, projects) centrally and want subsidiaries to inherit it.
Error handling
Findity returns a JSON envelope on errors:JSON

