---
title: "Transactions"
description: "Choose the recipe for reading your money movements: reconcile a day, trace one transfer, match a deposit, add up fees, tell why a transfer is stuck and check a sender's limits."
---
Every movement of money on Gravv, such as a payout, a refund, a deposit or a fee, leaves a **transaction row**, the record of that movement in your ledger. These recipes read those rows, and the webhook history beside them, to answer the questions finance and support teams ask every day.

**A money example to keep in mind.** On 12 October you sent three payouts from your USD account: 250 USD to Ada (`completed`), 400 USD to Bayo (`failed`, with a 400 USD `transfer_refund` row that brought the money back) and 120 USD to Kemi (still `pending`). For the day, your books show 250 USD paid, 400 USD that went out and came back, and 120 USD still open.

## Which recipe

| Question | Status | Recipe |
| :-- | :-- | :-- |
| "Do yesterday's movements match our books?" | Available | [Reconcile a day of movements](/recipes/transactions/reconcile-a-day-of-movements) |
| "Where is this transfer, and did our server get every webhook?" | Available | [Trace a transfer and resend a webhook](/recipes/transactions/trace-a-transfer-and-resend-a-webhook) |
| "A client wired us money. Where is it recorded?" | Available | [See a deposit arrive](/recipes/transactions/see-a-deposit-arrive) |
| "What did we pay in fees this month?" | Available | [Add up a month of fees](/recipes/transactions/add-up-a-month-of-fees) |
| "My transfer has said processing for two days" | Available | [Tell why a transfer is stuck](/recipes/transactions/tell-why-a-transfer-is-stuck) |
| "Can this sender send 1,500 USD today?" | Available when your business has a limits policy | [Check what a sender can still send](/recipes/transactions/check-what-a-sender-can-still-send) |
| A statement filtered by date through the API | Not supported. The list has no date filter, so page newest first and stop at the day you want | [Reconcile a day of movements](/recipes/transactions/reconcile-a-day-of-movements) |
| A full CSV export of a day or a month | Not supported. The export holds only the 10 newest matching rows | [Reconcile a day of movements](/recipes/transactions/reconcile-a-day-of-movements) |

## Three ids, three uses

| Id | Where you get it | What it opens |
| :-- | :-- | :-- |
| `transaction_id` | The `POST /v1/transfer` response, or the row's `id` | `GET /v1/transactions/{transaction_id}`; the `transaction_id` filter on webhook history |
| Transfer `reference` | The `POST /v1/transfer` response | `event_data.reference` and `event_group_id` on transfer webhooks; the refund row's `reference`; `POST /v1/transfer/{reference}/resume` |
| Webhook record `id` | `items[].id` from `GET /v1/webhooks/history` | The event detail, its delivery attempts, and a resend |

Save the first two, and your own `client_reference`, for every transfer you send.

## Rules every recipe relies on

- Every request goes to one host, `https://api.gravv.xyz`, with the `Api-Key` header. A key that starts with `grvSec_sandbox_` reads sandbox rows; any other key reads live rows. The two never mix.
- Every read here is a GET with no `Idempotency-Key`. The only POSTs are a webhook resend, a resume and the sandbox deposit simulator. A webhook resend takes no key and no body. A resume and the simulator each take a new `Idempotency-Key`.
- Amounts on rows are **strings** in major units (`"250"`, `"1.5"`), in the row's `currency`.
- `status` on a row is `pending`, `paused`, `waiting_approval`, `completed` or `failed`. Only `completed` and `failed` are final.
- A misspelled filter value (`status=complete`) returns an empty list, not an error.
- Gravv sends no webhook for fees, reads or limits. It sends `transfer.status.*` for transfers, `transfer.inflow.*` for deposits and `inflow.onchain.*` for on-chain wallet deposits.
