List fundraisers
A paginated list of public campaigns, newest first. No authentication; the result is the same whoever asks. Only published campaigns (active or ended) with visibility: public are listed — drafts, campaigns awaiting review, paused, rejected, unlisted and private campaigns never appear here, whatever is asked for — and deleted campaigns are excluded. Each item is a campaign card (FundraiserCard); fetch the detail read for the full campaign. Card text is translated into the reader's language (lang, then the language cookie, then Accept-Language) where a translation exists.
Near a point. With near=<lat>,<lng> the list holds only the campaigns whose city is within radius_mi miles (default 20) of that point, nearest first and then most raised, and each item carries distance_mi. Every other filter still applies, and so do the public-only rules above. A campaign's point is its CITY's centroid, geocoded on the server from the free-text location; a campaign whose location has no city-level point yet is not in a near list. For the cities to offer a picker, read GET /fundraisers/cities.
Only the parameters below are accepted. Any other query parameter is ignored.
Parameters
Query Parameters
active — live campaigns whose end date has not passed; closed — ended campaigns plus live ones past their end date; ended — the same as closed; all — both (the default). Any other value answers 400 with { "error": "Invalid status", "allowed": [...] }.
"active""closed""ended""all""all"Filter by category — its id, slug or name all match.
Free-text search over title, summary, story, category and location — the same match GET /search?scope=campaigns uses. Matches are ranked first.
true for projects only, false for fundraisers only; omit for both.
raised sorts by most raised first. Omit for newest first.
"raised"Language to translate card text into.
"en""ru""uk""es"Page size, 1–100. A larger value is treated as 100; a missing, zero, negative or non-numeric value as 20.
110020Number of campaigns to skip, 0 or more. A negative or non-numeric value is treated as 0.
00<lat>,<lng> in decimal degrees, e.g. 38.5816,-121.4944: latitude −90..90, longitude −180..180. Lists only the campaigns within radius_mi of the point, nearest first, then most raised (this order replaces sort and the search rank), each with distance_mi. Anything that is not two numbers in range — including an empty value or the parameter sent twice — answers 400 { "error": "invalid_near" }.
"38.5816,-121.4944""^\\s*[+-]?(\\d+(\\.\\d*)?|\\.\\d+)\\s*,\\s*[+-]?(\\d+(\\.\\d*)?|\\.\\d+)\\s*$"Radius in miles around near, 1–100, default 20. A larger value is treated as 100, a smaller one as 1, and a non-numeric one as 20. Ignored without near.
110020Responses
Paginated list of campaign cards
Create fundraiser
Create a new fundraising campaign.
Send status: "draft" to save a draft, which skips the publish gate. Any other status, including an omitted one, runs the publish gate (profile readiness, an image, reasonability and AI review), and a flagged campaign lands pending for review. Note that an omitted status that passes the gate is stored as draft, not active. Send status: "active" to publish.
Requires a bearer session and is gated by the features.fundraiser_creation flag. Publishing requires a verified email address. A caller whose email is not yet verified may still create a draft (status: "draft" sent explicitly) and may hold at most 5 drafts. Past that the answer is 403 with code UNVERIFIED_DRAFT_LIMIT. Any other status from an unverified caller answers 403 with code EMAIL_NOT_VERIFIED. A failing gate answers 403, not 401.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Request Body
Responses
Fundraiser created
List cities with active fundraisers
Every city that has at least one active public campaign, for a "near" city picker: one row per city, with how many active public campaigns it has and a representative point to pass to GET /fundraisers?near=<lat>,<lng>. No authentication.
Active means what GET /fundraisers?status=active lists: status active, end date not passed, visibility: public, not deleted. Cities come from a server-side, city-level geocode of each campaign's free-text location; campaigns whose location has no city (not yet geocoded, not a place, or a whole state or country) are not counted. lat/lng is the average of that city's campaigns' points, which are all the city's centroid, to 2 decimals. Sorted by count, most first, then by label. label is "City, REGION" in the US and "City, Country" elsewhere. Cached for up to 5 minutes.
Responses
Cities with active public campaigns
Get fundraiser
Retrieve a single fundraiser by UUID — the stored row, without the joined owner and raised figures the slug read adds. Authentication is optional and widens what you can see: a campaign that is not active, paused or ended, is private, or has been deleted, is returned to its owner and answers 404 to everyone else. An unlisted campaign is readable with its link. The owner also gets trustStatus and the private fields they entered, such as beneficiary_contact; every other caller, signed in or not, gets the campaign without them.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Query Parameters
Overlay the stored translation for this language, when one exists.
"en""ru""uk""es"Responses
Fundraiser details
Delete fundraiser
Soft-deletes a fundraiser (sets deleted_at). Only the owner may delete. A campaign that has collected funds cannot be deleted and answers 400. Once deleted, GET /fundraisers/{id} and GET /fundraisers/slug/{slug} answer 404 to everyone but its owner.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Responses
Fundraiser soft-deleted
Update fundraiser
Update fundraiser details. Only the owner can update. Setting status is how a draft is published (active) or sent for review (pending). Publishing runs the same gate as creation — profile readiness, at least one image, reasonability and AI review — and a flagged campaign lands pending. A campaign that has collected money cannot go back to draft.
The caller's email must be verified, with one exception: an unverified caller may edit a campaign that is currently draft, as long as the body sends no status or sends status: "draft". Moving a draft to any other status, or editing a campaign that is not a draft, answers 403 with code EMAIL_NOT_VERIFIED.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Request Body
Responses
Fundraiser updated
Get fundraiser by slug
Retrieve a fundraiser using its URL-friendly slug, with the owner, category name, raised figures and share count joined in. Authentication is optional and widens what you can see, exactly as on GET /fundraisers/{id}: unpublished, private and deleted campaigns, the private fields such as beneficiary_contact, and trustStatus are for the owner only.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
Query Parameters
Overlay the stored translation for this language, when one exists.
"en""ru""uk""es"Responses
Fundraiser details
Check slug availability
Check if a fundraiser slug is available. Every campaign counts, including drafts and soft-deleted ones.
Parameters
Path Parameters
Query Parameters
A campaign id to ignore — pass the campaign being edited so its own slug reads as available.
"uuid"Responses
Availability status
Get fundraiser statistics
Aggregate totals for one campaign. Readable exactly when GET /fundraisers/{id} is: a campaign that is not active, paused or ended, is private, or has been deleted answers 404 to everyone but its owner. Authentication is optional.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Responses
Campaign statistics
Get campaign stats (broken)
Not available: currently answers 500 for every campaign. Use GET /fundraisers/{id}/stats instead.
Intended as a public stat-tile read: raised and goal (cents), donor, update and view counts, dates and days left.
Parameters
Path Parameters
"uuid"Responses
Campaign stats (bare object; not currently reachable)
Run a pre-publish trust assessment
Runs the full trust assessment the platform applies at publish time, without publishing: profile and campaign blockers, suggestions, a trust score, an AI analysis of the story, and the moderation decision it would lead to. No request body. Campaign owner only.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Responses
Assessment (bare object)
Get a campaign's lifecycle timeline
Lifecycle events (created, submitted for review, approved, rejected, updated, update posted, goal reached, deleted), newest first, with who acted. Campaign owner only; works for soft-deleted campaigns too.
Actions taken by FundlyHub staff appear with role: "admin" and null id, name and email.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Responses
Timeline (unwrapped)
Report a campaign
Flags an active campaign for moderator review. One report per user per campaign: reporting again replaces the earlier reason and details. Requires a verified email address.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Request Body
Responses
Report recorded
Contact the organizer
Sends a message to the campaign's organizer by email. The organizer receives it with the sender's email as the reply address and answers by replying, so the organizer's own address is never revealed unless they reply. Authentication is optional: anyone who can read the campaign may write, with the same visibility rule as GET /fundraisers/{id} (a campaign hidden from the caller answers 404). Limited to five messages an hour per client address and, when signed in, per account. A message with more than three links is refused, and the name may contain none.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Request Body
Responses
The message was accepted for delivery.
Get the featured donor for a campaign
Feeds the campaign page's "{name} and N others have donated" row: one featured donor and up to three faces, chosen from the latest 100 paid, non-anonymous gifts. Authentication is optional and only changes WHO is featured: a signed-in viewer sees people they follow, or who follow them, first. Only public campaigns that are active, paused or ended return donors; anything else returns empty.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
The campaign's UUID; anything else answers 400.
"uuid"Responses
Featured donor (bare object)
Get related campaigns
Four lists of other people's live, public campaigns for the discovery rail at the bottom of a campaign page: same category (similar), same US state (nearby), 70–99% funded (almost) and newest (recent). An empty list means that tab is not shown. Public.
Titles and summaries are in the reader's language (?lang=, then the locale cookie, then Accept-Language) when a translation exists; when a language is resolved, each card also carries translation_source and, where the text was replaced, original_title / original_summary.
Parameters
Path Parameters
The campaign's UUID; anything else answers 400.
"uuid"Query Parameters
Cards per list, clamped to 1–12.
11212"en""ru""uk""es"Responses
The four lists (bare object)
Get a campaign's outcome report
The creator's published account of what the money did. Returns { "report": null } (not 404) when there is no report, when it is still a draft, and when FundlyHub has hidden it; the three cases are deliberately indistinguishable. Authentication is accepted and does not change the report; owners read their draft from /mine. The campaign itself is readable exactly when GET /fundraisers/{id} is: a campaign that is not active, paused or ended, is private, or has been deleted answers 404 to everyone but its owner.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Responses
The published report, or null
Save or publish the outcome report
Creates or replaces the campaign's single outcome report, and with publish: true publishes it in the same call. Publishing is one-way: a published report stays published on later saves, and publishedAt keeps its first value. Only the campaign's owner may write it. The body is sanitised as rich text; the title is plain text. Shares the media-upload rate limit (30 per 15 minutes). Audit-logged.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Request Body
Responses
The saved report
Get my campaign's outcome report, draft included
The owner's view of the outcome report: a draft is returned, and a hidden report is returned with hiddenAt set. { "report": null } when none has been written. Campaign owner only.
Authorizations
In the browser, authentication rides on the httpOnly session cookies set by /cognito/signin or the Google / Apple sign-in at /cognito/oauth/{provider}. For scripts and for Swagger UI testing, paste an API key (fh_live_…, created with POST /api-keys); a Cognito JWT is accepted too. Sign-in does not return a token in its body.
Parameters
Path Parameters
"uuid"Responses
The report, or null
Get aggregate campaign stats
Counters for the /causes stat tiles, over public, non-deleted campaigns in active or ended status, filtered the same way as the listing. "Closed" means ended, or active with a past end_date. Every figure, total_donors and topCategories included, covers the same filtered set.
Counts and sums are returned as numeric strings.
No authentication.
Parameters
Query Parameters
"true""false""1""0"Category slug, id or name.
Responses
The aggregates (bare object)