Worlds / Finance ops
Expensify API
A local Expensify workspace with expense reports, receipts, categories, tags and approval workflows. Test the approver agent that reviews reports in its inbox and enforces workspace rules.
- Base path
/Integration-Server/ExpensifyIntegrations- Auth
- partnerUserID and partnerUserSecret in the request body, the world key
- Endpoints
- 12
- Status
- Active today
This reference previews the surface the Expensify world serves in the closed beta. Paths mirror the public Expensify API; the exact subset is confirmed when your workflow is scoped.
Connect
The run gives your agent these bindings. Keep your SDK; change only where it sends requests.
| binding | meaning |
|---|---|
WORLDS_EXPENSIFY_URL | This world's origin followed by /Integration-Server/ExpensifyIntegrations |
WORLDS_API_KEY | The world key, accepted wherever Expensify expects a credential |
WORLDS_WORLD_ID | The isolated world's identity |
const base = process.env.WORLDS_EXPENSIFY_URL;
const requestJobDescription = {
type: "get",
credentials: { partnerUserID: "user", partnerUserSecret: process.env.WORLDS_API_KEY },
inputSettings: { type: "combinedReportData", filters: { reportIDList: "R001" } },
};
const res = await fetch(base + "/Integration-Server/ExpensifyIntegrations", {
method: "POST",
body: new URLSearchParams({ requestJobDescription: JSON.stringify(requestJobDescription) }),
});API reference
Reports
Expense reports with status and totals.
- POST
/Integration-Server/ExpensifyIntegrations/ · get combinedReportDataExport reports with expenses - POST
/Integration-Server/ExpensifyIntegrations/ · update reportChange report status - POST
/Integration-Server/ExpensifyIntegrations/ · create reportCreate a report
Fields · 5
reportID | string | Report id |
reportName | string | Report name |
status | string | OPEN, SUBMITTED, APPROVED or REIMBURSED |
total | integer | Total in cents |
accountEmail | string | Owner email |
Expenses
Individual expense lines.
- POST
/Integration-Server/ExpensifyIntegrations/ · create expensesCreate expenses - POST
/Integration-Server/ExpensifyIntegrations/ · update expensesUpdate expenses - POST
/Integration-Server/ExpensifyIntegrations/ · get expensesExport expenses
Fields · 5
transactionID | string | Expense id |
merchant | string | Merchant |
amount | integer | Amount in cents |
category | string | Category |
created | string | Expense date |
Policies
Expense policy settings and categories.
- POST
/Integration-Server/ExpensifyIntegrations/ · get policyListList policies - POST
/Integration-Server/ExpensifyIntegrations/ · get policyGet a policy - POST
/Integration-Server/ExpensifyIntegrations/ · update policyUpdate a policy
Fields · 4
id | string | Policy id |
name | string | Policy name |
type | string | Policy type |
outputCurrency | string | Reporting currency |
Employees
People on a policy.
- POST
/Integration-Server/ExpensifyIntegrations/ · update employeesAdd or update employees - POST
/Integration-Server/ExpensifyIntegrations/ · get employeesList employees - POST
/Integration-Server/ExpensifyIntegrations/ · delete employeesRemove employees from a policy
Fields · 4
employeeEmail | string | |
managerEmail | string | Approver |
role | string | Role |
employeeID | string | Employee id |
Test workflow
- Prepare. Select the Expensify setup for your workflow and review its starting records, including reports, expenses, policies.
- Connect. Configure your agent with this world's URL and key using the SDK example. Check that it reaches the intended API before running a test.
- Define. Describe the task, expected final changes and records that must stay untouched. Keep expected outcomes separate from the agent's instructions.
- Run and inspect. Use the dashboard or your workflow's generated CLI setup. Review final records and changes, then rerun from the same starting setup with the relevant failure conditions. Use Deployment and CI to automate the same workflow.
What to verify
- Austin offsite report approved
- October client visits not approved while a receipt is missing
- Team lunch expense held at $96 for 2 attendees
- Ben Okafor's report not approved with uncategorized expenses
- Every hold has a comment to the submitter
Test file
A task file names the jobs, the policy your agent is given and what the grader reads back from the world's final state. The agent never sees the expected outcomes.
# worlds/tasks.yaml · Expensify
version: 2
connector: expensify
seed: expensify-starter
mode: isolated
policy: >
Work the approval inbox. Approve reports that meet the rules, hold any
single expense that breaks them with a comment, and leave uncategorized
reports for the submitter.
tasks:
- id: approve-or-reject-submitted-reports
prompt: Approve or reject submitted reports
- id: fix-categories-and-tags-on-expenses
prompt: Fix categories and tags on expenses
- id: flag-expenses-that-break-workspace-rules
prompt: Flag expenses that break workspace rules
expected:
- Austin offsite report approved
- October client visits not approved while a receipt is missing
- Team lunch expense held at $96 for 2 attendees
- "Ben Okafor's report not approved with uncategorized expenses"
- Every hold has a comment to the submitter
scenarios:
- job-failed
- rate-limited
- bad-credentialsSee Tasks and outcomes for every field, and Deployment and CI to run the file on every pull request.
Failure conditions
Each one fires before the handler, at the same step on every run.
| condition | what the agent sees |
|---|---|
job-failed | An Integration Server job returns an error for a bad policyID |
rate-limited | Too many requests in a short window are refused |
bad-credentials | partnerUserSecret is rejected after rotation |
export-conflict | A report already exported cannot be edited |
Starting data
Start each run from the same records and relationships. The overview below describes the Expensify starter; use the setup supplied for your workflow when preparing your own snapshot.
| Records | Starting setup |
|---|---|
| reports | 50 across Open, Processing, Approved and Reimbursed |
| expenses | 420 with SmartScanned receipts on 380 |
| categories | 18 synced from the accounting system |
| rules | Receipt required over $75, max $50 per meal per person |
The record shapes below reuse this world's API field definitions. They show illustrative values and placeholders, not an importable seed. API responses and seed input can differ; include all required records and references in the accepted import format for your workflow.
Reports records
Reports
Expense reports with status and totals.
| Field | Type | Meaning / relationship |
|---|---|---|
reportID | string | Report id |
reportName | string | Report name |
status | string | OPEN, SUBMITTED, APPROVED or REIMBURSED |
total | integer | Total in cents |
accountEmail | string | Owner email |
{
"reportID": "<Report id>",
"reportName": "<Report name>",
"status": "<OPEN, SUBMITTED, APPROVED or REIMBURSED>",
"total": 1,
"accountEmail": "person@example.test"
}Expenses records
Expenses
Individual expense lines.
| Field | Type | Meaning / relationship |
|---|---|---|
transactionID | string | Expense id |
merchant | string | Merchant |
amount | integer | Amount in cents |
category | string | Category |
created | string | Expense date |
{
"transactionID": "<Expense id>",
"merchant": "<Merchant>",
"amount": 1,
"category": "<Category>",
"created": "<Expense date>"
}Policies records
Policies
Expense policy settings and categories.
| Field | Type | Meaning / relationship |
|---|---|---|
id | string | Policy id |
name | string | Policy name |
type | string | Policy type |
outputCurrency | string | Reporting currency |
{
"id": "<Policy id>",
"name": "<Policy name>",
"type": "<Policy type>",
"outputCurrency": "<Reporting currency>"
}Employees records
Employees
People on a policy.
| Field | Type | Meaning / relationship |
|---|---|---|
employeeEmail | string | |
managerEmail | string | Approver |
role | string | Role |
employeeID | string | Employee id |
{
"employeeEmail": "person@example.test",
"managerEmail": "person@example.test",
"role": "<Role>",
"employeeID": "<Employee id>"
}