Donations
The Donations API enables users to make one-time contributions to campaigns. The API handles payment processing through the PayMongo gateway, tracks donation history, and provides personal statistics.
The Donation Model
The donation model represents a monetary contribution to a campaign, including all payment details and donor information.
Properties
- Name
id- Type
- integer
- Description
Unique identifier for the donation
- Name
institution_id- Type
- integer
- Description
Foreign key to the institution receiving the donation
- Name
campaign_id- Type
- integer
- Description
Foreign key to the campaign being supported
- Name
user_id- Type
- integer | null
- Description
Foreign key to the authenticated user. Null for guest donations
- Name
subscription_id- Type
- integer | null
- Description
Foreign key to subscription if this is a recurring donation
- Name
donation_type- Type
- enum
- Description
Type of donation:
one_timeorrecurring
- Name
donor_name- Type
- string | null
- Description
Donor name for guest donations or anonymous donations
- Name
donor_email- Type
- string | null
- Description
Donor email for guest donations
- Name
is_anonymous- Type
- boolean
- Description
Whether the donation should be displayed anonymously. Default:
false
- Name
message- Type
- text | null
- Description
Optional message from the donor to the campaign
- Name
amount- Type
- decimal(12,2)
- Description
Donation amount in PHP before fees
- Name
convenience_fee- Type
- decimal(12,2)
- Description
Payment gateway processing fee. Default:
0.00
- Name
system_fee- Type
- decimal(12,2)
- Description
Platform service fee. Default:
0.00
- Name
total_amount- Type
- decimal(12,2)
- Description
Total amount charged (amount + convenience_fee + system_fee)
- Name
reference_number- Type
- uuid
- Description
Internal UUID reference sent to payment gateways as
requestReferenceNumber
- Name
transaction_id- Type
- string | null
- Description
Payment gateway transaction ID (PayMongo
cs_.../pi_...)
- Name
payment_gateway- Type
- string
- Description
Payment gateway used:
paymongo
- Name
payment_method- Type
- string | null
- Description
Specific payment method:
gcash,paymaya,card,grab_pay,qrph
- Name
status- Type
- enum
- Description
Current status:
pending,completed,failed,cancelled, orexpired
- Name
paid_at- Type
- timestamp | null
- Description
Timestamp when payment was completed
- Name
billing_period_start- Type
- date | null
- Description
Start date of billing period for recurring donations
- Name
billing_period_end- Type
- date | null
- Description
End date of billing period for recurring donations
- Name
created_at- Type
- timestamp
- Description
Record creation timestamp
- Name
updated_at- Type
- timestamp
- Description
Record last update timestamp
- Name
deleted_at- Type
- timestamp | null
- Description
Soft delete timestamp
Relationships
- Name
institution- Type
- Institution
- Description
The institution receiving the donation
- Name
campaign- Type
- Campaign
- Description
The campaign being supported
- Name
user- Type
- User | null
- Description
The authenticated user who made the donation (null for guests)
- Name
subscription- Type
- DonationSubscription | null
- Description
The subscription for recurring donations
Computed Properties
- Name
donor_display_name- Type
- string
- Description
Returns "Anonymous Donor" if anonymous, otherwise user's name or donor_name
List Donations
Returns a paginated list of donations. Results are scoped by role.
Authentication: Required
Role scoping:
system_admin— all donations; optionally filter byinstitution_idinstitution_admin— all donations for their institution; optionally filter byinstitution_idcommittee_member— donations for their institutiondonor— only their own donations
Query Parameters
- Name
institution_id- Type
- integer
- Description
Filter by institution. Only available to
system_adminandinstitution_admin.
- Name
campaign_id- Type
- integer
- Description
Filter by campaign
- Name
status- Type
- string
- Description
Filter by status:
pending,completed,failed,cancelled,expired
- Name
search- Type
- string
- Description
Search by donor name, email, transaction ID, or reference number
- Name
per_page- Type
- integer
- Description
Results per page (default: 15)
- Name
page- Type
- integer
- Description
Page number
Request
curl https://batchmates-v2.revlv.com/api/v1/donations \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"data": {
"current_page": 1,
"data": [
{
"id": 45,
"amount": "1000.00",
"status": "completed",
"payment_gateway": "paymongo",
"donor_name": "Juan Dela Cruz",
"donor_email": "juan@example.com",
"institution_id": 1,
"campaign_id": 5,
"paid_at": "2024-02-05T10:00:00.000000Z"
}
],
"per_page": 15,
"total": 48,
"last_page": 4
}
}
Create Donation
Creates a new donation and immediately initiates payment with the selected gateway. This is a one-step process where the donor selects their payment gateway upfront and gets redirected to checkout immediately.
Authentication: Optional - supports both authenticated users and guest donations
Request Body
- Name
campaign_id- Type
- integer
- Description
ID of the campaign to donate to
- Name
amount- Type
- number
- Description
Donation amount in PHP (minimum: 1, maximum: 99,999,999.99, max 2 decimal places)
- Name
payment_gateway- Type
- string
- Description
Payment gateway to use: must be
paymongo
- Name
payment_method- Type
- string
- Description
card|gcash|paymaya|grab_pay|qrph
- Name
is_anonymous- Type
- boolean
- Description
Make donation anonymous. Default:
false
- Name
message- Type
- string
- Description
Optional message to the campaign (max 500 characters)
- Name
donor_name- Type
- string
- Description
Required for guest donations (when not authenticated) unless
is_anonymousis true
- Name
donor_email- Type
- string
- Description
Required for guest donations (when not authenticated) unless
is_anonymousis true
Response
Returns a payment session with redirect URL and transaction details.
Request (Authenticated User)
{
"campaign_id": 1,
"amount": 1000,
"payment_gateway": "paymongo",
"payment_method": "gcash",
"message": "Keep up the good work!"
}
Request (Guest Donor)
{
"campaign_id": 1,
"amount": 500,
"payment_gateway": "paymongo",
"payment_method": "card",
"donor_name": "John Doe",
"donor_email": "john@example.com",
"message": "Supporting your cause!"
}
Request (Anonymous)
{
"campaign_id": 1,
"amount": 250,
"payment_gateway": "paymongo",
"payment_method": "qrph",
"is_anonymous": true
}
Response
{
"success": true,
"data": {
"redirectUrl": "https://checkout.paymongo.com/cs_abc123xyz",
"transaction_id": "cs_abc123xyz",
"reference_number": "550e8400-e29b-41d4-a716-446655440000"
},
"message": "Payment initiated successfully"
}
Error (Campaign Not Active)
{
"message": "The payment field is required.",
"errors": {
"payment": [
"Campaign is not accepting donations"
]
}
}
Error (Invalid Amount Format / Decimal Scale — 422)
{
"message": "The amount field must have between 0 and 2 decimal places.",
"errors": {
"amount": [
"The amount field must have between 0 and 2 decimal places."
]
}
}
Charge Saved Payment Method
Creates a donation charged directly to a saved payment method, bypassing the hosted checkout flow.
| Gateway | Endpoint |
|---|---|
| PayMongo | POST /api/v1/donations/charge-saved/paymongo |
Authentication: Required
Request Body
- Name
campaign_id- Type
- integer
- Description
ID of the campaign to donate to
- Name
payment_method_id- Type
- integer
- Description
ID of the saved payment method to charge. Must belong to the authenticated user and match the gateway of the endpoint called.
- Name
amount- Type
- number
- Description
Donation amount in PHP (minimum: 1, maximum: 99,999,999.99, max 2 decimal places)
- Name
cvc- Type
- string
- Description
Card CVC (3–4 digits) — PayMongo requires it on every saved-card charge
- Name
is_anonymous- Type
- boolean
- Description
Make donation anonymous. Default:
false
- Name
message- Type
- string
- Description
Optional message to the campaign (max 500 characters)
Request
{
"campaign_id": 1,
"payment_method_id": 3,
"amount": 500,
"cvc": "123",
"message": "Happy to help!"
}
Response (completed)
{
"success": true,
"data": {
"id": 88,
"amount": "500.00",
"status": "completed",
"payment_gateway": "paymongo",
"paid_at": "2025-03-01T08:00:00.000000Z"
},
"message": "Donation charged successfully"
}
Response (3DS required)
{
"success": false,
"requires_action": true,
"action_url": "https://checkout.paymongo.com/authenticate/pi_...",
"message": "Payment requires authentication"
}
Error (Wrong Owner — 403)
{
"success": false,
"message": "Payment method does not belong to you"
}
3DS authentication may be required on any charge. If requires_action: true is returned, redirect the user to action_url. After authentication, PayMongo calls our success webhook and the donation is marked completed automatically.
Retry Payment
Creates a fresh PayMongo checkout session for an existing donation and returns a new redirectUrl. Used when a donation is stuck pending, failed, or expired and the donor wants to try paying again — the original Donation record is reused, not duplicated.
Authentication: Required for the donation's owner. system_admin and institution_admin may retry on behalf of a donor.
Authorization: 403 if the donation belongs to another user and the caller isn't system_admin/institution_admin.
Preconditions: the donation must have been created with payment_gateway: paymongo and must not already be completed.
Request
curl -X POST https://batchmates-v2.revlv.com/api/v1/donations/45/pay/paymongo \
-H "Authorization: Bearer {token}"
Response
{
"redirectUrl": "https://checkout.paymongo.com/cs_newsession123",
"transaction_id": "cs_newsession123",
"reference_number": "550e8400-e29b-41d4-a716-446655440000"
}
Error (Not Authorized — 403)
{
"message": "You are not authorized to retry this donation."
}
Error (Wrong Gateway / Already Completed — 422)
{
"message": "The given data was invalid.",
"errors": {
"payment": [
"Donation already completed"
]
}
}
Unlike Create Donation, this response is not wrapped in data — read redirectUrl directly off the response body.
Get My Donations
Retrieves the authenticated user's donation history with campaign details.
Query Parameters
- Name
page- Type
- integer
- Description
Page number for pagination
- Name
per_page- Type
- integer
- Description
Items per page (default: 20)
Request
curl https://batchmates-v2.revlv.com/api/v1/donations/my \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"data": {
"current_page": 1,
"data": [
{
"id": 1,
"campaign_id": 1,
"amount": "1000.00",
"status": "completed",
"payment_method": "gcash",
"paid_at": "2024-01-15T14:30:00.000000Z",
"campaign": {
"id": 1,
"title": "Engineering Scholarship Fund",
"institution": {
"name": "University of the Philippines"
}
}
}
],
"per_page": 20,
"total": 12
}
}
Get My Stats
Retrieves donation statistics for the authenticated user, including total amounts, donation count, and campaigns supported.
Request
curl https://batchmates-v2.revlv.com/api/v1/donations/my/stats \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"data": {
"total_donated": "15000.00",
"total_count": 12,
"campaigns_supported": 5,
"this_month": "2500.00"
}
}
Payment Flow
The donation process follows a one-step flow:
- Initiate Donation - User submits donation with selected payment method
- Create Record - System creates donation with
pendingstatus - Payment Gateway - User is redirected to PayMongo checkout
- Webhook Callback - Gateway sends webhook on payment completion
- Update Status - System updates donation to
completedand campaign balances - Redirect - User returns to success/failure page
Status Transitions
pending→completed— payment confirmed via PayMongo webhook (re-verified against PayMongo's API)pending→failed— payment declined, failure webhook receivedpending→cancelled— user explicitly clicked cancel on the PayMongo checkout pagepending→expired— donation was abandoned (tab closed, navigated away), confirmed unpaid by re-checking PayMongo, and cleaned up by thedonations:expirescheduler after 30 minutes. Donations still inawaiting_next_action(3DS) orprocessingare leftpendingrather than expired. If PayMongo instead confirms the payment succeeded, the scheduler completes the donation instead of expiring it.
Fee Calculation
Total amount charged includes:
- Base donation amount
- Convenience fee (gateway processing fee)
- System fee (platform service fee)
Example (GCash):
Amount: ₱1,000.00
Convenience Fee: ₱22.30 (2.23% PayMongo GCash rate)
System Fee: ₱15.00 (1.5% platform fee)
Total Charged: ₱1,037.30
Donation Types
One-Time Donations
Single donations made to a campaign. These are the default donation type.
{
"campaign_id": 1,
"amount": 1000,
"payment_gateway": "paymongo",
"payment_method": "gcash"
}
Recurring Donations
Scheduled donations linked to a subscription. Recurring donations require:
- Active subscription (
subscription_id) - Billing period dates
donation_type: "recurring"
These are typically created automatically by the subscription system.
Anonymous Donations
Donors can choose to remain anonymous:
{
"campaign_id": 1,
"amount": 500,
"payment_gateway": "paymongo",
"payment_method": "card",
"is_anonymous": true
}
When is_anonymous is true:
donor_display_namereturns "Anonymous Donor"- Donor details are not shown publicly
donor_nameanddonor_emailbecome optional
Error Responses
- Name
422 Validation Error- Description
Invalid input data or business rule violation
- Name
403 Forbidden- Description
User lacks permission to access the resource, or the specified
payment_method_idbelongs to a different user (POST /donations/charge-saved).
- Name
404 Not Found- Description
Donation or campaign not found
Validation Error Example
{
"message": "The given data was invalid.",
"errors": {
"campaign_id": ["The selected campaign id is invalid."],
"amount": ["The amount must be at least 1."],
"payment_gateway": ["The selected payment gateway is invalid."]
}
}