post_donations_create_checkout_session

Changes data · you confirm first

Calls POST /api/donations/create-checkout-session as the signed-in person · REST reference

Create a Stripe Checkout session for a public gift

Unauthenticated donate flow used by the marketing site. Creates a Stripe Checkout session and returns its redirect URL. NOTHING is persisted here — the (:Donation) is written by POST /webhooks/stripe on payment_intent.succeeded, the single idempotent recorder — so a 201 means "the donor can be sent to Stripe", not "the gift was recorded". The organization a gift is attributed to is never read from the body on this route (it is unauthenticated, so a body-supplied org id would let anyone credit any organization); use POST /api/donations/org-checkout-session for an attributed gift. UNIT WARNING - amount is in DOLLARS here (a decimal number), not integer cents, as it is on /org-checkout-session, which takes the same body. The handler multiplies by 100 for Stripe and stamps the fee coverage on the PaymentIntent as integer cents for the webhook.

Arguments

ArgumentTypeDescription
bodyJSONobjectrequiredThe request body, as a JSON object. Its fields are listed below.

Fields of body

FieldTypeDescription
amountnumberrequiredGift amount in DOLLARS, not cents. Must be greater than zero. Any falsy value (including 0) is rejected with 400.
anonymity"NAMED" | "ANONYMOUS" | "FULLY_ANONYMOUS"Upper-cased before use. FULLY_ANONYMOUS collects no donor identity, waives the name/email requirement, sends no PII to Stripe and gets no receipt or certificate. ANONYMOUS still records identity but hides it from responses.
coverProcessingFeesbooleanAdds a second Stripe line item that GROSSES UP the charge to cover 2.9% + $0.30 of the total, and stamps processing_fee_cents on the PaymentIntent so the webhook excludes it from the 70/30 split.
donorInfoobjectRequired unless anonymity is FULLY_ANONYMOUS, in which case it is ignored.
donorInfo.addressstring
donorInfo.citystring
donorInfo.emailstring (email)
donorInfo.namestring
donorInfo.phonestring
donorInfo.zipCodestring
recurringbooleanSaves the card off-session and creates a Stripe Customer. The schedule is driven by this platform, not by Stripe subscriptions.
recurringInterval"DAILY" | "WEEKLY" | "MONTHLY" | "ANNUAL"Case-insensitive. Required with recurring unless recurringRule is given.
recurringRulestringAn RRULE string, the advanced alternative to recurringInterval.

Example call

A client sends this over the MCP session; Claude and other agents build it for you. The values are placeholders — the shape is real.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "post_donations_create_checkout_session",
    "arguments": {
      "body": {
        "amount": 1,
        "anonymity": "NAMED",
        "coverProcessingFees": false,
        "donorInfo": {
          "address": "string",
          "city": "string",
          "email": "name@example.org",
          "name": "string",
          "phone": "string",
          "zipCode": "string"
        },
        "recurring": false,
        "recurringInterval": "DAILY",
        "recurringRule": "string"
      }
    }
  }
}
Confirmation
The client shows the person the exact request and waits. Nothing runs until they tick Make this change. See Reading and changing.

Result

On success (HTTP 201) the tool returns one text item holding the API's JSON, pretty-printed.

Checkout session created. Redirect the browser to url.

json
{
  "sessionId": "string",
  "url": "https://example.org"
}

Fields

FieldTypeDescription
sessionIdstringStripe Checkout session id (cs_...).
urlstring (uri)Stripe-hosted checkout page.

When it fails

A failed call returns isError: true with the API's message as text. A change the person declines, or lets time out, also comes back this way and nothing changes.

400

The request was malformed or failed a guard.

What the model is shown

This is the tool exactly as the server lists it in tools/list. The description starts with the REST call it makes.

json
{
  "name": "post_donations_create_checkout_session",
  "description": "POST /api/donations/create-checkout-session — Unauthenticated donate flow used by the marketing site. Creates a Stripe Checkout session and returns its redirect URL. NOTHING is persisted here — the (:Donation) is written by POST /webhooks/stripe on payment_intent.succeeded, the single idempotent recorder — so a 201 means \"the donor can be sent to Stripe\", not \"the gift was recorded\". The organization a gift is attributed to is never read from the body on this route (it is unauthenticated, so a body-supplied org id would let anyone credit any organization); use POST /api/donations/org-checkout-session for an attributed gift. UNIT WARNING - `amount` is in DOLLARS here (a decimal number), not integer cents, as it is on /org-checkout-session, which takes the same body. The handler multiplies by 100 for Stripe and stamps the fee coverage on the PaymentIntent as integer cents for the webhook.\n\nThis changes data. The person is asked to confirm it before it runs, and nothing happens if they decline.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "body": {
        "type": "string",
        "description": "The JSON request body: { amount*: number (Gift amount in DOLLARS, not cents.); anonymity: one of \"NAMED\" | \"ANONYMOUS\" | \"FULLY_ANONYMOUS\" (Upper-cased before use.); coverProcessingFees: boolean (Adds a second Stripe line item that GROSSES UP the charge to cover 2.9% + $0.30 of the ...); donorInfo: { address: string; city: string; email: string; name: string; phone: string; zipCode: string } (Required unless anonymity is FULLY_ANONYMOUS, in which case it is ignored.); recurring: boolean (Saves the card off-session and creates a Stripe Customer.); recurringInterval: one of \"DAILY\" | \"WEEKLY\" | \"MONTHLY\" | \"ANNUAL\" (Case-insensitive.); recurringRule: string (An RRULE string, the advanced alternative to recurringInterval.) }"
      }
    },
    "required": [
      "body"
    ]
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": true,
    "idempotentHint": false,
    "openWorldHint": false
  }
}