Partner API Documentation
Everything you need to integrate Fund My Squad fundraising into your platform. Machine-readable version available at /llms.txt
Implementation Overview
Fund My Squad (FMS) is a fundraising platform for youth sports. The Partner API lets external platforms (league management, team apps, registration software) offer built-in fundraising to their users. Partners earn commission on every donation processed through fundraisers created via their integration.
Integration Flow:
┌─────────────────────────────────────────────────────────────────┐
│ PARTNER INTEGRATION FLOW │
└─────────────────────────────────────────────────────────────────┘1. SETUP
Apply at /partners → Get staging API key → Build & test in sandbox
2. CREATE FUNDRAISER (your platform → FMS API)
Your user wants to fundraise
→ POST /partner/v1/fundraisers {title, goalAmount, externalId}
→ FMS returns id, publicUrl, donateUrl
3. COLLECT DONATIONS (donors → FMS hosted page)
Share the donateUrl or embed link
→ Donor visits FMS donation page
→ FMS processes payment via Stripe
4. ENABLE PAYOUTS (fundraiser creator → Stripe Connect)
POST /partner/v1/fundraisers/:id/connect/onboard
→ Redirect user to Stripe onboarding
→ User completes KYC/banking setup
5. TRACK & DISPLAY (FMS API → your platform)
GET /partner/v1/fundraisers/:id → Show progress
GET /partner/v1/fundraisers/:id/donations → Show donors
6. COMMISSION PAYOUT (automatic on each donation)
Donor pays $100 → Stripe fee ~$3.20
→ Platform fee (10%): $10.00
→ Partner commission (e.g. 4%): $4.00
→ FMS keeps: $6.00
→ Fundraiser creator receives: $86.80
Quick Start: 1. Apply at https://fundmysquad.com/partners 2. Once approved, log in to the Partner Portal 3. Generate a staging API key from the API Keys tab 4. Test all endpoints in the Sandbox tab 5. Request a production API key 6. Integrate into your platform and go live
Full machine-readable docs: https://fundmysquad.com/llms.txt
Authentication
All API requests require your partner API key in the x-partner-api-key header:
curl https://api.fundmysquad.com/partner/v1/fundraisers \
-H "x-partner-api-key: fms_partner_abc123..."
Base URL: Always use https://api.fundmysquad.com for all requests.
Environments:
| Key Type | Behavior |
|---|---|
| Staging keys | Requests are automatically routed to the sandbox environment. No real data is created. Response includes x-fms-environment: sandbox header. |
| Production keys | Requests hit the production environment. Real fundraisers, real donations. |
Partners always use the same base URL. The API detects whether your key is staging or production and routes accordingly. Staging key requests never touch the production database.
Create a Fundraiser
POST /partner/v1/fundraisers
Required fields:
title (string) — Fundraiser titlegoalAmount (number) — Goal in dollars (e.g. 5000)externalId (string) — Your platform's unique ID for the team/userOptional fields:
description (string), goalType ("team" or "individual"), category, sportheroImageUrl (string), startsAt, endsAt (ISO 8601)metadata (object) — Arbitrary JSON for your own trackingconnectExternalOwnerId (string) — attach a reusable owner Connect account (see Stripe Connect)Example:
curl -X POST https://api.fundmysquad.com/partner/v1/fundraisers \
-H "x-partner-api-key: fms_partner_abc123..." \
-H "Content-Type: application/json" \
-d '{
"title": "Tigers Spring Travel Fund",
"goalAmount": 5000,
"goalType": "team",
"externalId": "team_8472",
"sport": "baseball",
"endsAt": "2026-06-01T00:00:00Z"
}'
Returns the created fundraiser with its id, publicUrl, and donateUrl.
List Fundraisers
GET /partner/v1/fundraisers
Query parameters:
externalId — Filter by your team/user IDstatus — Filter: active, closed, draftsort — newest, oldest, most_raised, ending_soonlimit (max 100), offset — PaginationExample:
curl "https://api.fundmysquad.com/partner/v1/fundraisers?externalId=team_8472&status=active" \
-H "x-partner-api-key: fms_partner_abc123..."
Get Fundraiser Details
GET /partner/v1/fundraisers/:id
Returns full details including current stats (raised amount, donation count, supporter count, progress %) and the 10 most recent donations.
Lookup by external ID:
GET /partner/v1/fundraisers/by-external-id/:externalId
Update a Fundraiser
PATCH /partner/v1/fundraisers/:id
Updatable fields: title, description, goalAmount, startsAt, endsAt, category, sport, heroImageUrl, externalId, metadata
Only include the fields you want to change. Omitted fields are left unchanged.
curl -X PATCH https://api.fundmysquad.com/partner/v1/fundraisers/abc123... \
-H "x-partner-api-key: fms_partner_abc123..." \
-H "Content-Type: application/json" \
-d '{ "goalAmount": 7500 }'
Close & Reopen
Close a fundraiser:
POST /partner/v1/fundraisers/:id/close
Reopen a closed fundraiser:
POST /partner/v1/fundraisers/:id/reopen
Optionally pass { "endsAt": "2026-08-01T00:00:00Z" } to set a new end date.Donations & Stats
List donations:
GET /partner/v1/fundraisers/:id/donations?limit=50&offset=0
Fundraiser stats (with 14-day trend):
GET /partner/v1/fundraisers/:id/stats
Portfolio summary:
GET /partner/v1/summary
Returns aggregate stats across all your fundraisers: total raised, active/closed counts, unique teams, total donors.Stripe Connect (Payouts)
Onboard a fundraiser creator for payouts:
POST /partner/v1/fundraisers/:id/connect/onboard
Required fields:
returnUrl (string) — Where to redirect after Stripe onboardingOptional fields:
refreshUrl (string) — Where to redirect if the link expiresResponse:
{
"onboardingUrl": "https://connect.stripe.com/...",
"stripeAccountId": "acct_...",
"message": "Redirect the fundraiser creator to onboardingUrl..."
}
Redirect your user to onboardingUrl. After completing Stripe's KYC/banking setup, they'll be redirected to your returnUrl.
Check Connect status:
GET /partner/v1/fundraisers/:id/connect/status
Returns connected (boolean), chargesEnabled, payoutsEnabled, detailsSubmitted.
Commission splits: When a donation is made to a partner-created fundraiser with a connected payout account:
---
Reusable owner Connect accounts
Onboard a payout account once per owner (a team, club, or individual on your platform) and reuse it across many fundraisers — instead of onboarding per fundraiser. Keyed by your externalOwnerId.
POST /partner/v1/connect/onboard{ externalOwnerId, ownerType: "entity" | "individual", email?, returnUrl, refreshUrl? }. Find-or-creates the owner's Connect account and returns { onboardingUrl, connectAccountId }, or { status: "already_connected", connectAccountId } if already done.GET /partner/v1/connect/status?externalOwnerId=...
Returns connected, status, chargesEnabled, payoutsEnabled, detailsSubmitted, connectAccountId.Attach to a fundraiser — either pass connectExternalOwnerId when creating the fundraiser, or link an existing fundraiser:
POST /partner/v1/fundraisers/:id/connect/link
Body: { externalOwnerId }. Sets the fundraiser's payout account to that owner's Connect account.The per-fundraiser /connect/onboard flow above still works for one-off fundraisers.
Product Fundraisers
Sell products (candy, cookie dough, merch) instead of — or alongside — donations.
Turn on the shop: set shopEnabled: true when creating a fundraiser (or PATCH it on later), plus optional shopHeadline and shopDescription. Adding the first product also enables the shop automatically.
curl -X POST https://api.fundmysquad.com/partner/v1/fundraisers \
-H "x-partner-api-key: fms_partner_abc123..." \
-H "Content-Type: application/json" \
-d '{ "title": "Tigers Candy Sale", "goalAmount": 2000, "externalId": "team_8472", "shopEnabled": true }'
Payouts required: a shop only accepts orders once the creator finishes Stripe Connect onboarding. Until then checkout returns PAYOUT_NOT_CONFIGURED.
Three ways to stock a shop: a pre-configured bundle (simplest), individual catalog products by id, or fully custom products you supply & ship.
Catalog & Bundles
Browse the same platform-fulfilled products website users pick from.
List catalog products:
GET /partner/v1/catalog/products
Returns { products: [{ id, title, description, images, minRetailPrice, shippingCost }] }. Use a product's id as platformProductId when adding it.List bundles (curated packs):
GET /partner/v1/catalog/bundles
Returns each bundle with the catalog products it contains.Add a whole bundle in one call:
POST /partner/v1/fundraisers/:id/bundles
Body: { "bundleId": "best-sellers" }. Each product is added at its default price; products already on the fundraiser are skipped (safe to re-run).Requires products:read to browse, products:write to add.
Manage Products
Add a product:
POST /partner/v1/fundraisers/:id/products
What you pass determines the type:
platformProductId — a catalog product by id (FMS fills in title/cost/images & fulfillment; retailPriceCents optional, must be ≥ the catalog minimum)source: "custom" + title, retailPriceCents (optional baseCostCents, shippingCostCents, images) — your own productsource: "printful" or "goody" + externalProductId, title, baseCostCents, retailPriceCentsAll amounts are cents on input. FMS validates the margin and returns an earnings breakdown.
List / update / delete:
GET /partner/v1/fundraisers/:id/products
PATCH /partner/v1/fundraisers/:id/products/:productId
DELETE /partner/v1/fundraisers/:id/products/:productId
Delete hard-removes a product with no orders, otherwise deactivates it.Product Orders
List orders:
GET /partner/v1/fundraisers/:id/orders?status=&source=&limit=50&offset=0
Each order includes product title, buyer, quantity, amount, fulfillment status, and tracking.Single order:
GET /partner/v1/fundraisers/:id/orders/:orderId
Product sales also appear in fundraiser stats (a productSales block + combinedRaisedAmount) and in GET /partner/v1/summary. Requires products:read.
Endpoint Reference
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| POST | /partner/v1/fundraisers | fundraisers:write | Create a fundraiser |
| GET | /partner/v1/fundraisers | fundraisers:read | List all fundraisers |
| GET | /partner/v1/fundraisers/:id | fundraisers:read | Get fundraiser details |
| GET | /partner/v1/fundraisers/by-external-id/:externalId | fundraisers:read | Lookup by external ID |
| PATCH | /partner/v1/fundraisers/:id | fundraisers:write | Update a fundraiser |
| POST | /partner/v1/fundraisers/:id/close | fundraisers:write | Close a fundraiser |
| POST | /partner/v1/fundraisers/:id/reopen | fundraisers:write | Reopen a fundraiser |
| GET | /partner/v1/fundraisers/:id/donations | donations:read | List donations |
| GET | /partner/v1/fundraisers/:id/stats | fundraisers:read | Get fundraiser stats |
| GET | /partner/v1/summary | fundraisers:read | Partner portfolio summary |
| POST | /partner/v1/fundraisers/:id/connect/onboard | fundraisers:write | Start Stripe Connect (per fundraiser) |
| GET | /partner/v1/fundraisers/:id/connect/status | fundraisers:read | Check Connect status (per fundraiser) |
| POST | /partner/v1/connect/onboard | fundraisers:write | Onboard a reusable owner Connect account |
| GET | /partner/v1/connect/status | fundraisers:read | Owner Connect status (by externalOwnerId) |
| POST | /partner/v1/fundraisers/:id/connect/link | fundraisers:write | Attach an owner Connect account to a fundraiser |
| GET | /partner/v1/catalog/products | products:read | List platform catalog |
| GET | /partner/v1/catalog/bundles | products:read | List pre-configured bundles |
| POST | /partner/v1/fundraisers/:id/bundles | products:write | Add a bundle to a fundraiser |
| POST | /partner/v1/fundraisers/:id/products | products:write | Add a product |
| GET | /partner/v1/fundraisers/:id/products | products:read | List products |
| PATCH | /partner/v1/fundraisers/:id/products/:productId | products:write | Update a product |
| DELETE | /partner/v1/fundraisers/:id/products/:productId | products:write | Remove a product |
| GET | /partner/v1/fundraisers/:id/orders | products:read | List product orders |
| GET | /partner/v1/fundraisers/:id/orders/:orderId | products:read | Get an order |
Errors & Rate Limits
Error format:
{ "error": "description of what went wrong" }
| Status | Meaning | |||
|---|---|---|---|---|
| 400 | Bad request — missing or invalid fields | |||
| 401 | Auth failed — bad or expired API key | |||
| 404 | Not found (or not owned by your partner) | |||
| 409 | Conflict — e.g. closing an already-closed fundraiser | |||
| 429 | Rate limit exceeded | |||
| 500 | Server error | Rate limits: 120 requests/minute and 10,000 requests/day per API key. Rate limit headers on every response: | Header | Description |
| -------- | ------------- | |||
| X-RateLimit-Limit | Requests allowed per minute | |||
| X-RateLimit-Remaining | Requests remaining in current window | |||
| X-RateLimit-Reset | Unix timestamp when the window resets | |||
| Retry-After | Seconds until retry (only on 429) |
Key Concepts
External IDs:
The externalId field bridges your platform and FMS. Pass your unique identifier for teams or users. Create multiple fundraisers for the same team and look them all up with one call.
Partner Metadata:
The metadata field is a free-form JSON object. Store league info, coach contacts, season details — FMS preserves it as-is.
Scopes:
| Scope | Grants |
|---|---|
| fundraisers:read | List and view fundraisers |
| fundraisers:write | Create, update, close, reopen |
| donations:read | View donations |
| products:read | View catalog, products, and orders |
| products:write | Add, update, and remove products & bundles |
| * | All permissions |
Sandbox vs Production: Staging API keys create sandbox fundraisers (not public, no real donations). Production keys create real fundraisers that accept real donations.
