Every finance manager has a folder they don't talk about.
A quiet accumulation of receipt photos, Slack forwards, and email attachments with subjects like "pls reimburse ty." It grows a little every week, an it never shrinks on its own.
Here's how to stop feeding that folder, with a scan to bank transfer automated workflow.
The workflow
Employee submits a receipt → Veryfi extracts the data → Slack sends the manager an approve/reject message → QuickBooks logs the expense → Wise transfers the reimbursement.
API #1 — Veryfi (receipt OCR)
Veryfi takes a receipt image or PDF and returns structured JSON in seconds: vendor name, date, total amount, line items, currency, and tax.
It's pre-trained on hundreds of millions of receipts and works across 38 languages and 91 currencies.
No model training required on your end.
POST https://api.veryfi.com/api/v8/partner/documents/
Headers:
CLIENT-ID: your_client_id
AUTHORIZATION: apikey your_username:your_api_key
Content-Type: application/json
{
"file_url": "https://your-storage.com/receipts/receipt-001.jpg",
"tags": ["expense", "reimbursement"],
"categories": ["Meals", "Travel", "Office Supplies"]
}
The response gives you total, vendor.name, date, currency_code, and a full line_items array. All of that feeds into the Slack message in the next step.
API #2 — Slack (manager approval)
Rather than routing approvals through email, you send the manager an interactive Slack message using Block Kit - Slack's UI framework for composing messages with buttons and structured data.
The manager sees the receipt details and clicks Approve or Reject directly in Slack.
POST https://slack.com/api/chat.postMessage
Headers:
Authorization: Bearer xoxb-your-bot-token
Content-Type: application/json
{
"channel": "manager-slack-user-id",
"text": "New expense reimbursement request",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*New expense request*\n*Employee:* John Doe\n*Vendor:* Marriott\n*Amount:* USD 189.00\n*Date:* 2025-03-10"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "Approve" },
"style": "primary",
"action_id": "approve_expense",
"value": "expense_id_123"
},
{
"type": "button",
"text": { "type": "plain_text", "text": "Reject" },
"style": "danger",
"action_id": "reject_expense",
"value": "expense_id_123"
}
]
}
]
}
When the manager clicks a button, Slack sends an interaction payload to your app's endpoint with the action_id and value. You use that to trigger the next step.
Tips: You'll need to enable Interactivity in your Slack app settings and provide a Request URL — that's the endpoint your app exposes to receive button click payloads. Test this locally first using a tunnel like ngrok before deploying.
API #3 — QuickBooks (accounting sync)
Once approved, you log the expense in QuickBooks Online via the Purchase endpoint. This creates a record in the books against the right account and employee.
POST https://quickbooks.api.intuit.com/v3/company/{realmId}/purchase
Headers:
Authorization: Bearer your_oauth2_access_token
Content-Type: application/json
Accept: application/json
{
"PaymentType": "Cash",
"AccountRef": { "value": "35", "name": "Checking" },
"EntityRef": { "value": "employee_id", "type": "Employee" },
"TotalAmt": 189.00,
"Line": [
{
"Amount": 189.00,
"DetailType": "AccountBasedExpenseLineDetail",
"AccountBasedExpenseLineDetail": {
"AccountRef": { "value": "7", "name": "Travel" }
}
}
]
}
API #4 — Wise (reimbursement payout)
Wise handles the actual bank transfer to the employee.
It's API-first, uses the mid-market exchange rate with a flat transparent fee, and works for both domestic and international payouts across 40+ currencies.
The payout flow is three calls: create a quote, create the transfer, then fund it.
# Step 1 — Create a quote
POST https://api.wise.com/v3/profiles/{profileId}/quotes
{
"sourceCurrency": "USD",
"targetCurrency": "USD",
"sourceAmount": 189.00,
"targetAccount": "<recipient_account_id>"
}
# Step 2 — Create the transfer
POST https://api.wise.com/v1/transfers
{
"targetAccount": "<recipient_account_id>",
"quoteUuid": "<quote_id_from_step_1>",
"customerTransactionId": "expense_id_123",
"details": { "reference": "Expense reimbursement — March 2025" }
}
# Step 3 — Fund the transfer
POST https://api.wise.com/v3/profiles/{profileId}/transfers/{transferId}/payments
{
"type": "BALANCE"
}
Piecing things together
Your app receives the receipt, calls Veryfi to extract the data, formats it into a Slack Block Kit message, and waits for the manager's response.
On approval, it logs the expense in QuickBooks and triggers the Wise payout.
The whole chain from submission to transfer initiation runs without anyone opening a spreadsheet.
Final note: What this doesn't cover
Receipt policy enforcement: flagging expenses that exceed per-category limits, and multi-level approval chains are not covered here.
Those are logic layers you can add on top of the Slack interaction step, no additional APIs needed.

Top comments (0)