---
name: charitips
description: Integrate the Charitips donation API into a product (donations, votes, recurring donations, donation matching, webhooks, fiscal receipts). Use when the project mentions Charitips, charitable donations, round-up, giving at checkout, or a donation campaign.
metadata:
  version: '1'
---

Charitips lets a product give to charities: your code creates donations, your users pick the charity, Charitips transfers the donation to the charity and issues the fiscal receipt. The full documentation is at https://www.charitips.com/docs/llms.txt; every page exists as Markdown by adding `.md` to its address. The OpenAPI document, with the errors each endpoint returns, is at https://www.charitips.com/docs/openapi.json, and the read-only docs MCP server at `https://www.charitips.com/docs/mcp` (setup: https://www.charitips.com/docs/get-started/mcp.md).

## Rules

1. **Build and test on the sandbox**: `https://api.sandbox.charitips.com`, with credentials that start with `test_`. Never call `https://api.charitips.com` unless the user asks for production.
2. **Credentials come from environment variables** (`CHARITIPS_CLIENT_ID`, `CHARITIPS_CLIENT_SECRET`). Never write them in code, logs or commits.
3. **One access token per hour.** `POST /v1/authentication` with Basic authentication returns `accessToken`; cache it for the hour and reuse it. Never ask for a token before each call.
4. **Amounts are integers in cents.** 20 € is `2000`.
5. **Send `uniqueExternalId` on every create** (donation, vote, donor, recurring donation), set to your own id for the thing that caused it: an order, a transaction, an invoice. A repeated call then returns `409 Unique constraint failed on uniqueExternalId` instead of creating a duplicate. Treat that 409 as success and fetch the existing resource with the list endpoint filtered by `uniqueExternalId` (donations, votes, donors); for recurring donations, keep the id you received at creation.
6. **Create donations from the server**, after the payment or event is confirmed, never from the browser.
7. **Listen to webhooks instead of polling.** Verify the signature of every delivery before acting on it, as shown in [Webhooks configuration](https://www.charitips.com/docs/webhooks/configuration.md#signature), and reject what does not verify. Deliveries happen at least once, so handlers must be idempotent: key them on the resource id and its status.
8. **A fiscal receipt needs the donor's identity.** `withFiscalReceipt` and `hasBeenCharged` need the B2C use case on your account, and the receipt needs the donor's first name, last name and postal address, and a charity whose `fiscalReceiptsSupport` is `ENABLED`. For the donations you fund, the receipt goes to your account: one a year by default (`fiscalReceiptType: YEARLY`), or one per campaign once it is complete and paid, when the campaign is created with `fiscalReceiptType: SINGLE_DONATION`.
9. **Unknown fields are rejected.** Send only the fields of the request schema; a 400 lists every problem in `message`. The query parameters `search` and the `include…` flags are optional: leave them out when you do not need them, and send `search` only with 3 characters or more.
10. **Paginate the lists that take a `cursor`** (donations, votes, donors, campaigns, charities, selections, recurring donations, invoices, fiscal receipts and more): `limit` goes from 1 to 100, `cursor` is the id of the last item of the previous page, and the answer is a plain array. Send `limit` explicitly and loop until a page comes back shorter than it. Webhook logs (`GET /v1/webhooks/logs`) are read by time window instead: `start` and `end` (the last hour by default) and `limit` up to 500. A few lists, like `GET /v1/webhooks`, return everything at once.
11. **Honour `Retry-After` on a 429.** Wait the number of seconds it gives, then send the call once more. Never retry in a loop.

## The core flow

1. `POST /v1/authentication` (Basic auth) for a token.
2. Once: `GET /v1/charities` to pick the charities to offer, `POST /v1/charities-selections` with a `name` (2 to 100 characters) and their ids in `charityIds`, then `POST /v1/campaigns` with a `name` and the `charitiesSelectionId`, then `POST /v1/campaigns/{campaignId}/activate`. A campaign is created with status `PENDING`; without a selection it cannot be activated, and activation needs an active monthly subscription on the account that is billed (its parent account when the parent pays).
3. For each event in the product: `POST /v1/donations` with `campaignId`, `amount` and `uniqueExternalId`.
4. When the user picks a charity, show them the charities of the selection (`GET /v1/charities-selections/{charitiesSelectionId}` with `includeCharities`), then `POST /v1/donations/{donationId}/claim` with `charityId`. Or pass `charityId` on creation if it is already known.

An unclaimed donation is assigned automatically when it expires or when its campaign closes: no donation is lost.

## Use cases

Before writing code, read https://www.charitips.com/docs/use-cases.md and pick the use case that matches the product. For each one it gives who pays, what starts the donation, the calls, the webhooks, what the account needs, the other scenarios the same flow covers, its page, and the build spec of its demo: a made-up site walked through screen by screen with the call of each step. Read the page of that use case, and its build spec when it has one. If no use case matches, build on the core flow: every flow is a campaign, donations, and a charity someone picks.

If the product serves businesses that each run their own giving (a marketplace, a platform for companies, an agency), read [Account hierarchy](https://www.charitips.com/docs/concepts/account-hierarchy.md) first. Each business gets a child account under yours, and your credentials act on all of them: pass the child's `accountId` when you set something up for it or read its data. Creating a child account needs the account hierarchy feature (`accountHierarchy`) on the plan, otherwise it answers `402 Plan upgrade required`.

How the objects behave is in the concept pages: [Campaigns](https://www.charitips.com/docs/concepts/campaigns.md), [Donation lifecycle](https://www.charitips.com/docs/concepts/donation-lifecycle.md) and [Billing and fiscal receipts](https://www.charitips.com/docs/concepts/billing-and-receipts.md).

## When a call fails

Every error is JSON with a `message`. Most also carry `statusCode` and `error`; some carry a `code` instead, like `ACCOUNT_CLOSED` or `INSUFFICIENT_CAMPAIGN_BUDGET`. Branch on the HTTP status of the response, then on `code` or `message`. Fix the cause, do not retry blindly: only a 401 (once, with a new token), a 429 (once, after `Retry-After`) and a 500 whose message names no state (once, with the same `uniqueExternalId`) are worth retrying. An id from another account is treated as unknown: 404 when it is in the path, 400 `Bad Request` when it is in the body or the query. Never 403.

- `Invalid credentials`: The client id or secret is wrong, or the pair belongs to the other environment: sandbox credentials start with `test_` and only work on api.sandbox.charitips.com. Send them as Basic authentication (`-u id:secret`). See https://www.charitips.com/docs/get-started/sandbox.md.
- `Unauthorized`: The access token is missing, expired or invalid. Create a new one with your client id and secret, send it as `Authorization: Bearer <accessToken>`, then retry once. Sandbox tokens only work on api.sandbox.charitips.com. See https://www.charitips.com/docs/get-started/authentication.md.
- `Account closed`: The account behind these credentials is closed: no token is issued and every call is refused, reads included. Contact Charitips to reopen it. See https://www.charitips.com/docs/api-reference/troubleshooting.md#calls-answer-403-account-not-active-account-not-validated-or-account-closed.
- `Account not active`: The account behind these credentials has not finished onboarding, so no token is issued. Complete the onboarding in the dashboard, or contact us. See https://www.charitips.com/docs/api-reference/troubleshooting.md#calls-answer-403-account-not-active-account-not-validated-or-account-closed.
- `No charity selection linked to this campaign`: Create a charities selection with at least one charity, set it on the campaign with `charitiesSelectionId`, then activate. See https://www.charitips.com/docs/api-reference/create-charities-selection.md.
- `No budget set for this campaign`: A campaign with `amountType: FIXED_AMOUNT` needs a `budget` in cents, and the API cannot add one after creation. Create the campaign again with its `budget`, then activate it. See https://www.charitips.com/docs/api-reference/create-campaign.md.
- `Campaign budget exceeds payment card amount limit`: The amount to charge (the budget, the usage not billed yet and the fees) is above what the account's payment card can be charged at once. Create the campaign with a lower budget, or switch to another payment method, such as a bank transfer, in the dashboard, under Settings > Billing. The sandbox never returns this error. See https://www.charitips.com/docs/api-reference/create-campaign.md.
- `Campaign budget exceeds SEPA Direct Debit amount limit`: The amount to charge (the budget, the usage not billed yet and the fees) is above what a SEPA direct debit can take at once. Create the campaign with a lower budget, or switch to another payment method, such as a bank transfer, in the dashboard, under Settings > Billing. The sandbox never returns this error. See https://www.charitips.com/docs/api-reference/create-campaign.md.
- `Invoice amount <amount_due> is over the SDD limit <SDD_AMOUNT_LIMIT>`: The budget of the campaign is invoiced at activation, and the invoice is above what a SEPA direct debit can take at once. Create the campaign with a lower budget, or switch to another payment method, such as a bank transfer, in the dashboard, under Settings > Billing. The sandbox never returns this error. See https://www.charitips.com/docs/api-reference/create-campaign.md.
- `Invoice amount <amount_due> is over the payment card limit <PAYMENT_CARD_AMOUNT_LIMIT>`: The budget of the campaign is invoiced at activation, and the invoice is above what the payment card can be charged at once. Create the campaign with a lower budget, or switch to another payment method, such as a bank transfer, in the dashboard, under Settings > Billing. The sandbox never returns this error. See https://www.charitips.com/docs/api-reference/create-campaign.md.
- `No active subscription found`: The account has no active monthly subscription, so the campaign cannot be activated. Contact us if you sandbox account has no subscription. See https://www.charitips.com/docs/overview/plans.md.
- `Missing payment method`: The account that pays for the donations (your (parent) account or a child account if they are billed directly) has no payment method. Add one in the dashboard, under Settings > Billing, then retry. On the sandbox, creating a single donation skips this check, but other calls can still return it, like activating a FIXED_AMOUNT campaign that is billed on order. See https://www.charitips.com/docs/concepts/billing-and-receipts.md#payment-methods.
- `Campaign has ended.`: The campaign is COMPLETE or CANCELED: nothing can be created, claimed or cast on it any more. Use an active campaign. See https://www.charitips.com/docs/api-reference/list-campaigns.md.
- `Campaign is waiting for payment`: The fixed budget of the campaign has been invoiced and is not paid yet. Pay the invoice, then activate. See https://www.charitips.com/docs/api-reference/list-invoices.md.
- `Account not validated`: The account behind your credentials has not finished onboarding. Complete it in the dashboard, or contact us. See https://www.charitips.com/docs/api-reference/troubleshooting.md#calls-answer-403-account-not-active-account-not-validated-or-account-closed.
- `Forbidden`: Your credentials cannot perform this action on this resource. An id from another account never answers 403: it is treated as unknown, with a 404 in the path or a 400 `Bad Request` in the body or the query. See https://www.charitips.com/docs/api-reference/errors.md.
- `Not Found`: No resource with this id on your account and environment. An id that belongs to another account answers 404 too when it is in the path. Ids from the sandbox do not exist in production. See https://www.charitips.com/docs/get-started/sandbox.md.
- `Campaign is a DISTRIBUTION one. Only votes can be created`: On a DISTRIBUTION campaign, people vote on a budget: create a vote, not a donation. See https://www.charitips.com/docs/api-reference/create-vote.md.
- `donor is required for EMAIL campaigns.`: EMAIL campaigns send the donation to someone: pass `donor` with at least `email` and `firstName`. See https://www.charitips.com/docs/api-reference/create-donation.md.
- `Both donor.email and donor.firstName are required for email campaigns`: Pass both `donor.email` and `donor.firstName`. See https://www.charitips.com/docs/api-reference/create-donation.md.
- `donor is required for SLACK campaigns.`: SLACK campaigns send the donation in Slack: pass `donor` with `slackId` and `firstName`. See https://www.charitips.com/docs/api-reference/create-donation.md.
- `Both donor.slackId and donor.firstName are required for slack campaigns`: Pass both `donor.slackId` and `donor.firstName`. See https://www.charitips.com/docs/api-reference/create-donation.md.
- `Bad Request`: The `campaignId` does not exist on your account and environment. Ids from the sandbox do not exist in production. See https://www.charitips.com/docs/api-reference/errors.md.
- `Insufficient campaign budget.`: This donation would take the campaign over its budget. Create a smaller donation, or use another campaign: the API does not change the budget of an existing campaign. See https://www.charitips.com/docs/api-reference/errors.md.
- `A field is missing, has the wrong type, or is not part of the request schema.`: `message` lists every problem. Unknown fields are rejected, not ignored: remove them rather than sending extra data. See https://www.charitips.com/docs/api-reference/errors.md.
- `Campaign has to be activated first.`: Activate the campaign once it has its charities selection, then retry. See https://www.charitips.com/docs/api-reference/activate-campaign.md.
- `Only recurring donations can be created for recurring campaigns.`: This campaign has a recurring frequency: create a recurring donation. See https://www.charitips.com/docs/api-reference/create-recurring-donation.md.
- `Unique constraint failed on uniqueExternalId`: A resource with this uniqueExternalId already exists: your previous call succeeded. Fetch it with the list endpoint filtered by uniqueExternalId (donations, votes, donors) instead of creating it again; for recurring donations, keep the id you received at creation. See https://www.charitips.com/docs/api-reference/list-donations.md.
- `Lead is required`: The campaign collects the donor's details at the claim: pass `lead` with the fields enabled in the campaign's `leadCollectionOptions` and `hasAcceptedTerms` set to true. See https://www.charitips.com/docs/api-reference/claim-donation.md.
- `Lead has to accept terms and conditions`: Set `lead.hasAcceptedTerms` to true once the person has accepted the terms. See https://www.charitips.com/docs/api-reference/claim-donation.md.
- `Invalid lead information`: A field enabled in the campaign's `leadCollectionOptions` (fullname, companyName, email, phone or custom) is missing from `lead`. See https://www.charitips.com/docs/api-reference/claim-donation.md.
- `Lead collection is not enabled for this campaign`: The campaign does not collect leads: remove `lead` from the claim, or create the campaign with `withLeadCollection` and `leadCollectionOptions`. See https://www.charitips.com/docs/api-reference/create-campaign.md.
- `Donation already claimed`: The donation is no longer waiting for a claim: it is already linked to a charity, by your previous claim or automatically, or it was canceled. Read the donation: `status` and `charityId` tell which. See https://www.charitips.com/docs/api-reference/get-donation.md.

Every other error, with its fix, is on https://www.charitips.com/docs/api-reference/errors.md.

## Before you say it works

1. Run the flow once on the sandbox and show the user the responses of the create and claim calls.
2. Replay the create call with the same `uniqueExternalId` and show that it returns 409, not a second donation.
3. If the project receives webhooks, show one delivery handled twice without a double effect, and one delivery with a bad signature rejected.
4. Check that no credential or token appears in the code or the logs.
