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_time or recurring

  • 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, or expired

  • 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


GET/api/v1/donations

List Donations

Returns a paginated list of donations. Results are scoped by role.

Authentication: Required

Role scoping:

  • system_admin — all donations; optionally filter by institution_id
  • institution_admin — all donations for their institution; optionally filter by institution_id
  • committee_member — donations for their institution
  • donor — only their own donations

Query Parameters

  • Name
    institution_id
    Type
    integer
    Description

    Filter by institution. Only available to system_admin and institution_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
  }
}

POST/api/v1/donations

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_anonymous is true

  • Name
    donor_email
    Type
    string
    Description

    Required for guest donations (when not authenticated) unless is_anonymous is 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.

GatewayEndpoint
PayMongoPOST /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"
}

POST/api/v1/donations/{donation}/pay/paymongo

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"
    ]
  }
}

GET/api/v1/donations/my

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/api/v1/donations/my/stats

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:

  1. Initiate Donation - User submits donation with selected payment method
  2. Create Record - System creates donation with pending status
  3. Payment Gateway - User is redirected to PayMongo checkout
  4. Webhook Callback - Gateway sends webhook on payment completion
  5. Update Status - System updates donation to completed and campaign balances
  6. 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 received
  • pending → cancelled — user explicitly clicked cancel on the PayMongo checkout page
  • pending → expired — donation was abandoned (tab closed, navigated away), confirmed unpaid by re-checking PayMongo, and cleaned up by the donations:expire scheduler after 30 minutes. Donations still in awaiting_next_action (3DS) or processing are left pending rather 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_name returns "Anonymous Donor"
  • Donor details are not shown publicly
  • donor_name and donor_email become 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_id belongs 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."]
  }
}

Was this page helpful?