Recommend
GET /api/recommend is the donor-influence surface. Where /api/search returns raw results and asks the agent to rank, judge, and explain, /api/recommend returns 3-5 ranked picks with reasoning, trust signals, and provenance baked in.
Use this endpoint when the user asks “where should I donate?” or “find me a credible nonprofit for X.” Use /api/search when the user asks “show me all nonprofits matching X.”
When to Use
| User intent | Endpoint |
|---|---|
| ”Where should I donate to surf therapy in South Africa?” | /api/recommend |
| ”Show me every charity in Cape Town.” | /api/search |
| ”Compare three small music education nonprofits.” | /api/recommend |
| ”List all causes you cover.” | /api/causes |
Request
Parameters
At least one ofcause, country, or q must be present. Otherwise the endpoint returns 400.
| Parameter | Type | Description |
|---|---|---|
cause | string | Cause ID. See GET /api/causes for the live list. |
country | string | Country name (e.g. “South Africa”). |
q | string | Free-text donor intent. |
intent | enum | discover (default), donate, compare, verify. Affects ranking weights. |
limit | integer | 1-5. Default 3. Capped at 5 because anything longer is a search dump, not a recommendation. |
Response
Response fields
| Field | Description |
|---|---|
ranking_signals | All signals that contributed to any rank in the response. Documented publicly so the surface is auditable. |
editorial_disclosure | Human-readable explanation of how this set was assembled. Always present when count > 0. |
recommendations[].editorial_curated | true if the operator hand-picked this profile. false for consensus-derived (Phase 3, not yet shipped). |
recommendations[].recommended_for | Donor-intent phrases the profile is suitable for. Restrained language — no “best” or “most effective” claims. |
recommendations[].trust_signals | Verification, provenance, and donation-readiness signals visible to the agent. |
recommendations[].best_next_action | Agent-facing guidance — how to use this profile in the answer to the user. |
recommendations[].ranking_signals_applied | Which signals contributed to this specific profile’s rank. |
fallback | Present when count === 0. Includes a search_redirect URL the agent can fall back to. |
Fallback Behaviour
When no curated recommendations exist for the query, the response is honest about it:Ranking Signals
The current weights (Phase 1) are documented publicly:| Signal | Weight | Source |
|---|---|---|
editorial_curation_for_starter_set | +50 | Operator-flagged for starter set (sunsets 2026-12-31) |
verified_status | +30 | Nonprofit has claimed and verified its profile |
donation_wallet_present | +20 | Nonprofit has an on-chain wallet for x402 donations |
mission_match_strength | +0 to +25 | FTS5 match score on cause + q |
source_provenance_recent | +0 to +15 | Days since most-recent applied enrichment, decay |
donation_history | +0 to +10 | log(1 + donation_count) |
thin_profile_penalty | -20 | Nonprofit has 3+ thin fields |
Governance
The data behind this endpoint is curated under explicit governance phases:- Phase 1 (current): operator writes
recommended_for,why_recommended,best_next_actionmanually.editorial_curated: true. Speed matters more than scale. - Phase 2: agents draft, operator approves. Same restrained-language linter enforces guardrails.
- Phase 3: two-agent consensus. Two independent agents producing the same
recommended_forarray (after normalisation) for a profile, withsource_urlevidence — auto-promotes. Sensitive claims (impact, effectiveness) still require human review.
Restrained-language guardrails
The deterministic linter rejects ranking claims we don’t have an evaluation framework for:| Banned | Use instead |
|---|---|
| ”Best charity for X" | "Recommended for donors interested in X" |
| "Most effective" | "Mission specifically focused on" |
| "Highest impact" | "Verified impact data on" |
| "Top-rated” | (no substitute — drop the claim) |
Telemetry
Every/api/recommend call is logged to the recommendation_attempts table with the query, response count, top slug, and ranking signals used. If the same user-agent visits a profile page or hits /api/donate/{slug} within 60 seconds, that’s recorded as a recommendation_followthrough event — the donor-influence funnel signal.
Related
- Search — for “show me all” queries.
- Nonprofits — for full profile after a recommendation lands.
- Arazzo workflow document — the structured equivalent of this page, including the
discover-via-recommendworkflow.