First-party app
Expensify Expensify

Expensify

Create expenses, reports and policies in Expensify, export report data, run card reconciliation, and update policies, tag approvers, expense rules and employees.

stable Finance & AccountingHuman Resources

About

Expensify ships in the w6w first-party pack. It declares 15 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.

App id
io.w6w.expensify
Version
0.1.0
Author
w6w
Licence
MIT
Categories
Finance & Accounting · Human Resources

Overview

Expensify is expense management and reimbursement software. This app drives its Integration Server: it creates expenses, reports, policies and expense rules, reads policies, policy details and domain card lists, exports report data through a Freemarker template and downloads the generated file, and runs card reconciliation exports.

It also updates a policy’s categories, tags and report fields, tag approvers and expense rules, marks approved reports as reimbursed, and provisions policy members through the Advanced Employee Updater.

Every call is one form-encoded job description posted to a single endpoint; the partner credentials are merged into it by the connection’s sign hook, never by an action. Health checks verify the credentials, whether the Integration Server is answering, Expensify’s status page (Integration APIs component), and declare that no rate-limit headroom signal exists.

Build with Expensify

Three routes to the same 15 actions. The Workflow tab is generated from Expensify's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.

Create Expense Rule

create-expense-rule

Create an expense rule for a policy member: expenses they create get the given tag and/or billable default.

Create Expenses

create-expenses

Create expenses in the connected account (or, with advanced permissions, another employee's). Each expense needs merchant, created date, amount in cents and a currency.

Create Policy

create-policy

Create a policy (workspace). Defaults to the team plan.

Create Report

create-report

Create a report containing expenses in a policy. Domain and policy admin only, and the feature must first be enabled for your domain by concierge@expensify.com (otherwise 'Not authorized to authenticate as user').

Download File

download-file

Download a file generated by Export Reports or Run Card Reconciliation. Text formats (csv, txt, json, xml) come back as `content`; binary formats (xlsx, xls, pdf) as `contentBase64`.

Export Reports

export-reports

Generate a file of report and expense data from a Freemarker template, selected by report IDs or a date range. Returns the generated file name — pass it to Download File. Optionally marks the reports as exported and emails a link.

Get Policy Details

get-policy

Fetch categories, report fields, tags, tax rates and/or employees for one or more policies.

List Domain Cards

list-domain-cards

List the company cards assigned at domain level (masked number, owner, bank, last import).

List Policies

list-policies

List the account's policies with name, ID, type, owner, role and currency.

Run Card Reconciliation

run-reconciliation

Export card transactions for a domain and date range through a reconciliation template. Returns the generated file name — download it with Download File using file system `reconciliation`. Domain admin credentials only.

Update Employees

update-employees

Provision and de-provision policy members from an employee feed: invite, set managers and roles, assign domain groups, remove terminated staff. Run with Dry run first.

Update Expense Rule

update-expense-rule

Update an existing expense rule of a policy member by rule ID.

Update Policy

update-policy

Manage a policy's categories, tags and report fields from JSON. Updates one policy, or the same change across several policies. Needs admin rights on the policy.

Mark Reports Reimbursed

update-report-status

Mark Approved reports as Reimbursed, selected by report IDs or a date range. Reports in any other status are skipped. A partial result (207) is returned, not thrown, with the skipped and failed reports listed.

Update Tag Approvers

update-tag-approvers

Route expenses carrying a given tag to a specific approver. Single-level tag lists only. Requires policy admin.

A workflow step names the app and the action, and the editor fills in the connection when you pick one. This is the Step shape from the workflow spec, carrying Expensify's real ids.

{
  "manifestVersion": "2",
  "name": "expensify-example",
  "steps": [
    {
      "id": "create-expense-rule",
      "uses": {
        "app": "io.w6w.expensify",
        "action": "create-expense-rule",
        "connection": "conn_YOUR_CONNECTION_ID"
      },
      "with": {
        "policyID": "<policyID>",
        "employeeEmail": "<employeeEmail>"
      }
    }
  ]
}

Here are some of the things you can do

  • Create Expense Rule

    perform
    create-expense-rule
  • Create Expenses

    perform
    create-expenses
  • Create Policy

    perform
    create-policy
  • Create Report

    perform
    create-report
  • Download File

    read
    download-file

+10 more actions available

Every app-specific value here is a blank you have to fill in. An app action is reached through the connection that authenticates it, so the address is a connection id, not the app id — and connections belong to your account, so a public page cannot know yours. Create one for Expensify, then fill in the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the parameters that action declares. The call itself is real — the shape is transcribed from the studio's own snippet builder, which prints the same kind of blanks — but nothing in it is specific to Expensify. The Workflow tab is where this app's real ids are.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { W6wClient, isActionRun } from "@w6w/sdk";

// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();

const envelope = await client.run({
  urn: "conn_YOUR_CONNECTION_ID",
  action: "create-expense-rule",
  payload: {
    policyID: "<value>",
    employeeEmail: "<value>",
    // tag: "<value>",
    // defaultBillable: "<value>",
  },
});

if (isActionRun(envelope)) console.log(envelope.value);
Install the CLI
npm install -g @w6w/cli
CLI
w6w run conn_YOUR_CONNECTION_ID --action create-expense-rule --payload '{"policyID":"<value>","employeeEmail":"<value>"}'

Give an AI agent Expensify — without giving it Expensify's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.

One tool call
{
  "name": "w6w_invoke",
  "arguments": {
    "ref": "app:io.w6w.expensify#create-expense-rule",
    "input": {
      "policyID": "<policyID>",
      "employeeEmail": "<employeeEmail>"
    }
  }
}

Every tool names its target with a single ref. The app: form above doesn't name a connection at all — the host resolves which of the caller's Expensify connections to sign with, and refuses rather than guesses when the answer is ambiguous.

What the agent gets

Credentials it can't read

The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.

A tool surface scoped to the caller

Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.

A durable workflow in one call

Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.

Health-aware discovery

Expensify's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.

The MCP surface is part of the hosted platform. Expensify itself is MIT, and the runtime that executes it is source-available (FSL).

Request MCP access

Health checks

Expensify declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

Expensify platform status

status.expensify.com (Statuspage v2). The `Integration APIs` component decides; `Report PDFs` is capped at degraded; every other component is detail only.

dependency

Integration Server reachability

Unauthenticated policyList job against integrations.expensify.com. Expensify's `{responseCode, responseMessage}` error envelope is the expected healthy answer; credential validity is the `auth:partner-credentials` check's job.

quota

API request headroom