Last updated

Reconciliation

Pull settled transactions into your ledger — and know the defaults that bite.

One endpoint serves both card and travel transactions: POST /v1/cards/transactions. The source field selects which transactions you get and the response shape: cards is your company's regular Jeeves corporate cards; travel is the virtual cards created through this API. This page covers the request model, the date-window defaults, cursor pagination, and migration from the deprecated GET endpoints.

The request model

curl -X POST \
  'https://public-sandbox.tryjeeves.com/v1/cards/transactions' \
  -H "Authorization: Bearer $JEEVES_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "cards",
    "startDate": "2026-09-01",
    "endDate": "2026-09-28"
  }'

Scopes: transactions:read (plus transactions:multiple:read to read across multiple companies under the same parent with one credential).

sourceReturnsRow highlights
cardsSettled transactions from your company's regular Jeeves corporate cardscompany, user, card, merchant, amounts in billing and local currency, settlement date
travelCompleted transactions from virtual cards created via this APIcard metadata (reservation code…), MCC, authorization code, restrictions

Date-window defaults — read this twice

RequestWindow applied
No cardIdsstartDate and endDate both default to yesterday (D-1). A nightly job with no explicit dates naturally pulls yesterday's settlements.
With cardIdsNo default window — you get the full history of those cards unless you set dates explicitly.

startDate must not be after endDate, and neither may be in the future — violations return structured 400 errors naming the failing property.

Cursor pagination

Because this is a POST endpoint, the response's links.next is always null (a request body can't be encoded into a URL). Page forward by re-sending the same filters with pageCursor:

curl -X POST \
  'https://public-sandbox.tryjeeves.com/v1/cards/transactions' \
  -H "Authorization: Bearer $JEEVES_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "cards",
    "startDate": "2026-09-01",
    "endDate": "2026-09-28",
    "pageSize": 25,
    "pageCursor": "MTI7eyJ0cmFuc2FjdGlvbklkIjoi..."
  }'

Loop until pagination.hasNext is false:

request ──► pagination.nextCursor ──► request with pageCursor ──► … ──► hasNext: false

pageSize limits differ by source: up to 50 for source: cards, up to 100 for source: travel.

Payment transactions

Non-card payment transactions have their own read endpoint, GET /v1/payments/transactions, with the same date-range filters and cursor pagination:

curl 'https://public-sandbox.tryjeeves.com/v1/payments/transactions?startDate=2026-09-01%2000:00:00&endDate=2026-09-28%2023:59:59&pageSize=20' \
  -H "Authorization: Bearer $JEEVES_ACCESS_TOKEN"

Push, don't poll

For real-time reconciliation, subscribe to webhooks: transaction.auth.approved and transaction.settled deliver each transaction as it happens, and the nightly POST /v1/cards/transactions pull becomes your reconciliation safety net rather than your primary feed.

Migrating from the deprecated GET endpoints

DeprecatedReplacement
GET /v1/transactionsPOST /v1/cards/transactions with "source": "cards"
GET /v1/travel/transactionsPOST /v1/cards/transactions with "source": "travel"

The GET endpoints still respond, but new integrations should not use them, and existing ones should migrate — same data, one endpoint, one pagination model.