Documentation

Donations

Donation campaigns deploy a dedicated on-chain wallet per campaignId. Share walletAddress with donors, they send USDC from any wallet, any amount. Videpay tracks contributions, quotes fees, handles unsupported tokens, and sweeps or refunds based on goalUsd, deadline, and expiryAction. No hosted donate page yet; the campaign wallet address is the shareable link. Fundraising with block explorer receipts, transparency goes hard.

Need machine-readable request/response bodies for your AI or codebase? Download this page as plain Markdown.

When should I use this?

  • Nonprofits or creators accepting open-ended USDC contributions.
  • Crowdfunding with a USD goal and optional deadline.
  • Community treasuries that need sweep-to-treasury or refund-on-expiry behavior.
  • You want variable donation amounts, not a fixed invoice total.

Why use Videpay?

  • campaignId is your stable identifier in API paths and reconciliation.
  • Donors send any amount to walletAddress, no fixed checkout total required.
  • Donation protocol fees are lower than deposit session fees: better economics for open fundraising.
  • Automatic transfer detection with donation.received webhooks.
  • Reconcile, sweep, refund donor, and recover unsupported token/native flows.
  • expiryAction controls refund_donors vs sweep_to_treasury when deadline passes.

Open-source fundraiser

You create campaignId campaign_id with goalUsd 50000 and a 30-day deadline. You post walletAddress on your site and Discord. Supporters send 5, 50, or 500 USDC whenever they want. You monitor donation.received webhooks, then POST /donations/campaigns/:campaign_id/sweep when ready to move funds to settlementAddress.

Before you start

  • Merchant registered on-chain (campaign wallet deploys automatically)
  • campaignId chosen upfront: immutable identifier for API paths
  • Webhook endpoint for donation.received and campaign lifecycle events

Deposit address vs donation address

You might be staring at two different on-chain addresses in Videpay and thinking: why are these not the same thing? Respectfully, they are built for different vibes.

Two addresses, two jobs

Deposit session address (checkout / payments) is for exact invoices, you set a fixed `amount` when creating the session, and Videpay configures the on-chain route with that `expectedAmount`. Partial sends are tracked until the total is met; overpayment is settled up to the expected amount and the surplus is returned automatically. It's giving 'pay exactly 49.99 USDC for order #1042.' Donation campaign `walletAddress` is for open contributions, donors send whatever they want (5 USDC, 50, 500), there is no fixed session total, and you aggregate toward `goalUsd` over time. It's giving 'support the project whenever, however much.' Donation protocol fees are also lower than deposit session fees. Use deposits when the amount is the contract; use donations when the amount is the community's choice.

  1. Need a fixed price, checkout link, or deposit session with expectedAmount? → deposit session address.
  2. Need open-ended contributions, tips, or crowdfunding with optional goalUsd? → donation campaign walletAddress.
  3. Quote fees with POST /donations/quote-fee (Donation fee type) or your deposit/checkout quote to compare net proceeds.

How donations work

  1. Create a campaign with campaignId, title, optional goalUsd and deadline.
  2. Videpay deploys the campaign wallet and emits donation.campaign.created.
  3. Share walletAddress with donors, they send USDC from any wallet, any amount.
  4. donation.received webhook fires per contribution; unsupported tokens emit donation.unsupported_token.
  5. Close manually or wait for deadline: expiryAction determines refund vs sweep.
  6. Sweep proceeds to settlementAddress (defaults to merchant wallet).

Dashboard features

Dashboard → Donations

Create campaigns with goal, deadline, and expiry action. View raised progress, copy walletAddress to share with donors, reconcile mismatches, sweep to treasury, refund individual donors, and recover unsupported tokens: each action maps to the API endpoints below.

  1. Campaign list: status, raised vs goalUsd, deadline countdown.
  2. Campaign detail: copy walletAddress, view transfers, reconcile, sweep, close.
  3. Transfer list: donorRef, amount, txHash, refund action per donor.
  4. Recovery: recover token or native balance sent by mistake.

Quote donation fee

Preview protocol fee before showing net proceeds to donors. Donation fees use the Donation fee bucket, lower than deposit sessions. Use `token`: `"USDC"` and a human `amount`, same shape as checkout and transfers.

Human amounts and token symbols

Quote fee, sweep, and most campaign actions accept `token`: `"USDC"` and `amount`: `"100"`.

FieldTypeRequiredDescription
businessIduuidNoTarget business. Omit when your API key is scoped to one business.
chainstringNoChain scope for settlement APIs (base, polygon, etc.). Required for wallet direct/intent prepare. Sandbox resolves to testnets automatically.
campaignIdstringNoOptional campaign scope for fee context.
tokenstringYesDonation token symbol for the chain (e.g. `"USDC"`): same as checkout, transfers, and subscriptions.
amountdecimal stringYesHuman-readable donation amount (e.g. `"100"` for 100 USDC). Responses include `amount.raw` for reconciliation.
POST/donations/quote-fee

Quote fee for a donation amount against a campaign or token.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "businessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",03  "chain": "base",04  "campaignId": ":campaign_Id",05  "token": "USDC",06  "amount": "100"07}

Create and manage campaigns

FieldTypeRequiredDescription
businessIduuidNoTarget business. Omit when your API key is scoped to one business.
chainstringNoChain scope for settlement APIs (base, polygon, etc.). Required for wallet direct/intent prepare. Sandbox resolves to testnets automatically.
campaignIdstringYesYour campaign identifier (max 120). Used in URLs and API paths: e.g. campaign_id.
titlestringYesPublic campaign title (max 160 characters).
goalUsddecimal stringNoFundraising goal in USD human units (up to 6 decimals). Omit for open-ended campaigns.
deadlineintegerNoUnix timestamp in seconds. Omit for campaigns without an expiry.
expiryActionenumNoWhen deadline passes without meeting goal: refund_donors or sweep_to_treasury (default sweep_to_treasury).
settlementAddressaddressNoAddress receiving net sweep proceeds. Defaults to merchant settlement wallet when omitted.
POST/donations/campaigns

Create a donation campaign. Emits donation.campaign.created.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "businessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",03  "chain": "base",04  "campaignId": ":campaign_Id",05  "title": "New Microphone Fund",06  "goalUsd": "50000",07  "deadline": 1767225600,08  "expiryAction": "sweep_to_treasury",09  "settlementAddress": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"10}
GET/donations/campaigns?limit=20

List donation campaigns for the business.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json
GET/donations/campaigns/:campaign_Id

Retrieve campaign details including wallet address and progress.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json
POST/donations/campaigns/:campaign_Id/close

Manually close a campaign. Emits donation.campaign.closed.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{}

Donation transfers

List detected contributions, manually detect a transfer by txHash, or reconcile campaign state with on-chain balances.

FieldTypeRequiredDescription
businessIduuidNoTarget business. Omit when your API key is scoped to one business.
chainstringNoChain scope for settlement APIs (base, polygon, etc.). Required for wallet direct/intent prepare. Sandbox resolves to testnets automatically.
txHashstringYesTransaction hash of the donor transfer.
logIndexintegerNoLog index within the transaction (default 0).
GET/donations/campaigns/:campaign_Id/transfers?limit=20

List transfers detected for a campaign.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json
POST/donations/campaigns/:campaign_Id/transfers

Manually detect a donation transfer by txHash and log index. Emits donation.received when confirmed.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "businessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",03  "chain": "base",04  "txHash": "0xdonate...",05  "logIndex": 006}
POST/donations/campaigns/:campaign_Id/reconcile

Reconcile campaign raised amounts with on-chain wallet balances.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{}

Sweep, refund, and recovery

FieldTypeRequiredDescription
businessIduuidNoTarget business. Omit when your API key is scoped to one business.
chainstringNoChain scope for settlement APIs (base, polygon, etc.). Required for wallet direct/intent prepare. Sandbox resolves to testnets automatically.
donorRefstringNoDonor reference from transfer record: path param on refund endpoint.
tokenstringNoToken to sweep (e.g. `"USDC"`) or recover. For unsupported tokens not in your registry, pass the contract address.
sweepRefstringNoYour reconciliation reference for the sweep.
POST/donations/campaigns/:campaign_Id/sweep

Sweep net campaign balance to settlementAddress. Emits donation.campaign.swept.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "businessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",03  "chain": "base",04  "token": "USDC",05  "sweepRef": "treasury-sweep-march"06}
POST/donations/campaigns/:campaign_Id/refunds/donor-001

Refund a specific donor by donorRef.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{}
POST/donations/campaigns/:campaign_Id/recover/token

Recover unsupported ERC-20 tokens sent to the campaign wallet.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "businessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",03  "chain": "base",04  "token": "0xUnsupportedToken1234567890123456789012345678"05}
POST/donations/campaigns/:campaign_Id/recover/native

Recover native ETH/MATIC accidentally sent to the campaign wallet.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "businessId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",03  "chain": "base"04}

Campaign object reference

FieldTypeRequiredDescription
campaignIdstringNoYour stable campaign identifier: API paths and public URL slug.
goalUsddecimal stringNoFundraising target in USD human units (6 decimal precision on-chain).
deadlineintegerNoUnix timestamp in seconds. Omitted for open-ended campaigns.
expiryActionenumNorefund_donors or sweep_to_treasury when deadline passes without meeting goal.
settlementAddressaddressNoReceives net sweep proceeds. Defaults to merchant settlement wallet.
raisedUsd / walletAddressstring / addressNoProgress metric and on-chain deposit address for donors.

Webhooks you'll receive

Register a webhook endpoint and verify the X-Protocol-Signature header on every delivery before fulfilling orders or updating your database.

Webhookdonation.campaign.created

Sent when a campaign is created and wallet deployment is queued.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: donation.campaign.created04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookdonation.campaign.closed

Sent when a campaign is manually closed.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: donation.campaign.closed04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookdonation.campaign.swept

Sent when campaign funds are swept to settlementAddress.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: donation.campaign.swept04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookdonation.received

Sent when a supported USDC donation is detected on-chain.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: donation.received04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookdonation.unsupported_token

Sent when a donor sends a token other than the campaign's supported asset.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: donation.unsupported_token04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...