Skip to main content
Send card-purchase events into Findity to auto-generate expenses for cardholders. This guide covers the partner-side integration for card issuers — banks, fintechs, and Card-as-a-Service platforms — that want to embed Findity’s expense management. You’ll onboard a customer with a one-time setup call, then stream card transactions so each purchase becomes an expense in the cardholder’s app, ready for receipt capture and approval.

Overview

A card-issuer integration has two phases — a one-time customer onboarding flow and a continuous transaction stream. The layers below sit between your existing card-issuing platform and the Findity expense engine:
Onboarding runs once per customer (creating the organization, the cardholders, and at least one administrator). After that, every card authorization and every settlement on a connected card flows through a single POST /cardtransactions call. Transactions are processed asynchronously by default — the endpoint returns 202 Accepted immediately and queues the transaction for processing. The closer to real-time you send them, the better the cardholder experience — expenses appear in the app within seconds of purchase.

Prerequisites

  1. Have Findity configure your cardType value. Contact your project manager or Findity support before development begins — cardType must match a value the backend recognises, otherwise every transaction returns 400.
  2. Complete Authentication and have an admin-scoped access token. The same token is used for onboarding calls (Admin API) and transaction calls (Connect API).
  3. Decide which liability each card type you issue carries: PRIVATE, CORPORATE, or DEBET. This is not a per-transaction choice — it’s tied to the card and dictates how Findity treats the resulting expenses. See Key concepts below.

Key concepts

API endpoints

Base URL for all examples in this guide:
Use the matching production host (https://expense.findity.com) only after your integration is verified in stage.

Create customer organization

See the Admin API — Organizations guide for full request and response details.

Create cardholder or administrator

See the Admin API — Users guide for full request and response details.

Submit card transaction

This is the primary endpoint for this integration — used for all transaction lifecycle events.

Required headers

Customer onboarding

When a customer signs up to use Findity through your card-issuing platform — typically from a “My Pages” or equivalent surface — your adapter makes three sequential calls to provision the customer in Findity.
After these three calls succeed, the customer’s organization is provisioned, its cardholders exist as users, and there is at least one administrator who can sign in to the Findity admin web client. The administrator is who reviews corporate-card invoices, runs reports, and configures expense categories. The administrator does not need to be a cardholder, and a cardholder may also be made an administrator — set admin: true on the user object. See the Organizations and Users guides for the full request and response shape of these calls.
The organizationId and personId values returned by these onboarding calls are what you’ll pass into every subsequent POST /cardtransactions call. Store them in your adapter, keyed by your own customer and cardholder ids.

Add card to user

A user becomes a cardholder when a card is linked to their account. An employee can hold multiple cards (for example, a personal-liability card for travel plus a corporate-liability card for office purchases), but most integrations connect one card per cardholder. The card’s liability setting dictates how Findity treats the expenses generated from it. Pick the right value when the card is provisioned — changing it later requires migration.
The cardholder’s user must exist in the organization (created in the onboarding step) before any transaction can be associated with them. A transaction with an unknown personId returns 400.

Integration steps

After onboarding, your adapter spends most of its time on a single endpoint — POST /api/v1/connect/cardtransactions — with the eventType field driving the behaviour. The four steps below cover the full transaction lifecycle. Steps 1 and 3 fire on every successful transaction; steps 2 and 4 are conditional. Reuse the same transactionId across all events that belong to one purchase so Findity can stitch them together.

Step 1 — Send the authorization

When the card scheme approves a purchase, send an AUTHORIZATION_ACCEPTED event so Findity creates the draft expense and notifies the cardholder via the mobile app. Generate a fresh transactionId here and reuse it on every subsequent event for this purchase.
Optional pre-step — pre-authorization. For flows where the final amount isn’t known yet (e.g. fuel pumps, hotel holds), send PRE_AUTHORIZATION first. Findity creates a draft expense that’s hidden from the cardholder. Replay the same transactionId with AUTHORIZATION_ACCEPTED once the final amount is confirmed; the existing draft is updated and the cardholder is notified.
See Generate expenses from card transaction for the full request body, the required fields, and a worked cURL example.

Step 2 — Reverse or reject (if applicable)

If the card scheme cancels the authorization before settlement, or rejects it outright, replay the same transactionId with the matching eventType.
Findity reduces the amount on AUTHORIZATION_REVERSAL and removes the draft expense entirely on AUTHORIZATION_REJECTED. After either event, the lifecycle is closed for this transactionId and no further events (except REFUND after a settled CAPTURE) are accepted.

Step 3 — Capture on settlement

When the transaction settles (the funds actually move from the cardholder’s account), send a CAPTURE event with the same transactionId. For CORPORATE-liability cards, include an invoiceNumber — Findity groups all transactions sharing the same invoiceNumber into a single corporate-card report that the cardholder submits as one batch.
CAPTURE finalises the expense amount. If the cardholder hasn’t yet attached a receipt, they’re prompted to do so at this point. See Invoice matching for the full grouping behaviour.

Step 4 — Process refunds (if applicable)

When a refund clears for a previously captured transaction, send a REFUND event using the same transactionId. Findity records the negative amount on the original expense and preserves the audit trail — the cardholder can see both the original purchase and the refund in their report.
For partial refunds, send the partial amount; Findity adjusts the net total accordingly. For full refunds, send the full original amount as billingAmount — do not negate the value, the negation is implicit from eventType: REFUND.
The whole lifecycle uses a single endpoint with the same body shape — only eventType and the relevant amount fields change. Build one transport function in your adapter and switch on eventType at the boundary.

Generate expenses from card transaction

For each purchase made on a connected card, your adapter sends a POST /cardtransactions request. Findity creates a draft expense for the cardholder, sends them a push notification through the Findity mobile app, and lets them attach a receipt and submit it for approval. The same endpoint is used for the full transaction lifecycle — initial authorization, optional reversal, settlement (CAPTURE), and refund — by varying the eventType field and reusing the same transactionId.

Request body — required fields

Request body — conditionally required fields

These fields are required depending on your card type and how the cardholder is identified:
Cardholder identification: You must provide either organizationId + personId, or organizationId + employeeId. If the card is already registered in Findity (via a previous transaction), the system can also look up the cardholder by supplierCardId alone.

Request body — optional fields

Example request

cURL

Example response

By default, transactions are processed asynchronously. A successful call returns 202 Accepted with the request body echoed back, indicating the transaction has been queued for processing. Async response (default):
Sync response (with ?async=false): For integration testing, you can add ?async=false to process the transaction synchronously. This returns 201 Created with the stored transaction(s), including the Findity-assigned id and expenseRecordId:
Production note: Do not use ?async=false in production — it may cause issues with simultaneous requests. Use it only for integration testing.
Send AUTHORIZATION_ACCEPTED as close to real time as your card scheme allows — typically within a few seconds of the authorization clearing. The cardholder’s push notification is generated when Findity processes the event, so any delay translates directly into a worse user experience.

Invoice matching

For CORPORATE-liability cards, the cardholder cannot submit individual expenses — purchases are invoiced to the employer monthly (or whatever your billing cycle is) and must be grouped to match the invoice. This is what invoiceNumber is for. The flow:
  1. During the month, you send AUTHORIZATION_ACCEPTED events for each purchase. Findity creates draft expenses; the cardholder attaches receipts but cannot submit yet.
  2. When your card scheme settles a batch and issues an invoice, you replay each affected transaction with eventType: CAPTURE, the same transactionId as the original authorization, and the new invoiceNumber.
  3. Findity matches the CAPTURE event to the original draft by transactionId, updates the expense with the final amount, and groups all expenses sharing the same invoiceNumber into one corporate-card report.
  4. The cardholder submits the resulting report. The administrator sees an overview of open corporate-card reports and can send reminders to cardholders who haven’t yet submitted.

Example CAPTURE request

cURL
You can update the same transactionId multiple times — for example, an AUTHORIZATION_REVERSAL followed by a CAPTURE for the corrected amount. Always send the same transactionId across the lifecycle so Findity can stitch the events together.

Transaction lifecycle

Each transaction progresses through a lifecycle of events. The eventType field indicates the current stage:

Event type behavior

Capture timeout

If a CAPTURE event is not received within a configured timeout period (set per cardType), Findity automatically removes the draft expense. This prevents orphaned expenses from purchases that were never settled.

Airline/travel accumulation

For airline and travel merchants (MCC codes 3005, 3010, 3020, 3030, 3031, 3041, 4511), multiple CAPTURE events with the same transactionId are accumulated onto the existing expense rather than creating duplicates. This handles the common pattern where airlines send multiple settlement records for a single booking.

Error handling

Findity returns a JSON envelope on errors:

Validation errors (400)

Authentication errors

Other errors

Transaction order errors

Findity enforces transaction lifecycle order. You cannot send an AUTHORIZATION_ACCEPTED, AUTHORIZATION_REVERSAL, or AUTHORIZATION_REJECTED event after a CAPTURE or REFUND has been recorded for the same transactionId. Attempting to do so returns a 400 error with the message “Transactions received in the wrong order”.

Next steps

Last modified on August 31, 2026