Users
Manage user profiles, preferences, settings, and account details in the Expense API
Retrieve and manage the authenticated user's profile, preferences, settings, and account details — the starting point for any Expense API integration.
Overview
The Expense API user endpoints operate through the /me context, meaning all operations apply to the currently authenticated user. After authenticating with a user-scoped token (via the authorization_code grant), the /me endpoint is your first call — it returns the user's identity, preferences, and capabilities.
The user context is essential because most Expense API endpoints (expenses, reports, approvals) are scoped to the authenticated user's permissions and organization memberships.
Key concepts
| Concept | Description |
|---|---|
| Person | A unique individual in the Findity system. A person can have multiple users (employees) across multiple organizations |
| Capabilities | The meta.capabilities object indicates system-wide abilities like impersonation and admin access |
| Impersonation | Acting as another user — used by admin tools and support integrations |
| Extra recipients | Additional email addresses that can receive expense-related notifications |
| Counters | Per-organization badge counts for expenses, approvals, notifications, and rejections |
Get current user
Retrieve the authenticated user's profile. This is typically the first call after obtaining a user-scoped access token.
GET /v1/expense/me
Query parameters
| Parameter | Type | Description |
|---|---|---|
include | string | Optional properties: preferences, extraRecipients, meta.capabilities, temporaryApprovers |
Example request
curl -X GET "https://stage-api.findity.com/api/v1/expense/me?include=preferences,meta.capabilities" \
-H "Authorization: Bearer {access_token}"Example response
{
"id": "370e10197a2740dea1f39d21bc9e4a8c",
"email": "[email protected]",
"firstName": "Emma",
"lastName": "Expense",
"mobilePhone": "+4670123456789",
"defaultCurrency": "USD",
"language": "en_US",
"IBAN": "US2138890474392778363181",
"BIC": "ABCDEF123",
"formattingRegion": "sv_SE",
"address": {
"id": "2ee7643987df40b38537b32ccda585d9",
"street1": "132, My Street",
"postalCode": "12401",
"city": "New York",
"countryCode": "US"
},
"meta": {
"capabilities": {
"canImpersonate": false,
"canViewAdmin": false
}
}
}Update current user
Update the authenticated user's profile information.
PUT /v1/expense/me
Example request
curl -X PUT "https://stage-api.findity.com/api/v1/expense/me" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Emma",
"lastName": "Expense",
"defaultCurrency": "SEK",
"language": "sv_SE",
"IBAN": "SE3550000000054910000003",
"BIC": "ESSESESS",
"address": {
"street1": "Sveavägen 10",
"postalCode": "111 57",
"city": "Stockholm",
"countryCode": "SE"
},
"formattingRegion": "sv_SE"
}'Updatable fields
| Field | Type | Description |
|---|---|---|
firstName | string | User's first name |
lastName | string | User's last name |
defaultCurrency | string | Preferred currency code (e.g., SEK, USD, EUR) |
language | string | Language/locale code (e.g., en_US, sv_SE) |
bankAccountNumber | string | Bank account number |
IBAN | string | International bank account number |
BIC | string | Bank identifier code |
formattingRegion | string | Region used for formatting dates and numbers |
address | object | Address with street1, postalCode, city, countryCode |
Action parameter
The PUT /me endpoint also supports an action query parameter instead of a request body:
| Action | Description |
|---|---|
enableSupportAccess | Grants Findity support temporary access to the user's account |
disableSupportAccess | Revokes support access |
PUT /v1/expense/me?action=enableSupportAccess
User settings (fields format)
User settings can also be fetched and updated using the fields format — the same dynamic form system used for expenses. This is useful when building a full settings UI.
Fetch settings
GET /v1/expense/me/settings/fields
Returns a fields structure with grouped settings:
| Field group | Contents |
|---|---|
settings.personalGroup | Name, email, phone, address, password, receipt email |
settings.bankGroup | Bank account, IBAN, BIC |
settings.experienceGroup | Currency, language, formatting region |
settings.appGroup | App theme, camera defaults, prompt preferences |
settings.notificationGroup | Card transaction notifications, email preferences |
temporaryApprovalGroup | Temporary approver assignments |
Update settings
PUT /v1/expense/me?format=fields
Send the full fields structure back with updated values. Fields with requiresUpdate: true trigger server-side recalculation — follow the same update loop pattern described in the Fields system guide.
Counters
Retrieve badge counts across all organizations the user belongs to. Use this to show notification badges in your UI.
GET /v1/expense/me/counters
Example response
{
"meta": { "count": 2, "total": 2 },
"data": [
{
"organizationId": "8ab28c4e6f858814016f8a9bd6b20054",
"expenses": 19,
"approvals": 0,
"rejections": 0,
"notifications": 3,
"transactions": 0,
"inbox": 0
},
{
"organizationId": "8ab28c4f6fd37d39016fd6fee0470003",
"expenses": 10,
"approvals": 11,
"rejections": 0,
"notifications": 0,
"transactions": 0,
"inbox": 0
}
]
}Counter fields
| Field | Description |
|---|---|
expenses | Number of new/draft expenses |
approvals | Number of items pending approval (if user is an approver) |
rejections | Number of recently rejected expenses |
notifications | Number of unread notifications |
transactions | Number of card transactions |
inbox | Number of expenses created via email or card auto-creation |
Profile image
Manage the user's profile picture.
| Operation | Method | Endpoint |
|---|---|---|
| Get profile image | GET | /v1/expense/me/profileimage |
| Upload profile image | PUT | /v1/expense/me/profileimage |
| Delete profile image | DELETE | /v1/expense/me/profileimage |
When uploading, set the Content-Type header to the image format (e.g., image/jpeg, image/png). The request body should be the binary image data.
Email and phone management
Email and phone number changes require a two-step verification process to prevent unauthorized changes.
Change email
- Request a verification code:
curl -X POST "https://stage-api.findity.com/api/v1/expense/me/email?action=change" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]" }'- Verify with the code:
curl -X POST "https://stage-api.findity.com/api/v1/expense/me/email?action=verify" \
-H "Authorization: Bearer {access_token}" \
-H "Content-Type: application/json" \
-d '{ "verificationCode": "123456" }'Change phone number
Follows the same two-step pattern using /v1/expense/me/phone:
POST /me/phone?action=changewith{ "phoneNumber": "+46701234567" }POST /me/phone?action=verifywith{ "verificationCode": "123456" }
To remove a phone number entirely: DELETE /v1/expense/me/phone
Phone numbers must be in international format with a plus-code prefix (e.g.,
+46701234567).
Change password
POST /v1/expense/me/password
Example request
{
"oldPassword": "currentPassword123!",
"newPassword": "newSecurePassword456!"
}A successful response returns new access and refresh tokens, since the password change invalidates the previous session:
{
"expiresIn": 3600,
"accessToken": "eae3a3a225368f247b419e...",
"refreshToken": "59fec24de9f49918f50a31..."
}Passwords must be at least eight characters long with at least one number, one uppercase letter, and one lowercase letter.
After a successful password change, immediately replace your stored access and refresh tokens with the new ones returned in the response. The old tokens are invalidated and will no longer work.
Extra recipients
Extra recipients are additional email addresses that receive expense-related notifications alongside the user's primary email.
| Operation | Method | Endpoint |
|---|---|---|
| List extra recipients | GET | /v1/expense/me/extrarecipients |
| Add extra recipient | POST | /v1/expense/me/extrarecipients?action=add |
| Verify extra recipient | POST | /v1/expense/me/extrarecipients?action=verify |
| Delete extra recipient | DELETE | /v1/expense/me/extrarecipients/{extraRecipientId} |
Each extra recipient has a status of CONFIRMED or NOT_CONFIRMED — they must complete email verification before receiving notifications.
Impersonation
Users with impersonation privileges can search for and act as other users. This is used for admin tools, support scenarios, and delegated expense management.
Search impersonation targets
GET /v1/expense/impersonation/users/search
| Parameter | Type | Description |
|---|---|---|
searchText | string | Free text search across users |
max | integer | Max records to return |
offset | integer | Pagination offset |
sort | string | Sort with order, e.g., firstName:desc,lastName:asc |
Example response
{
"meta": { "total": 2, "count": 2 },
"data": [
{
"personId": "a61fa8a24d9d49f7b75d1874257e044a",
"firstName": "Emma",
"lastName": "Expense",
"email": "[email protected]",
"impersonatorType": "PERSON",
"profilePictureUrl": "https://expense.findity.com/api/v1/expense/profileimage/a61fa..."
}
]
}The impersonatorType indicates the scope of impersonation:
| Type | Description |
|---|---|
PERSON | Can act as the person across all their organizations |
EMPLOYEE | Can act as the person within a specific organization only |
Impersonation requires special permissions. Check
meta.capabilities.canImpersonateon the/meresponse before showing impersonation features in your UI.
Integration best practices
Fetch user context immediately after authentication
Call GET /me?include=meta.capabilities as the first request after obtaining a user-scoped token. This confirms the token is valid, identifies the user, and reveals system-level capabilities like impersonation access.
Use counters for badge notifications
Poll GET /me/counters periodically to update badge counts in your UI. This single endpoint returns counts across all organizations, so you don't need to query each organization separately.
Cache user profile data
User profile data (name, currency, language) changes rarely. Fetch it once at login and store it in your session. Only refresh when the user explicitly edits their profile.
Respect the fields format for settings
When building a settings screen, use the fields format (GET /me/settings/fields) rather than constructing the UI manually. This ensures your settings UI stays in sync with any new settings Findity adds, and handles the requiresUpdate loop for interdependent settings.
Handle verification flows gracefully
Email and phone changes are asynchronous — the user receives a verification code externally. Design your UI to handle the two-step flow: show an input for the verification code after requesting the change, and handle error codes like EXPIRED_VERIFICATION_CODE by prompting the user to request a new code.
Error handling
Common errors when working with user endpoints:
| Status code | Error code | Description |
|---|---|---|
400 | NO_KNOWN_JSON_PROPERTIES | Failed to parse the JSON body. Check your request payload. |
400 | INVALID_JSON_BODY | No known or only read-only properties received. Verify you're sending updatable fields. |
400 | EMAIL_IS_BLANK | Email address is required but was empty. |
400 | INVALID_EMAIL | The provided email address is not valid. |
400 | EMAIL_ALREADY_IN_USE | An account already exists with this email address. |
400 | INVALID_PHONE_NUMBER | The phone number format is invalid. Use international format with plus-code. |
400 | PHONE_NUMBER_ALREADY_USED | The phone number is already associated with another account. |
400 | INVALID_VERIFICATION_CODE | The verification code is incorrect. |
400 | EXPIRED_VERIFICATION_CODE | The verification code has expired. Request a new one. |
400 | PASSWORD_VALIDATION_ERROR | Password doesn't meet requirements (8+ chars, 1 number, 1 uppercase, 1 lowercase). |
400 | INCORRECT_CURRENT_PASSWORD | The current password provided doesn't match. |
404 | ORGANIZATION_NOT_FOUND | Person does not belong to any organization (for counters endpoint). |
Next steps
Updated about 2 hours ago
