Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
---
title: Automate User Provisioning in Expensify with Okta Workflows
description: Set up Okta Workflows with Expensify’s API to automatically provision, update, and deprovision users.
keywords: Okta Workflows, Expensify API, user provisioning, deprovisioning, Advanced Employee Updater, automate onboarding, SSO, identity management
---

<div id="new-expensify" markdown="1">

# Automate User Provisioning in Expensify with Okta Workflows

Set up Okta Workflows with Expensify’s Advanced Employee Updater API to automate user provisioning, updates, and deprovisioning — no manual entry required.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Missing breadcrumb path below the H1 heading. Add a breadcrumb navigation path (e.g., "Settings > Integrations > API") to help users understand where this feature is located in the Expensify interface.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Missing breadcrumb navigation path below the H1 heading. Add a breadcrumb like "Settings > Domains > [Domain Name] > Integrations" or the appropriate navigation path to help users and AI understand where this feature is located in Expensify.


---

## Who can use the Advanced Employee Updater API with Okta Workflows

- **Domain Admins** in Expensify
- **Okta Admins** with Workflow Builder access

---

## Where to find your Expensify API credentials

### Web
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Structure issue: Missing breadcrumb path. Add a breadcrumb navigation path below the H1 heading (e.g., "Settings > Integrations > API") to help users understand their location in the product.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing breadcrumb path: Add a breadcrumb path below the H1 heading (line 9) to show the navigation path, such as "Settings > Integrations > Advanced Employee Updater API" to help users locate these features.

1. While logged into your Expensify account, visit the [**Integrations Center**](https://www.expensify.com/tools/integrations/).
2. Click **Generate API credentials**.
3. Copy your **partnerUserID** and **partnerUserSecret**.
4. Store these securely — these credentials will be used in your Okta workflow.

---

## What the Okta Workflows integration with Expensify does

Expensify’s native Okta integration handles authentication and SSO, but does **not** provision or update users. Use Okta Workflows with the Advanced Employee Updater API for user provisioning and updates.

With this setup, you can:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference "With this setup" lacks clear context. Consider "With the Okta Workflows and Expensify API integration" for better clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference - "this setup" is unclear. Change to "With Okta Workflows and the Advanced Employee Updater API, you can:"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference "With this setup" lacks clear context. Consider rewording to: "With Okta Workflows and Expensify's API, you can:"

- Provision users into specific Workspaces (formerly policies)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Use "Workspaces" instead of "Workspaces (formerly policies)" to match current Expensify standards. The "(formerly policies)" clarification is unnecessary as we've moved away from the old terminology.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Use 'Workspaces' instead of 'Workspaces (formerly policies)' to match current Expensify standards. The parenthetical note is unnecessary since the help docs should use current terminology.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspace" consistently instead of "Workspaces (formerly policies)" - the parenthetical clarification is unnecessary and creates inconsistency with current terminology standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Use 'Workspaces' instead of 'Workspaces (formerly policies)'. The parenthetical reference to the old terminology is unnecessary and potentially confusing. Simply use 'Workspaces' throughout the document.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify style violation: Use "Workspace" instead of "Workspaces (formerly policies)" - the parenthetical explanation is unnecessary and can confuse users. Simply use "Workspace" throughout the document.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspaces" instead of "Workspaces (formerly policies)" to follow current Expensify terminology standards. The parenthetical explanation is unnecessary and adds clutter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dupe

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: "Workspaces (formerly policies)" is inconsistent with Expensify's current terminology. Use "Workspaces" consistently throughout the document without the parenthetical reference to the old term.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Use "Workspaces" consistently instead of "Workspaces (formerly policies)" to match current Expensify terminology. The parenthetical reference to "policies" is unnecessary and confusing.

- Assign domain groups and managers
- Deprovision terminated employees
- Update names, email addresses, and more

---

## How to configure Okta Workflows with Expensify

### 1. Build the trigger

In **Okta Workflows**, create a new flow:
- Trigger: **User Created** or **User Assigned to Application**

---

### 2. Retrieve workspace policy IDs from Expensify

Use this API request to retrieve a list of policy IDs tied to your domain:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change "policy IDs" to "Workspace IDs" to match current Expensify terminology and maintain consistency throughout the document.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspace IDs" instead of "policy IDs" to maintain consistent terminology with current Expensify standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change "policy IDs" to "Workspace IDs" throughout the content to match current Expensify terminology.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change 'policy IDs' to 'workspace IDs' to maintain consistency with Expensify terminology standards.


```json
{
"type": "get",
"credentials": {
"partnerUserID": "your_partnerUserID",
"partnerUserSecret": "your_partnerUserSecret"
},
"inputSettings": {
"type": "policyList"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change "policyList" to match current Expensify terminology. This should reference "workspaces" or "workspaceList" if that's the correct API parameter.

}
}
```

We recommend using Postman or Insomnia to run this API request once, then store the results in an **Assign** card.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspace IDs" instead of "policy IDs" to maintain consistent terminology with current Expensify standards.

![Assign and Construct cards showing credentials setup]({{site.url}}/assets/images/okta-assign-construct.png){:width="100%"}
*Use an Assign card to store your Expensify credentials and policy IDs once for reuse throughout the workflow.*

---

## How to create a user in Expensify using Okta Workflows API

To create or update a user, your API request must follow Expensify’s required structure. Here's what your API request payload should include in the `requestJobDescription` parameter:

```json
{
"type": "update",
"credentials": {
"partnerUserID": "your_partnerUserID",
"partnerUserSecret": "your_partnerUserSecret"
},
"inputSettings": {
"type": "employees",
"entity": "generic",
"data": [
{
"employeeEmail": "[email protected]",
"managerEmail": "[email protected]",
"policyID": "your_policy_id",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change "policyID" to "workspaceID" to match current Expensify terminology. This should be consistent throughout all code examples.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "workspaceID" instead of "policyID" to maintain consistent terminology with current Expensify standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change "policyID" to "workspaceID" to match current Expensify terminology throughout the JSON examples and documentation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change 'policyID' to 'workspaceID' to maintain consistency with Expensify terminology standards.

"employeeID": "unique_employee_id",
"firstName": "First",
"lastName": "Last",
"isTerminated": false
}
]
},
"onFinish": {
"immediateResponse": true
}
}
```

---

## End-to-end workflow example

Here's how the Okta Workflows cards work together to create users in Expensify:

1. **Trigger**
Use **User Created** or **User Assigned to App**.

2. **Retrieve user profile**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting violation: Use "Read User" and "Get Profile" without bold formatting since these are Okta-specific technical terms, not Expensify features. Bold should only be used for Expensify UI elements and features.

Use a **Read User** or **Get Profile** card to fetch the employee’s details.

3. **Lookup policy**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: The heading "Lookup policy" should be "Lookup Workspace" to match current Expensify terminology and maintain consistency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: The phrase "If your company uses multiple Workspaces, use a Lookup card to determine the correct policyID" contains vague references. Change "policyID" to "workspaceID" for consistency and clarity.

(Optional) If your company uses multiple Workspaces, use a **Lookup** card to determine the correct `policyID`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Use "Workspaces" instead of "Workspaces" for consistency with current Expensify terminology standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspace" instead of "Workspaces" for consistency with Expensify terminology standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change "correct policyID" to "correct workspaceID" to match current Expensify terminology.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify style violation: Use "Workspace" instead of "Workspaces" consistently. The text should read "If your company uses multiple Workspaces" for consistency with Expensify terminology.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology and formatting violation: Change "use a Lookup card to determine the correct policyID" to "use a Lookup card to determine the correct workspaceID" - remove bold formatting from Okta terms and update terminology.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Change 'policyID' to 'workspaceID' to maintain consistency with Expensify terminology standards.


![Read, Lookup, and Assign cards for policy mapping]({{site.url}}/assets/images/okta-lookup.png){:width="100%"}
*Use Lookup logic to assign employees to the correct Workspace based on their cost center.*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspace" instead of "Workspaces" for consistency with Expensify terminology standards.


4. **Build credentials and payload**
Use **Assign**, **Construct**, or **Object** cards to:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting violation: Remove bold formatting from "Assign", "Construct", and "Object" as these are Okta-specific technical terms, not Expensify features. Bold should only be used for Expensify UI elements.

- Store your API credentials
- Format `inputSettings`

![Construct card for inputSettings block]({{site.url}}/assets/images/okta-construct4.png){:width="100%"}
*Create a reusable inputSettings object for all your user-related API calls.*

- Construct the `data` array with employee fields

![Construct and Compose cards building employee data]({{site.url}}/assets/images/okta-construct-compose.png){:width="100%"}
*Use Construct and Compose cards to format the employee data into the required API structure.*

- Add an onFinish email notification (optional)

![Construct card for onFinish email notification]({{site.url}}/assets/images/okta-construct3.png){:width="100%"}
*Use onFinish to trigger a follow-up action like notifying a manager after provisioning completes.*

5. **Create the full request**

![Construct card for requestJobDescription]({{site.url}}/assets/images/okta-construct2.png){:width="100%"}
*Build your requestJobDescription object to define the API call details.*

![Compose card referencing requestJobDescription]({{site.url}}/assets/images/okta-request-compose.png){:width="100%"}
*Connect your Constructed request to the Compose card to pass into the API request.*

6. **Set headers**

![Construct card for headers]({{site.url}}/assets/images/Okta-object-construct.png){:width="100%"}
*Set headers for your API call, including content type and accepted format.*

7. **Send the API request**
Use **Raw Request** to send the `POST` to:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting violation: Remove bold formatting from "Raw Request" as this is an Okta-specific technical term, not an Expensify feature. Use regular text formatting for third-party tool references.

```
https://integrations.expensify.com/Integration-Server/ExpensifyIntegrations
```

![API Connector Raw Request card setup]({{site.url}}/assets/images/Okta-request1.png){:width="100%"}
*Use the Raw Request card to POST the formatted data to Expensify’s API.*

8. **Handle the response**
Use **Parse JSON** to extract the `responseCode`, and use **Return Error If** to catch failures.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting violation: Remove bold formatting from "Parse JSON" and "Return Error If" as these are Okta-specific technical terms, not Expensify features.


![Parse and Return Error If cards for responseCode]({{site.url}}/assets/images/okta-error-handling.png){:width="100%"}
*Use Parse and Return Error If cards to handle failures returned by Expensify’s API.*

---

## Common use cases for Okta Workflows with Expensify user provisioning

This Okta Workflows integration guide reflects common customer workflows, such as:

- Auto-provisioning employees into Workspaces at onboarding
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology violation: Use "Workspaces" instead of "Workspaces" for consistency. Remove any remaining references to policies to maintain current terminology standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify Style violation: Use "Workspace" instead of "Workspaces" for consistency with Expensify terminology standards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expensify style violation: Use "Workspace" instead of "Workspaces" consistently. The text should read "Auto-provisioning employees into Workspace at onboarding" for consistency with Expensify terminology.

- Assigning managers and domain groups based on profile fields
- Deprovisioning users when removed from an Okta group
- Updating names and emails during employment changes

If your setup differs or you’ve found another way to use this integration, we’d love to hear from you. Reach out to Concierge with feedback or [recommend a change to this article](https://github.com/Expensify/App/edit/main/docs/articles/Unlisted/Automate-User-Provisioning-in-Expensify-with-Okta-Workflows.md) to help expand the use cases we cover.

---

# FAQ
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Wrong heading level. Change "# FAQ" to "## FAQ" to maintain proper heading hierarchy. According to HelpDot guidelines, avoid using ### or deeper heading levels and prefer # or ## structure for better AI parsing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heading level violation: The FAQ section uses "# FAQ" (H1) which should be "## FAQ" (H2) to maintain proper heading hierarchy. The main title is already H1, so FAQ should be H2.


## Can I use this to update existing users?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: FAQ question "Can I use this to update existing users?" uses vague reference "this". Consider: "Can I use the Advanced Employee Updater API to update existing users?" for better clarity.


Yes. Set `"type": "update"` — the API will either update or create the user depending on whether they already exist.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability violation: The answer "Yes. Set "type": "update" — the API will either update or create the user depending on whether they already exist." uses an em dash unnecessarily. Consider: "Yes. Set "type": "update" and the API will either update or create the user depending on whether they already exist."


## Can I test the flow without creating users?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability violation: "Yes. Set "dry-run": true in the request payload to simulate the call without applying changes." - This instruction lacks context about where exactly to place this parameter. Consider clarifying: "Yes. Add "dry-run": true to the top level of your API request payload to simulate the call without applying changes."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability violation: The phrase "Set \"dry-run\": true in the request payload" uses inconsistent formatting. Consider rephrasing to "Add \"dry-run\": true to your request payload" for better flow and clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: FAQ question "Can I test the flow without creating users?" uses vague reference "the flow". Consider: "Can I test the Okta Workflow without creating users?" for better specificity.


Yes. Set `"dry-run": true` in the request payload to simulate the call without applying changes.

## What happens if the API request contains invalid data?

The API response will include a `responseCode` and `responseMessage`. Handle this using error-checking logic in your flow.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference "this" in "Handle this using error-checking logic" lacks specificity. Should be: "Handle API errors using error-checking logic in your flow."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference - "this" without clear context. Change to "Handle this API response using error-checking logic in your flow."


## How often can I run this flow?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: FAQ question "How often can I run this flow?" uses vague reference "this flow". Consider: "How often can I run the Okta Workflow for user provisioning?" for better clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference "this flow" lacks context since multiple flows are discussed. Consider: "How often can I run the provisioning workflow?" for clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Readiness violation: Vague reference - "this flow" without clear context. Change to "How often can I run this Okta workflow?" to be more specific.


Expensify enforces API rate limits. Avoid sending excessive requests in a short period. Batching users can help reduce the load.

## Does Expensify support SCIM-based provisioning?

No. Expensify does **not** support SCIM-based user provisioning. However, we do support SCIM-based deprovisioning for customers using Okta. To learn more, see [Okta SCIM API for User Deactivation](https://help.expensify.com/articles/expensify-classic/domains/Managing-Single-Sign-On-(SSO)-in-Expensify#:~:text=Advanced%20Configurations-,Okta%20SCIM%20API%20for%20User%20Deactivation,-Ensure%20your%20domain).


---

## Resources

- [Expensify Advanced Employee Updater API Docs](https://integrations.expensify.com/Integration-Server/doc/employeeUpdater/)
- [Okta Workflows Documentation](https://help.okta.com/)
- [Expensify API Explorer](https://integrations.expensify.com/Integration-Server/doc/)

</div>
Binary file added docs/assets/images/Okta-object-construct.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/Okta-request1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-assign-construct.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-construct-compose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-construct2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-construct3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-construct4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-error-handling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-lookup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/okta-request-compose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading