Version 0.1.0. Early-access API behind the ad-targeting assistant: rank where to advertise by opportunity, and talk to the assistant directly. Endpoints and shapes may change while the product is in early access.
Base URL: https://valcour-ad-targeting.vercel.app
/api/v1/ai/ad-targeting/opportunityRank geographies by ad-targeting opportunity.
Scores geographies as reach × favorability × audience-fit ÷ (1 + ad-saturation), built from public data sources (Census ACS, Meta Ad Library, Google Political Ads, FEC). Reach (audience size) is a first-class term so large markets are not zeroed out by a low percentage. Fail-soft per source: any source returning nothing is listed in data_sources_unavailable, and a best-effort ranking is still produced.
statestring · nullableracestring · nullablecandidatesarray · nullablestringlimitinteger · min 1 · max 500200 Ranked geographies with scores, confidence bands, and source provenance.racestring · nullablestatestring · nullableresultsrequiredarraygeographyrequiredstringopportunity_scorerequirednumberci_lowrequirednumberci_highrequirednumbercompetitivenessrequirednumber · min 0 · max 1persuadable_densityrequirednumber · min 0 · max 1ad_saturationrequirednumber · min 0 · max 1whyrequiredstringcomponentsrequiredobjectcompetitiveness_sourcerequiredstringdata_sources_usedrequiredarraystringdata_sources_unavailablerequiredarraystringnotesrequiredarraystring401 unauthorized — missing or invalid bearer token422 invalid request body429 rate limitedcurl -X POST \
'https://valcour-ad-targeting.vercel.app/api/v1/ai/ad-targeting/opportunity' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{ /* see request body schema above */ }'/api/assistant/chatAsk the targeting assistant a question (streaming).
Same-origin proxy to the assistant. Send a message; the response is a Server-Sent Events (SSE) stream of the assistant's reply, including any tool runs (such as the opportunity ranking). This is the endpoint the public /chat page uses. Unauthenticated and rate-limited per IP.
messagerequiredstring · min length 1 · max length 8000conversation_idstring · nullablepage_contextobject200 text/event-stream of assistant events (text deltas, tool_start, tool_result).400 invalid input429 rate limited503 assistant temporarily unavailablecurl -X POST \
'https://valcour-ad-targeting.vercel.app/api/assistant/chat' \
-H 'Content-Type: application/json' \
-d '{ /* see request body schema above */ }'/api/healthDB-deep liveness probe.
200 Service healthy — database reachable.503 Service unhealthy — database unreachable.curl -X GET \ 'https://valcour-ad-targeting.vercel.app/api/health'
statestring · nullableracestring · nullablecandidatesarray · nullablestringlimitinteger · min 1 · max 500racestring · nullablestatestring · nullableresultsrequiredarraygeographyrequiredstringopportunity_scorerequirednumberci_lowrequirednumberci_highrequirednumbercompetitivenessrequirednumber · min 0 · max 1persuadable_densityrequirednumber · min 0 · max 1ad_saturationrequirednumber · min 0 · max 1whyrequiredstringcomponentsrequiredobjectcompetitiveness_sourcerequiredstringdata_sources_usedrequiredarraystringdata_sources_unavailablerequiredarraystringnotesrequiredarraystringgeographyrequiredstringopportunity_scorerequirednumberci_lowrequirednumberci_highrequirednumbercompetitivenessrequirednumber · min 0 · max 1persuadable_densityrequirednumber · min 0 · max 1ad_saturationrequirednumber · min 0 · max 1whyrequiredstringcomponentsrequiredobjectmessagerequiredstring · min length 1 · max length 8000conversation_idstring · nullablepage_contextobject