Skip to main content
Coming Soon - Webhook functionality is currently in development. This page documents the planned implementation.

Overview

The transaction.refunded event is triggered when a transaction is refunded, either fully or partially. This event fires immediately after the refund is processed.

When This Event Fires

  • Full refund is processed for a transaction
  • Partial refund is issued
  • Refund is initiated through the Givebutter dashboard
  • Refund is triggered via the API
  • Chargeback results in a refund
Refunds typically take 5-10 business days to appear in the donor’s account, but this webhook fires immediately when the refund is initiated.

Webhook Payload

{
  "id": "evt_ghi789jkl012",
  "type": "transaction.refunded",
  "created_at": "2024-01-20T09:15:00Z",
  "data": {
    "id": "txn_123456789",
    "amount": 5000,
    "currency": "USD",
    "status": "refunded",
    "type": "donation",
    "payment_method": "card",
    "fee_covered": true,
    "gross_amount": 5000,
    "fee_amount": 250,
    "net_amount": 4750,
    "refund": {
      "id": "ref_abc123",
      "amount": 5000,
      "reason": "requested_by_donor",
      "note": "Duplicate donation",
      "refunded_at": "2024-01-20T09:15:00Z"
    },
    "donor": {
      "id": "cont_987654321",
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "[email protected]",
      "phone": "+1234567890"
    },
    "campaign": {
      "id": "camp_abc123",
      "title": "Annual Gala 2024",
      "url": "https://givebutter.com/annual-gala-2024"
    },
    "note": "In memory of John Smith",
    "anonymous": false,
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-20T09:15:00Z"
  },
  "account_id": "acct_xyz789"
}

Event Data Fields

id
string
required
Unique identifier for the transaction (prefixed with txn_)
amount
integer
required
Original transaction amount in cents (e.g., 5000 = $50.00)
currency
string
required
Three-letter ISO currency code (e.g., USD, CAD, EUR)
status
string
required
Transaction status. Will be refunded or partially_refunded.
type
string
required
Type of transaction: donation, ticket, merchandise, registration, or other
payment_method
string
required
Payment method used: card, paypal, venmo, ach, google_pay, or daf
fee_covered
boolean
required
Whether the donor chose to cover processing fees
gross_amount
integer
required
Original total amount including fees (in cents)
fee_amount
integer
required
Original processing fee amount (in cents)
net_amount
integer
required
Original net amount after fees (in cents)
refund
object
required
Details about the refund
donor
object
required
Information about the supporter who made the original transaction
campaign
object
required
Campaign the transaction belongs to
note
string
Optional message or note left by the donor on original transaction
anonymous
boolean
required
Whether the donor chose to remain anonymous
created_at
string
required
ISO 8601 timestamp when the transaction was originally created
updated_at
string
required
ISO 8601 timestamp when the transaction was last updated (refund time)

Common Use Cases

Sync refunded transactions to your accounting system:
async function handleTransactionRefunded(event) {
  const { id, refund, amount, campaign } = event.data;

  await accounting.createRefundEntry({
    transaction_id: id,
    refund_id: refund.id,
    amount: refund.amount / 100,
    campaign: campaign.title,
    refunded_at: refund.refunded_at,
    reason: refund.reason
  });

  // Update campaign totals
  await updateCampaignTotals(campaign.id);
}
Alert your team when refunds are processed:
async function handleTransactionRefunded(event) {
  const { donor, refund, amount, campaign } = event.data;

  await sendSlackNotification({
    channel: '#finance',
    message: `💳 Refund processed: $${refund.amount / 100} for ${donor.first_name} ${donor.last_name}`,
    details: {
      campaign: campaign.title,
      reason: refund.reason,
      note: refund.note
    }
  });
}
Email donors to confirm their refund was processed:
async function handleTransactionRefunded(event) {
  const { donor, refund, campaign } = event.data;

  await sendEmail({
    to: donor.email,
    subject: `Refund processed for ${campaign.title}`,
    body: `Dear ${donor.first_name},\n\nYour refund of $${refund.amount / 100} has been processed. It should appear in your account within 5-10 business days.`
  });
}
Adjust lifetime giving totals in your CRM:
async function handleTransactionRefunded(event) {
  const { donor, refund } = event.data;

  const lifetimeGiving = await calculateLifetimeGiving(donor.id);

  await crm.updateContact(donor.id, {
    lifetime_giving: lifetimeGiving,
    last_refund_date: refund.refunded_at,
    last_refund_amount: refund.amount / 100
  });
}

Refund Reasons

Reason CodeDescription
requested_by_donorDonor requested a refund
duplicateDuplicate transaction identified
fraudulentSuspected or confirmed fraudulent transaction
chargebackDonor initiated a chargeback with their bank
otherOther reason (check refund.note for details)