Skip to content

Add Giving API support for imported donation failure states distinct from refunds #1461

@michaelhvisser

Description

@michaelhvisser

Related Product
Giving

Is your feature request related to a problem? Please describe.
We import historical giving data from third-party providers into Planning Center Giving through the Giving API. Some providers expose transaction outcomes that distinguish between donations that were successfully
refunded and donations that ultimately failed.

A concrete example is Subsplash, which can export statuses such as refunded, failed, and disputed. In the current Giving API, we can detect those statuses during import, but the only write-side action we
have for an already-created donation is POST /giving/v2/donations/{donation_id}/issue_refund.

That creates a problem for imports and reconciliations because we cannot preserve the original provider semantics. Today, if we want the imported data in Planning Center to reflect a non-successful transaction,
the only API option appears to be to refund the donation. That conflates distinct source states:

  • refunded: a completed donation that was later refunded
  • failed: a donation/payment attempt that did not complete successfully
  • disputed: a chargeback/dispute-like outcome that is not necessarily the same thing as a normal refund

As a result, integrations have to either:

  • map multiple source statuses into the same Planning Center refund action, which loses fidelity, or
  • leave those records in a manual/off-platform state and maintain provider-specific exceptions in our import logic.

Describe the solution you'd like
We would like the Giving API to expose a supported way to represent failed or otherwise non-refund negative outcomes distinctly from refunds.

Any of the following would solve the problem:

  • Allow integrations to explicitly set a donation outcome/status through the API for imported batch donations, including a value such as failed
  • Add a dedicated donation action such as mark_failed, void, mark_disputed, or similar
  • Provide a documented import-specific field or action that maps third-party provider outcomes into the correct Giving state model without requiring everything to become a refund

At minimum, it would help if the API supported a distinct write path for:

  • refunded donations
  • failed donations

Ideally, the API would also clarify how disputed or chargeback-like outcomes should be represented for imported donations.

Describe alternatives you've considered
We have considered these alternatives, but each has drawbacks:

  • Treat every non-success outcome as a refund using issue_refund
    • This is inaccurate for provider records that were failed rather than refunded
  • Skip automatic handling for failed rows and require manual reconciliation in Planning Center
    • This adds operational overhead and prevents consistent provider imports
  • Store the original provider status only in our own system and import a simplified result into Planning Center
    • This causes data divergence between our source import data and what admins see in Giving
  • Encode the original status in notes or labels
    • This preserves some context, but it does not provide the correct donation lifecycle/state in the Giving model

Additional context
We reviewed the current public Giving API documentation and found:

  • payment_status is documented as a readable donation attribute with values including pending, succeeded, and failed
  • payment_status does not appear to be assignable on donation create/update
  • the only donation action we found for this use case is POST /giving/v2/donations/{donation_id}/issue_refund

Because of that, it appears the public API currently supports "refunded" as a write action, but not "failed" as a distinct imported outcome.

This matters for provider integrations because we want to update our provider mappings according to the API’s supported state model rather than hard-coding inaccurate assumptions. If the intended model is
different, documented guidance on how imported provider statuses should map into Giving would also be very helpful.

I have..

  • Reviewed the documentation found at https://developer.planning.center/docs
  • Searched for previous issues asking for this feature request
  • Removed all private information from this issue (credentials, tokens, emails, phone numbers, etc.)
  • Reviewed my issue for completeness

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions