Developers
Guide

Donations API

The Donations API lets your own tools record and look up gifts: enter a donation the moment it happens in an external system, search a donor's giving history, or pull gifts by date range for a dashboard. It shares everything with the Constituents API and the Volunteerism API — the same API keys, the same base URL, the same error shape, and the same field vocabulary your donation webhooks already speak.

Authentication

Use the same key you use for the other APIs (Subscription Settings → API Keys, team admins only), sent as a bearer token on every request:

Authorization: Bearer argenta_sk_...

The base URL is https://app.argentasoftware.com/api/v1. All requests and responses are JSON.

Endpoints

Method & pathWhat it does
POST /donationsRecord a donation for a constituent. FkConstituent and DonationAmount are required; everything else is optional.
GET /donations/{id}Fetch one donation.
GET /donations?constituentId=...A constituent's giving history, newest first.
GET /donations?search=...&startDate=...&endDate=...&minAmount=...&maxAmount=...Search by donor name or email, filtered by date range and amount range. Paged, max page size 100.
Donations are create-only through the API — by design. There is no update and no delete endpoint for a donation. These are money records: once a gift is recorded, corrections, refunds, and deletions happen inside Argenta where the full modification history and general-ledger connections live. If your integration needs to fix a mis-entered gift, fix it in Argenta.

Record a donation

A donation always belongs to an existing constituent. Create or find the constituent first (the Constituents API upsert is built for exactly this), then:

curl -X POST "https://app.argentasoftware.com/api/v1/donations" \
  -H "Authorization: Bearer argenta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "FkConstituent": 424037,
    "DonationAmount": 250.00,
    "DateOfDonation": "2026-07-24",
    "DesignatedPurpose": "General Fund",
    "DonationDescription": "Monthly partner gift via HubSpot"
  }'

You get 201 with {"created": true, "donation": {...}}. Argenta treats the entry exactly like a hand-entered gift: the donor record is found or created for that constituent, the donor's giving level recalculates, the gift appears in the Donations grid and the donor's history immediately, and your donation.created webhook fires. The date defaults to today if you leave it off.

Donation fields

FieldTypeNotes
FkConstituentintRequired. The constituent who gave. Must exist in your account.
DonationAmountdecimalRequired. Positive, up to 10,000,000. Immutable once recorded.
DateOfDonationdateDefaults to today.
DonationDescriptionstringFree-text note about the gift.
DesignatedPurposestringWhat the donor designated the gift for.
CheckNumberstringFor check gifts.
FkDonationType, FkCategory, FkPaymentMethodintIds from your account's lookup lists; null for the default. Unknown ids are rejected.
IsAnonymous, IsTribute, IsThankYouSentboolFlags, all default false. Tribute gifts can carry TributeName and TributeNote.
Employer, Occupation, EmployerLocationstringFor political teams recording contribution compliance details. 50 characters max — over-length is rejected, never truncated.

Everything else a donation carries in Argenta — general-ledger posting, funds and accounts, campaign and event attribution, recurring schedules, receipts, refunds — is managed in-app and is not writable through the API. Unknown fields are rejected with 400 unknown_field rather than ignored, so a typo can never silently drop data.

Errors

Same shape as the other APIs: an HTTP status plus a JSON body with a machine code and a human message.

StatusCodeWhen
400missing_field / invalid_field / unknown_fieldThe body failed validation. Nothing was written — a bad field never leaves a blank donation behind.
401unauthorizedMissing, malformed, revoked, or unknown key.
403insufficient_scopeA read-only key tried to record a donation.
403record_protectedThe constituent is locked or view-only.
404not_foundNo donation with that id in your account.
413payload_too_largeBody over 64 KB.
429rate_limitedSlow down and retry with backoff.

Rate limits
Two limits apply, not one. Per key it is 15 requests a second and 600 a minute. There is also a per-IP limit of 40 a second and 1200 a minute, checked before we even read your key, so several keys calling from the same server share that budget. Either limit returns a 429 with a Retry-After header saying how many seconds to wait.

The same per-key limits as the rest of /api/v1. Batch entry is fine — pace large imports and honor 429 responses with a backoff and they will sail through.

Pair this API with the donation webhooks (donation.created, donation.refunded, donation.receipted, and friends) to keep an external system in sync in both directions — see Webhooks.
Reconnecting…

Whoops!

You've Encountered An Error

Something went wrong on our end. Don't worry, our development team has already been notified, and we'll get it fixed as soon as we can.

Please avoid repeating the same action for now. A quick reload usually gets you going again.