> ## Documentation Index
> Fetch the complete documentation index at: https://docs.grainledger.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Giving resources

> Work safely with donors, households, contributions, giving batches, and settlements.

Grain's giving API is a connected resource graph:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
donor ── member of ──> household
  │
  └── contribution ──> giving batch ──> settlement
           │                                │
           └── fund                         └── bank and accounting status (read-only)
```

Lists include compact, one-level summaries. Fetch large related collections through their own paginated endpoints with `donorId`, `householdRef`, `givingBatchId`, or `settlementId` filters instead of expecting nested unbounded data.

## Who owns the totals?

* Contribution amounts, processing fees, and stored net amounts are the source for a giving batch. Grain recalculates batch gross, absolute fees, net, fund splits, and distinct gift count whenever membership or money changes.
* Settlement `recordedTotals` are provider or client-owned values and remain independently editable.
* Settlement `linkedContributionTotals` are calculated from current linked contributions. Compare the two objects to identify import or membership differences.

Dates such as contribution date, batch date, and estimated arrival date are calendar days. Grain returns existing v1 date fields as UTC ISO strings, with calendar days represented at UTC midnight. Audit timestamps such as `createdAt`, `updatedAt`, and `committedAt` are real instants.

## Create a manual batch

If `givingIntegrationId` and `externalBatchId` are omitted, Grain uses its non-syncing manual giving integration and generates an external ID. Empty open batches are valid.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body \
  -X POST "https://api.grainledger.com/api/v1/batches" \
  -H "Authorization: Bearer $GRAIN_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "externalReference": "Sunday online gifts",
    "batchDate": "2026-08-16",
    "contributionIds": ["contribution_1", "contribution_2"]
  }'
```

`contributionIds` replaces batch membership atomically. A contribution already owned by another batch produces `409 Conflict`; move it explicitly with `PATCH /api/v1/contributions/{id}` before the bulk membership write.

## Link a whole batch to a settlement

Settlement writes accept both individual `contributionIds` and whole `givingBatchIds`. Attaching a batch also attaches all of its contributions in the same transaction.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --fail-with-body \
  -X POST "https://api.grainledger.com/api/v1/settlements" \
  -H "Authorization: Bearer $GRAIN_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "externalReference": "August online giving",
    "estimatedArrivalDate": "2026-08-21",
    "totalGross": 1025,
    "totalFees": 25,
    "totalNet": 1000,
    "paymentCount": 8,
    "givingBatchIds": ["batch_1"]
  }'
```

All donors, funds, merchants, integrations, contributions, batches, and settlements referenced by a write must belong to the authenticated organization. Partial-batch or conflicting settlement ownership returns `409` without applying a partial change.

## Accounting freeze behavior

CRUD never posts a journal entry, links a bank transaction, or reconciles a settlement. `MATCHED`, `RECONCILED`, and batch `SETTLED` are accounting-owned states and cannot be created through ordinary API edits.

Unfrozen contributions, batches, and settlements can be edited, moved, or deleted. Once a resource is posted, cleared, bank-linked, or otherwise accounting-frozen, conflicting writes return `409 Conflict`. Deleting an unfrozen batch or settlement unlinks and preserves its contributions; deleting a contribution recalculates its former batch.

## Household members

Use the member routes to keep current membership, position, and primary contact consistent:

* `POST /api/v1/households/{id}/members`
* `PATCH /api/v1/households/{id}/members/{donorId}`
* `DELETE /api/v1/households/{id}/members/{donorId}`

Moving a donor refreshes both affected household aggregates. Send `null` in donor or household PATCH requests to clear documented nullable fields.

<Tip>
  Give integrations separate `contributions`, `batches`, and `settlements`
  scopes. Write scopes imply read, but they do not grant journal-posting
  permission.
</Tip>
