Event catalogue

Every webhook event Gravv sends, when it is sent, its fields and an example.

This page lists every event Gravv sends to your webhook URL, grouped by what it is about. Each section gives the event types, when each one is sent, the fields in event_data and an example. The fields every event shares are on Webhook payload structure.

If an event type is not on this page, Gravv does not send it.

Example. Ada pays a supplier 100.50 USD. You receive transfer.status.pending three times, one for each step, with idempotency_key ending in :1, :2 and :3. Then transfer.status.completed arrives with :4, and you mark the invoice paid. If the :3 event reaches you after the :4 one, you ignore it, because its lower number means it is older.

How to read an event

  • event_type is the full type, such as transfer.status.completed. event_category is the first part, such as transfer. Webhook history filters by it.
  • event_group_id is the same for every event about one thing: one transfer, deposit, card or customer. Each section says which id it is.
  • Deduplicate on the body's event_id. It stays the same when an event is retried or resent.
  • Keys in event_data arrive in alphabetical order. Gravv can add new keys at any time, so ignore the ones you do not know.
  • Amounts in event_data are strings, such as "100.5" or "1500.00", unless a section says otherwise.
  • Gravv compares events that carry no idempotency_key by their content. It does not send an event identical to an earlier one for the same object. When a card goes active, then freeze, then active again, Gravv does not send the second active. Read the object after a change you made yourself.
  • Events can arrive in any order. Each section says how to tell which is newer.

All event types

Event type Category Sent when
transfer.status.pending transfer A transfer moved to a new step. Several arrive for one transfer
transfer.status.completed transfer The transfer was paid
transfer.status.failed transfer The transfer failed, or a person must check it
transfer.status.returned transfer A completed payout came back and the money was returned
transfer.requires_information transfer The transfer paused and waits for you
transfer.resumed transfer A paused transfer resumed
transfer.inflow.deposit_received transfer A deposit in another currency is being converted
transfer.inflow.awaiting_approval transfer A deposit is held for approval
transfer.inflow.completed transfer A deposit was credited to the account
transfer.inflow.deposit_settled transfer A deposit was credited and settled on-chain
transfer.inflow.payout_failed transfer Crediting a deposit failed
transfer.inflow.compensated transfer A failed deposit was reversed
inflow.onchain.completed inflow Stablecoins arrived at a wallet address
inflow.onchain.failed inflow An incoming on-chain transfer failed on chain
account.activated account A bank account Gravv registered for you is ready
applications.accounts.pending applications.accounts A v2 account application was accepted
applications.accounts.blocked applications.accounts A v2 account application waits on you or the customer
applications.accounts.completed applications.accounts The v2 account is active
applications.accounts.failed applications.accounts The v2 account application ended without an account
external_account.created external_account An external account was added
external_account.active external_account An external account's setup succeeded
external_account.setup_failed external_account An external account's setup did not succeed
cards.application.update cards A card application changed status
cards.status.update cards A card changed status
cards.transaction.payment cards A card payment was recorded or changed status
cards.transaction.funding cards Money was added to a card
cards.transaction.withdraw cards Money was taken off a card
cards.dispute.submitted cards A dispute on a card payment was filed
cards.dispute.updated cards A dispute is under review
cards.dispute.resolved cards A dispute ended
collection.status.pending collection A collection is in progress, expired or was cancelled
collection.status.awaiting_capture collection A card payment is authorized and waits for capture
collection.status.provider_success collection The payment succeeded and settlement has not finished
collection.status.completed collection The money reached your destination
collection.status.failed collection The payment failed, was abandoned, or a refund failed
collection.status.provider_voided collection A card authorization was voided
collection.status.refund_pending collection A refund started
collection.status.refunded collection The payment was refunded
collection.status.disputed collection The payer opened a chargeback, or one was lost
customer.created customer A customer or an associated person was added
customer.kyc.status.pending customer Verification started or is still under way
customer.kyc.status.completed customer Verification passed
customer.kyc.status.failed customer Verification did not pass
feature_access.requested feature_access You asked for access to a feature
feature_access.action_required feature_access Gravv needs more information about your request
feature_access.approved feature_access Your request was approved
feature_access.rejected feature_access Your request was rejected
feature_access.suspended feature_access Gravv suspended a feature for your business

Transfers

Gravv sends these events for every transfer: payouts, transfers between accounts and wallets, card funding and withdrawal, and conversions. The category is transfer.

  • event_group_id is the transfer's reference.
  • idempotency_key is <reference>:<sequence>. The sequence goes up by one with each change. Apply an event only when its sequence is higher than the last one you applied for that transfer.
  • The top-level transaction_id is the first id in associated_transactions.
Event type status Sent when
transfer.status.pending pending The transfer moved to a new internal step. Gravv sends several for one transfer. Treat them all as "still moving"
transfer.status.completed completed The transfer was paid
transfer.status.failed failed The transfer failed or was rejected, and Gravv returned the money and fee to the source. Gravv also sends it when transfer_status is manual_processing_required. In that case a person is checking the transfer, it is not final, and you must not send it again. Gravv also sends it, with reason, when a pause expired or was cancelled
transfer.status.returned returned Sent only after completed. The payout came back, and Gravv returned the money to the source
transfer.requires_information paused The transfer paused for a limit, a document or the sender's details. See Paused transfers
transfer.resumed pending A pause ended because you resumed it or Gravv released it
Field Type Description
amount string The transfer amount, without trailing zeros, such as "100.5". There is no currency field, so read the transaction
associated_transactions array of strings Your transaction ids for this transfer. Left out when there are none
client_reference string Your client_reference from the request. Left out when you sent none
destination_id string The destination.id from the request. Left out when there was none
reference string The transfer's reference, the id you resume a paused transfer with
status string pending, completed, failed, paused or returned
transfer_status string Gravv's internal step. Its values can change, so build on status. Read it only on transfer.status.failed, to tell manual_processing_required from a final failure
reason string On transfer.requires_information, why it paused. On transfer.resumed, resumed or released. On a pause that ended without resuming: limit_pause_expired, limit_pause_cancelled, supporting_document_expired, supporting_document_cancelled, sender_details_expired or sender_details_cancelled
limit_details object Only on a pause: reason, breached_window, cap_usd, used_usd, remaining_usd, amount_usd, fee_usd, tier, subject_type, subject_id, policy_id, policy_version, and requirements (a list of type, tier, levels, description)
tx_hash string or null The on-chain hash, when the transfer has one
workflow_type string The kind of transfer: crypto_transfer, internal_transfer, auto_sweep, card_funding, card_withdrawal, global_remittance, us_bank_transfer, sepa_transfer, fps_transfer, swift_transfer, chaps_transfer, cross_chain_self_transfer or stablecoin_conversion
send_asset, amount_sent, receive_asset, receive_amount, min_receive_amount, provider_fee, refunded_amount, refund_asset string Only on a stablecoin conversion: what was sent, what was or will be received, and the conversion fee. When a conversion failed and was refunded, receive_amount is left out and refunded_amount and refund_asset are set
{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "5d1e7a3b-2c4f-4b8e-9d6a-1f0e3c2b7a95",
  "event_category": "transfer",
  "event_type": "transfer.status.completed",
  "event_group_id": "9a7c1e52-6b3d-4f0a-8e21-7d5c4b3a2f10",
  "timestamp": "2026-10-13T09:15:02.481263Z",
  "event_data": {
    "amount": "100.5",
    "associated_transactions": ["5d1e7a3b-2c4f-4b8e-9d6a-1f0e3c2b7a95"],
    "client_reference": "inv-2291",
    "destination_id": "c2f5a0b1-8d3e-4a6f-9b7c-0e1d2f3a4b5c",
    "reference": "9a7c1e52-6b3d-4f0a-8e21-7d5c4b3a2f10",
    "status": "completed",
    "transfer_status": "completed",
    "workflow_type": "global_remittance"
  },
  "event_id": "e4b1c0d2-3f5a-4e6b-8c7d-9a0b1c2d3e4f",
  "idempotency_key": "9a7c1e52-6b3d-4f0a-8e21-7d5c4b3a2f10:4"
}

Deposits into accounts

Gravv sends these events when money arrives in one of your customers' accounts. The category is transfer, so webhook history returns them with the transfer events.

  • event_group_id is the deposit's transaction_id. On transfer.inflow.payout_failed it is Gravv's own id for the deposit.
  • Gravv sends each type at most once for one deposit.
  • Gravv credits the deposit in full and charges any deposit fee separately. See Add up a month of fees.
Event type status Sent when Fields besides the sender fields
transfer.inflow.deposit_received deposit_received A deposit in another currency is being converted to the account's currency. Not sent when the currencies match transaction_id, account_id, amount (the estimated amount after conversion), currency (the account's), reference, remark, tx_hash (the conversion's reference, not a chain hash), source and destination
transfer.inflow.awaiting_approval awaiting_approval The deposit is held for approval before it is credited transaction_id, account_id, amount, currency
transfer.inflow.completed completed The deposit was credited transaction_id, account_id, amount, currency, and settlement_event_group_id when it was also settled on-chain
transfer.inflow.deposit_settled settled The deposit was credited and settled on-chain to the account's wallet The same as completed, plus tokenized true
transfer.inflow.payout_failed failed Crediting the deposit failed account_id, error, failed_at, and transaction_id ""
transfer.inflow.compensated compensated A failed deposit was reversed account_id, deposit_id, failure_reason

Every type also carries the sender fields sender_name, sender_account_number, sender_bank, session_id and narration. They are strings and can be empty.

For a credited deposit, Gravv sends transfer.inflow.completed or transfer.inflow.deposit_settled, depending on the account. Treat either one as credited. When the deposit was also settled on-chain, Gravv sends a second event, inflow.onchain.completed, for the same money. Its event_group_id equals settlement_event_group_id here. Credit your customer once.

{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "event_category": "transfer",
  "event_type": "transfer.inflow.completed",
  "event_group_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "timestamp": "2026-10-13T08:02:11Z",
  "event_data": {
    "account_id": "4f3e2d1c-0b9a-4876-9543-210fedcba987",
    "amount": "2500",
    "currency": "USD",
    "narration": "Invoice 4471",
    "sender_account_number": "0123456789",
    "sender_bank": "Example Bank",
    "sender_name": "Jane Doe",
    "session_id": "",
    "status": "completed",
    "transaction_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
  },
  "event_id": "c0ffee00-1234-4abc-9def-001122334455",
  "idempotency_key": "6c1f0a9e2b7d4c3a8e5f1b0d9c7a6e4f2d3b1a0c9e8f7d6c5b4a3f2e1d0c9b8a"
}

On-chain deposits

Gravv sends these events when USDC or USDT arrives at a wallet address, or at the wallet address of an account. The category is inflow.

Event type Sent when
inflow.onchain.completed An incoming on-chain transfer was detected. Sent once
inflow.onchain.failed An incoming on-chain transfer failed on chain
  • Gravv derives event_group_id from the transaction hash, so both events for one deposit share it (see Deposits into accounts).
  • There is no idempotency_key.
Field Type Description
amount string The amount received
asset string The token received. It can be the token's contract address, so read asset_symbol when it is present
asset_symbol string The token's symbol, such as USDC. Left out when unknown
balance_before, balance_after string or null The wallet's balance before and after, when known
blockchain_network string The network, such as polygon
confirmations number Confirmations at detection
destination object wallet_address, blockchain_network, blockchain_memo (always null), and the wallet or account id and destination_type when known
source object The sender's wallet_address and blockchain_network, and blockchain_memo (always null)
remark string Crypto Funding, or inbound transaction failed on chain
status string COMPLETED or FAILED, in upper case
transaction_id string The chain transaction as <network>:<hash>. It is not the id of a transaction row. Find the row by tx_hash
tx_hash string The transaction hash
{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "polygon:0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060",
  "event_category": "inflow",
  "event_type": "inflow.onchain.completed",
  "event_group_id": "3b8f1d2e-4c5a-5b6d-8e7f-9a0b1c2d3e4f",
  "timestamp": "2026-10-13T07:58:40Z",
  "event_data": {
    "amount": "250.00",
    "asset": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
    "asset_symbol": "USDC",
    "balance_after": "1250.00",
    "balance_before": "1000.00",
    "blockchain_network": "polygon",
    "confirmations": 12,
    "destination": {
      "blockchain_memo": null,
      "blockchain_network": "polygon",
      "destination_type": "wallet",
      "id": "0d9c8b7a-6f5e-4d3c-2b1a-0f9e8d7c6b5a",
      "wallet_address": "0x8ba1f109551bD432803012645Ac136ddd64DBA72"
    },
    "remark": "Crypto Funding",
    "source": {
      "blockchain_memo": null,
      "blockchain_network": "polygon",
      "wallet_address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
    },
    "status": "COMPLETED",
    "transaction_id": "polygon:0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060",
    "tx_hash": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"
  },
  "event_id": "aa11bb22-cc33-4dd4-8ee5-ff6600778899"
}

Gravv also sends events for other tokens that land on an address, such as a spam token. Credit only USDC and USDT.

Account applications

Gravv sends these events as a v2 account you open with POST /v2/accounts moves from creation to active. The category is applications.accounts, and event_group_id is the application id.

Event type Sent when
applications.accounts.pending The application was accepted. Gravv can skip this event, so do not depend on it
applications.accounts.blocked The application waits on you or the customer: kyc_pending, tos_pending, awaiting_customer_document or awaiting_customer_data
applications.accounts.completed The account is active. It carries no bank details, so read the account
applications.accounts.failed The application ended without an account

Gravv sends no event for a block that waits on nobody, such as the bank's own review. Gravv sends each type once for one application, so it sends nothing for a second block of another kind. After you act on a block, read the application again instead of waiting for another event.

Field Type Description
application_id string The application
account_id string The account it opens
customer_id string The customer
tenant_id string Your business
type string The event type again, such as applications.accounts.blocked
status string pending, blocked, completed or failed
created_at, updated_at string Timestamps. The envelope timestamp is updated_at
metadata object or null null on pending and completed. On blocked: block_reason, action_url (for tos_pending and kyc_pending), and additional_requirements with fields and documents. On failed: fail_reason, one of verification_rejected, identity_document_mismatch, information_expired, region_not_supported, request_cancelled, review_declined or verification_declined
{
  "tenant_id": "5d0c9b8a-7f6e-4d5c-8b4a-3f2e1d0c9b8a",
  "transaction_id": "",
  "event_category": "applications.accounts",
  "event_type": "applications.accounts.blocked",
  "event_group_id": "5e7a9c1b-2d4f-4a6b-8c0d-e1f2a3b4c5d6",
  "timestamp": "2026-10-13T09:20:02Z",
  "event_data": {
    "account_id": "6f1c2a9e-3b1d-4f7a-9c62-0d8e4b7a5c11",
    "application_id": "5e7a9c1b-2d4f-4a6b-8c0d-e1f2a3b4c5d6",
    "created_at": "2026-10-13T09:12:44Z",
    "customer_id": "0b6f3c1e-2a4d-4c8e-9f10-7d2a6b5e4c33",
    "metadata": {
      "additional_requirements": {
        "documents": ["proof_of_address"],
        "fields": []
      },
      "block_reason": "awaiting_customer_document"
    },
    "status": "blocked",
    "tenant_id": "5d0c9b8a-7f6e-4d5c-8b4a-3f2e1d0c9b8a",
    "type": "applications.accounts.blocked",
    "updated_at": "2026-10-13T09:20:02Z"
  },
  "event_id": "2f4a6c8e-0b1d-4f3a-8c5e-7a9b1d3f5a7c",
  "idempotency_key": "4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b"
}

On completed, read GET /v2/accounts/{id} for the bank details.

Accounts Gravv registers for you

Gravv sends account.activated once, when an existing bank account that Gravv registered for you becomes active. Gravv never sends it for a v2 account you open yourself, so wait for applications.accounts.completed instead. The category is account, and event_group_id is the account id.

Field Type Description
account_id string The account
customer_id string The customer it belongs to
status string active
currency string The account currency
bank_details object Deposit details. USD: bank_name, account_name, account_number, routing_number, bank_address, beneficiary_address. EUR: bank_name, account_name, iban, bic, bank_address, beneficiary_address. GBP: the EUR keys plus account_number and sort_code. Other currencies: bank_name, account_name, account_number. Empty values are left out
wallet_details object address and network, only when the account settles to a wallet
created_at string When Gravv created the event
{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "",
  "event_category": "account",
  "event_type": "account.activated",
  "event_group_id": "4f3e2d1c-0b9a-4876-9543-210fedcba987",
  "timestamp": "2026-10-12T16:40:05Z",
  "event_data": {
    "account_id": "4f3e2d1c-0b9a-4876-9543-210fedcba987",
    "bank_details": {
      "account_name": "Acme Ltd",
      "account_number": "9876543210",
      "bank_name": "Example Bank",
      "routing_number": "021000021"
    },
    "created_at": "2026-10-12T16:40:05.118Z",
    "currency": "USD",
    "customer_id": "0ff6cf9a-8da0-466d-a71c-714eb4bde248",
    "status": "active"
  },
  "event_id": "5e4d3c2b-1a09-4f8e-a7d6-c5b4a3928170",
  "idempotency_key": "0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d"
}

External accounts

Gravv sends these events when you add an external account and when its setup finishes. The category is external_account. event_group_id is the external account's id, and idempotency_key is <id>:<event type>:<revision>.

A bank_account or mobile_money external account is active as soon as you add it, so Gravv sends only external_account.created for it. An ach_wire, sepa, swift or fps external account starts pending, and Gravv sets it up in the background.

Event type Sent when
external_account.created An external account was added, with its status at that moment: pending or active
external_account.active Setup of a pending external account succeeded. You can now send transfers to it
external_account.setup_failed Setup did not succeed, and you can pay only an active external account. error_message says why. Correct the details with Update an external account

event_data is the external account, with the fields that Get an external account returns. Gravv leaves out fields with no value. On setup_failed, error_message says why. Show your own message to your users, not this text.

{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "",
  "event_category": "external_account",
  "event_type": "external_account.active",
  "event_group_id": "c2f5a0b1-8d3e-4a6f-9b7c-0e1d2f3a4b5c",
  "timestamp": "2026-10-12T14:05:51.204377Z",
  "event_data": {
    "account_name": "ANNA SCHMIDT",
    "account_owner_type": "individual",
    "currency": "EUR",
    "customer_id": "0ff6cf9a-8da0-466d-a71c-714eb4bde248",
    "date_created": "2026-10-12T14:02:10.551Z",
    "iban": "DE89370400440532013000",
    "id": "c2f5a0b1-8d3e-4a6f-9b7c-0e1d2f3a4b5c",
    "institution_country_iso_code": "DE",
    "payee_type": "sepa",
    "status": "active"
  },
  "event_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "idempotency_key": "c2f5a0b1-8d3e-4a6f-9b7c-0e1d2f3a4b5c:external_account.active:2"
}

Cards

Gravv sends these events for cards you issue. The category is cards. event_group_id is the card id on every card event, including payments. There is no idempotency_key, so Gravv does not send an event identical to an earlier one again.

Event type Sent when event_data
cards.application.update The card application changed status application: id (the card's id), status and customer_id. approved means the card can be issued. pending, manual_review, needs_information and needs_verification mean it is still in review. status is empty when none is set
cards.status.update The card changed status card (below)
cards.transaction.payment A card payment was recorded or changed status card and transaction (below)
cards.transaction.funding Money was added to the card card and transaction
cards.transaction.withdraw Money was taken off the card card and transaction

card holds id, customer_id, name_on_card, last4, expiry, network and status, all strings. status is active, freeze, blocked or inactive.

transaction holds:

Field Type Description
id string The card transaction
transaction_type string card_payment, card_funding or card_withdrawal
status string pending, completed or failed
amount string The amount, such as "18.75"
currency string USD
client_reference string Only on a funding you sent as a transfer: your client_reference
reference string On a funding you sent as a transfer, the transfer's reference. Do not build on it for other types
tx_hash string Only when the movement has an on-chain hash

A payment event carries no merchant or cardholder details, and a declined payment carries no reason. See Card decline reasons. Do not wait for cards.transaction.funding to confirm a funding. Follow the transfer and the transaction instead, as Fund cards explains.

{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "",
  "event_category": "cards",
  "event_type": "cards.transaction.payment",
  "event_group_id": "6a5b4c3d-2e1f-4a0b-9c8d-7e6f5a4b3c2d",
  "timestamp": "2026-10-13T10:22:31.902117Z",
  "event_data": {
    "card": {
      "customer_id": "0ff6cf9a-8da0-466d-a71c-714eb4bde248",
      "expiry": "09/29",
      "id": "6a5b4c3d-2e1f-4a0b-9c8d-7e6f5a4b3c2d",
      "last4": "4242",
      "name_on_card": "JANE DOE",
      "network": "visa",
      "status": "active"
    },
    "transaction": {
      "amount": "18.75",
      "currency": "USD",
      "id": "f1e2d3c4-b5a6-4978-8a6b-5c4d3e2f1a0b",
      "status": "completed",
      "transaction_type": "card_payment"
    }
  },
  "event_id": "0f1e2d3c-4b5a-4697-8877-665544332211"
}

Card disputes

Gravv sends these events when a payment on one of your cards is disputed. These docs do not cover an API to open or respond to a dispute, so treat these events as notices for your records and your support team. The category is cards. event_group_id is the card id, and the top-level transaction_id is the disputed transaction.

Event type Sent when
cards.dispute.submitted The dispute was filed
cards.dispute.updated The dispute is under review, or it moved to a new stage
cards.dispute.resolved The dispute ended: won, lost, withdrawn or expired
Field Type Description
id string The dispute
card_id string The card
transaction_id string The disputed card transaction
status string submitted, under_review, won, lost, withdrawn or expired
reason string fraud, billing_error, duplicate or not_received
amount string The disputed amount
currency string The currency
stage string representment, second_presentment, pre_arbitration or arbitration, when set
resolution_amount string The amount decided, once known
evidence_due_by string When evidence is due, when set
resolved_at string When the dispute ended
{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "f1e2d3c4-b5a6-4978-8a6b-5c4d3e2f1a0b",
  "event_category": "cards",
  "event_type": "cards.dispute.resolved",
  "event_group_id": "6a5b4c3d-2e1f-4a0b-9c8d-7e6f5a4b3c2d",
  "timestamp": "2026-10-13T15:10:44Z",
  "event_data": {
    "amount": "18.75",
    "card_id": "6a5b4c3d-2e1f-4a0b-9c8d-7e6f5a4b3c2d",
    "currency": "USD",
    "id": "7b2e9c41-5d3a-4f8e-a1b6-0c9d8e7f6a5b",
    "reason": "not_received",
    "resolution_amount": "18.75",
    "resolved_at": "2026-10-13T15:10:44Z",
    "status": "won",
    "transaction_id": "f1e2d3c4-b5a6-4978-8a6b-5c4d3e2f1a0b"
  },
  "event_id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f"
}

Collections

Gravv sends these events as a payment collection moves from the payer's payment to the stablecoin reaching your destination. The category is collection. event_group_id and the top-level transaction_id are the collection's transaction_id.

On or after 31 October 2026, the values in onramp_status change and Gravv renames two event types. If you read new_onramp_status now, your integration keeps working through the change. See Status label change.

Event type Sent when
collection.status.pending The collection is in progress. Also sent, with onramp_status expired or cancelled, when it expires or is cancelled
collection.status.awaiting_capture A card payment is authorized and waits for capture
collection.status.provider_success The payment succeeded and settlement has not finished
collection.status.completed The money reached your destination
collection.status.failed The payment failed, the payer abandoned it, or a refund failed
collection.status.provider_voided A card authorization was voided. transaction_status is cancelled
collection.status.refund_pending A refund has started
collection.status.refunded The payment was refunded
collection.status.disputed The payer opened a chargeback, or a chargeback was lost

Gravv sends no event when you create a collection, and the first event can arrive several minutes later. Events can arrive out of order. The step where a payment succeeds can arrive as collection.status.pending with new_onramp_status payment_succeeded. So build on transaction_status and the status label, not on the event type or the order of arrival. Confirm the end state with GET /v1/collections/{id}.

Field Type Description
transaction_id string The collection's id. Use it with GET /v1/collections/{id}
transaction_status string pending, completed, failed, refunded, refund_pending, disputed or cancelled
onramp_status string The step, with the label in use until the change. See Status label change
new_onramp_status string The step, with the new label. Sent until the change
status_transition_deadline string 2026-10-31T23:59:59Z. Sent until the change
amount string The amount collected, with two decimals
asset, network string The stablecoin you receive (USDC or USDT) and its network. Can be empty before settlement
tx_hash string The settlement hash, once the money has settled
payment_method string How the payer paid, such as card, when known
payment_intent_id string The card payment intent, for collections made through one
payment_info object For card payments: bin, exp_month, exp_year, card_brand, card_type, card_segment, last4, each when known
error_code string A failure code, such as INSUFFICIENT_FUNDS, CARD_EXPIRED or THREE_DS_FAILED, when known. A decline simulated in sandbox carries none
error_message, remark string A readable failure description, when known
client_reference, reference string Your reference from the collection request
metadata object The data you attached to the collection request
customer_id string The Gravv customer the collection belongs to
client_customer_id string Your own customer id, when you passed one
tenant_id string Your business

Credit your customer once per transaction_id, never once per event. The same step can arrive twice with different event_id values. Treat a second event with the same transaction_id and status as a duplicate.

Status label change

Every collection event, and every collection the API returns, carries two status labels until 31 October 2026:

  • onramp_status carries the current label, kept for existing integrations.
  • new_onramp_status carries the new label.
  • status_transition_deadline is 2026-10-31T23:59:59Z, the date after which onramp_status takes the new labels.

On or after 31 October 2026:

  • onramp_status carries the new labels, the values new_onramp_status carries today.
  • Gravv stops sending new_onramp_status and status_transition_deadline.
  • collection.status.provider_success becomes collection.status.payment_succeeded.
  • collection.status.provider_voided becomes collection.status.payment_voided.

What to do now:

  1. Match on new_onramp_status when it is present, and on onramp_status when it is not.
  2. Accept both names of the two renamed event types.
  3. When you filter collections by onramp_status, either label works.
Label in onramp_status until the change Label in new_onramp_status, and in onramp_status after it Meaning
provider_initiated payment_initiated The payer started paying
provider_success payment_succeeded The payment succeeded
provider_failed payment_failed The payment failed
provider_voided payment_voided A card authorization was voided
transfer_queued settlement_queued Settlement to your destination is queued
transfer_initialized settlement_initiated Settlement has started
transfer_success settlement_succeeded Settlement succeeded
transfer_failed settlement_failed Settlement failed. Gravv retries it and does not send this step as an event
transfer_completed settlement_completed The money reached your destination

These labels do not change: created, initialize, pending, awaiting_capture, abandoned, expired, cancelled, pending_review, suspected_fraud, chargeback_opened, chargeback_won, chargeback_lost, refund_initiated, refunded and refund_failed.

{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
  "event_category": "collection",
  "event_type": "collection.status.failed",
  "event_group_id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
  "timestamp": "2026-10-13T11:04:27Z",
  "event_data": {
    "amount": "1500.00",
    "asset": "",
    "customer_id": "0ff6cf9a-8da0-466d-a71c-714eb4bde248",
    "error_code": "INSUFFICIENT_FUNDS",
    "error_message": "The card has insufficient funds",
    "network": "",
    "new_onramp_status": "payment_failed",
    "onramp_status": "provider_failed",
    "payment_info": {
      "bin": "424242",
      "card_brand": "visa",
      "last4": "4242"
    },
    "payment_intent_id": "pi_7f6e5d4c3b2a",
    "payment_method": "card",
    "remark": "The card has insufficient funds",
    "status_transition_deadline": "2026-10-31T23:59:59Z",
    "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
    "transaction_id": "2c3d4e5f-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
    "transaction_status": "failed"
  },
  "event_id": "77665544-3322-4110-8ffe-ddccbbaa9988",
  "idempotency_key": "8b7a6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b"
}

Customers and KYC

Gravv sends these events when you create a customer and when their verification changes. The category is customer. event_group_id is the customer id. There is no idempotency_key.

Event type Sent when
customer.created A customer was created, or an associated person was added to a business, either at creation or by a later update. Gravv sends one event for each person
customer.kyc.status.pending Verification started, or is still under way. It can arrive more than once
customer.kyc.status.completed Verification passed
customer.kyc.status.failed Verification did not pass

Gravv sends the KYC events for people and for businesses. Gravv verifies a business only after each of its associated persons, so the persons' events come first.

customer.created carries id, type (individual, business, or a person's role such as ubo), status, email, address and created_at, and a kyc list with basic and intermediate, both not_started. It carries no names and no phone number. Read them with GET /v1/customers/{customer_id}.

The KYC events carry:

Field Type Description
customer_id string The customer whose verification changed
tenant_id string Your business
kyc_type string The level, basic
status string pending, completed or failed
customer_email string The customer's email
customer_type string individual or business
applicant_id string An internal reference. Ignore it, and do not show it to users
completed_at string When verification passed. Only on completed
failure_reason string Only on failed. Show your own message, not this text
business_name, business_type, registration_number string Only for a business

Gravv sends no pending event when the card KYC check (/v1/risk/*) starts. Its events can also carry country, city, state, postal_code and business_address.

Gravv does not guarantee the order. Before you act, read the customer. kyc[type=basic].status on GET /v1/customers/{customer_id} is the source of truth.

{
  "tenant_id": "5d0c9b8a-7f6e-4d5c-8b4a-3f2e1d0c9b8a",
  "transaction_id": "",
  "event_category": "customer",
  "event_type": "customer.kyc.status.completed",
  "event_group_id": "3f6b2a1e-8c4d-4e7f-9a2b-5c1d0e9f8a71",
  "timestamp": "2026-10-13T10:01:03Z",
  "event_data": {
    "applicant_id": "<internal reference>",
    "completed_at": "2026-10-13T10:01:03Z",
    "customer_email": "amara.nwosu@example.com",
    "customer_id": "3f6b2a1e-8c4d-4e7f-9a2b-5c1d0e9f8a71",
    "customer_type": "individual",
    "kyc_type": "basic",
    "status": "completed",
    "tenant_id": "5d0c9b8a-7f6e-4d5c-8b4a-3f2e1d0c9b8a"
  },
  "event_id": "0b6e2f4a-8c1d-4e3f-9a5b-7c2d4e6f8a10"
}

Feature access

Gravv sends these events when your request for a feature, such as card issuing, moves forward. A request to a feature that is not enabled for you returns 403 with a feature_access_* code. See Feature access errors. These docs do not cover an API to request a feature or to respond to Gravv, so these events tell you when to look in the Dashboard. The category is feature_access.

Event type Sent when
feature_access.requested You sent a request, or answered a request for information (then resubmitted is true)
feature_access.action_required Gravv needs more information. requirements lists what it needs
feature_access.approved The request was approved
feature_access.rejected The request was rejected. reason says why, and reapply_after says when you can ask again
feature_access.suspended Gravv suspended the feature for your business. reason says why
  • event_group_id is the request's id, or your business id for a suspension.
  • idempotency_key is <request_id>:<event type>, or <business id>:<feature>:<event type> for a suspension. So Gravv does not send a second suspension of the same feature.
Field Type Description
feature string card_issuance, card_acquiring or otc_trade_desk
feature_name string The display name, such as Card Issuance
status string The feature's new access status: locked, pending, action_required, rejected, enabled or suspended
request_id string Your request's reference, such as far_7k29pqvd. Left out for a suspension
reason string Only on rejected and suspended
reapply_after string The earliest time you can send a rejected request again, when there is a wait
requirements array of strings Only on action_required. Codes for what is needed. The Dashboard shows the full text
resubmitted boolean true when requested is your response to action_required
occurred_at string When it happened. The envelope timestamp is the same
{
  "tenant_id": "dfa96ede-fc13-43cf-8328-8b910d1cd1d2",
  "transaction_id": "",
  "event_category": "feature_access",
  "event_type": "feature_access.action_required",
  "event_group_id": "5d2c7a10-3b4e-4f6a-9c8d-1e2f3a4b5c6d",
  "timestamp": "2026-10-13T09:41:07Z",
  "event_data": {
    "feature": "card_issuance",
    "feature_name": "Card Issuance",
    "occurred_at": "2026-10-13T09:41:07Z",
    "request_id": "far_7k29pqvd",
    "requirements": ["business_website", "expected_monthly_volume"],
    "status": "action_required"
  },
  "event_id": "e4d3c2b1-a098-4f7e-8d6c-5b4a39281706",
  "idempotency_key": "far_7k29pqvd:feature_access.action_required"
}
Was this page helpful?