Cinco cosas antes de llamar la API
- 84 endpoints públicos agrupados en 5 tags — agents, data, geo, verification, assets.
- Sin auth para lectura. Cada endpoint JSON / CSV / SVG / feed está abierto y con CORS. Las únicas superficies con auth son Stripe checkout y los webhooks.
- OpenAPI 3.1 + MCP. Especificación en /api/openapi.json y /api/openapi.yaml. Servidor MCP con 16+ herramientas en /api/mcp.
- CC-BY-4.0. Atribuye a "ProFix Directory" y lánzalo — uso comercial bienvenido.
- 18 esquemas en
components.schemas— Pro, ProList, City, State, CostGuide, LicenseGuide, BuyerGuide, FAQ, SearchResponse, CorrectionSubmission, ErrorResponse, ProDossier, ProPhotos, MatchResponse, ProPermits.
Convenciones de la API
Autenticación
La mayoría de los endpoints son públicos. Sin API key, sin OAuth. CORS permisivo (Access-Control-Allow-Origin: *). Los endpoints de Stripe checkout y webhook aceptan el header Stripe-Signature. Las rutas administrativas en /api/admin/* requieren un token bearer del editor en el header Authorization: Bearer.
Límites de tasa
No publicamos un límite por API key — las lecturas públicas están cacheadas en el borde y no cuestan nada en repetir. Los endpoints POST de leads, claim y correcciones tienen una compuerta suave por IP (~20 req/min) para frenar abusos. Por encima devolvemos HTTP 429 con Retry-After. Las descargas masivas de /api/all.json deberían cachearse al menos 1 hora.
Cache headers y ETags
Las lecturas usan Cache-Control: public, max-age=3600, s-maxage=86400, stale-while-revalidate=604800. Next.js adjunta un ETag derivado del cuerpo — devuélvelo como If-None-Match en peticiones posteriores y respondemos 304 Not Modified cuando el snapshot no cambió.
Envelope de respuesta
Las respuestas JSON comparten una envoltura estándar: { ok: true, license: "CC-BY-4.0", generated_at, ...payload }. Los errores son { ok: false, error, message } — ver el esquema ErrorResponse. Los CSV siguen RFC 4180 con fila de encabezado.
Descubrimiento agent-native
- Servidor MCP en /api/mcp — HTTP streamable, 16+ herramientas tipadas: find_pros, get_pro, triage_symptom, get_cost_estimate, list_guides, get_active_storm_events y más.
- Manifiesto ai-plugin en /.well-known/ai-plugin.json — manifiesto de plugin ChatGPT / conector Anthropic que apunta a esta OpenAPI.
- ai.txt + llms.txt en /.well-known/ai.txt y /llms.txt — política de acceso para agentes y mapa de contenido para LLMs.
Agentes y descubrimiento
Servidor MCP, espejo OpenAPI/YAML, manifiesto ai-plugin, llms.txt, ai.txt — las superficies que cualquier agente autónomo o motor de IA toca primero.
/.well-known/ai-plugin.jsonChatGPT plugin manifest
ChatGPT plugin / Anthropic connector manifest pointing at this OpenAPI spec. Schema version `v1`, auth `none`, API type `openapi`.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Plugin manifest JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/.well-known/ai-plugin.json"const res = await fetch("https://profixdirectory.com/.well-known/ai-plugin.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/.well-known/ai-plugin.json", timeout=10)
res.raise_for_status()
print(res.json())/.well-known/ai.txtAI agent access policy
Plain-text AI-agent access policy mirroring robots.txt — Spawning.ai ai.txt draft + llmstxt.org convention. Lists allowed agents, disallowed paths, and discovery pointers (llms.txt, MCP, OpenAPI, dataset).
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(ai.txt plain text)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/.well-known/ai.txt"const res = await fetch("https://profixdirectory.com/.well-known/ai.txt");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/.well-known/ai.txt", timeout=10)
res.raise_for_status()
print(res.json())/api/allDiscovery index — every machine-readable surface in one document
Single-fetch agent-discovery payload aggregating the bulk dataset, every JSON/CSV/RSS/iCal feed (via /api/feeds-index.json), the canonical site graph, and every relevant content map. Useful for AI engines that want one URL to crawl. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Discovery index JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/all"const res = await fetch("https://profixdirectory.com/api/all");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/all", timeout=10)
res.raise_for_status()
print(res.json())/api/changelogGit-derived product changelog — paginated JSON (last 90 days)
Paginated, machine-readable feed of every user-facing change (feat/fix/perf) sourced from the live git log over a rolling 90-day window. 50 entries per page, ETag + Cache-Control, scope-aware url hints, and HEAD support. Personal git authors are dropped — every entry is published under the ProFix Editorial Team banner. Paginate with ?page=1..N. Companion HTML pages: /changelog (EN), /es/registro-cambios (ES). CC-BY-4.0.
Parámetros
page(query)tipo:integer1-indexed page number. Defaults to 1.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Changelog JSON page)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/changelog"const res = await fetch("https://profixdirectory.com/api/changelog");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/changelog", timeout=10)
res.raise_for_status()
print(res.json())/api/changelog.jsonNewsroom changelog — machine-readable
JSON companion to /newsroom. Every entry has date, type (research/feature/data/api/design), headline, body, optional url. Sorted newest-first. CC-BY-4.0.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Changelog JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/changelog.json"const res = await fetch("https://profixdirectory.com/api/changelog.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/changelog.json", timeout=10)
res.raise_for_status()
print(res.json())/api/emergency-playbook/{slug}.jsonEmergency playbook JSON companion
Minimal JSON mirror of /emergency/playbooks/{slug}. Returns immediate steps, shutoff guidance, do-not list, who-to-call list, damage mitigation, typical cost band, insurance note, and prevention guidance. CC-BY-4.0. CORS-enabled, 1h cache.
Parámetros
slug(path)requeridotipo:stringEmergency playbook slug, for example burst-pipe-inside.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Emergency playbook JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/emergency-playbook/miller-plumbing-toledo.json"const res = await fetch("https://profixdirectory.com/api/emergency-playbook/miller-plumbing-toledo.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/emergency-playbook/miller-plumbing-toledo.json", timeout=10)
res.raise_for_status()
print(res.json())/api/jsonld/{type}Open JSON-LD feeds — full Schema.org graphs by type
First-class structured-data feeds for AI engines, partners, and structured-data tooling. Supported types: `pros` (LocalBusiness graph for every pro), `cost-guides` (Article graph), `faq` (combined FAQPage), `organization` (ProFix Directory entity), `local-business-index` (top-100 ItemList), `faq-trade-{trade}` (per-trade FAQPage), `breadcrumb-coverage` (BreadcrumbList for /coverage). No auth, 1h CDN cache + 1d stale-while-revalidate.
Parámetros
type(path)requeridotipo:stringJSON-LD feed identifier (see description for valid values)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(JSON-LD graph)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/jsonld/organization"const res = await fetch("https://profixdirectory.com/api/jsonld/organization");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/jsonld/organization", timeout=10)
res.raise_for_status()
print(res.json())/api/markdown-corpusPaginated index of every Markdown-exportable route
JSON metadata listing every available `/api/markdown/{slug}` URL grouped by content type. Pages capped at 5000 entries via `?cursor=` (offset). Use `?type=<contentType>` to filter. Every entry is CC-BY-4.0 sourced from the ProFix Editorial Team.
Parámetros
type(query)tipo:stringOptional content type filter.cursor(query)tipo:integerZero-based offset for pagination.limit(query)tipo:integerPage size. Hard-capped at 5000.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Paginated corpus index JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/markdown-corpus"const res = await fetch("https://profixdirectory.com/api/markdown-corpus");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/markdown-corpus", timeout=10)
res.raise_for_status()
print(res.json())/api/markdown/{slug}Markdown export of a single editorial route
Returns CC-BY-4.0 Markdown with YAML frontmatter for any (contentType, slug) pair covered by the corpus. Use `?type=<contentType>` to disambiguate when a slug exists across multiple types; otherwise the route auto-infers. Strong ETag + Cache-Control. Designed for AI training pipelines and content aggregators.
Parámetros
slug(path)requeridotipo:stringThe route slug (e.g. `plumber`, `furnace-tune-up-cost-toledo`).type(query)tipo:stringContent type. Optional — auto-inferred from slug when omitted.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Markdown text/plain with YAML frontmatter)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/markdown/miller-plumbing-toledo"const res = await fetch("https://profixdirectory.com/api/markdown/miller-plumbing-toledo");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/markdown/miller-plumbing-toledo", timeout=10)
res.raise_for_status()
print(res.json())/api/mcpModel Context Protocol server
Streamable HTTP MCP server exposing 46 tools for AI agents (Claude, ChatGPT, Perplexity): find_pros, find_pros_by_neighborhood, get_pro, list_taxonomy, get_emergency_contacts, get_cost_estimate, list_cost_guides, list_guides, get_guide, triage_symptom, get_methodology, get_active_storm_events, get_verification_feed, get_county_coverage_stats, find_emergency_pros, get_trade_pricing, get_trade_guide, get_trade_faq, list_emergency_playbooks, get_emergency_playbook, estimate_cost, list_research_articles, get_research_article, verify_contractor, and national state/pro/license matching tools. Use when your agent supports MCP; otherwise prefer the REST endpoints.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(MCP handshake)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/mcp"const res = await fetch("https://profixdirectory.com/api/mcp");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/mcp", timeout=10)
res.raise_for_status()
print(res.json())/api/newsroom.rssNewsroom RSS 2.0 feed
RSS feed combining changelog entries + published research articles. Subscribe in any RSS reader to track ProFix's product + editorial milestones. CC-BY-4.0.
Respuesta de ejemplo
# RSS XML
# Feed en texto plano (RSS / Atom / iCal).Ejemplos de código
curl -sL "https://profixdirectory.com/api/newsroom.rss"const res = await fetch("https://profixdirectory.com/api/newsroom.rss");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/newsroom.rss", timeout=10)
res.raise_for_status()
print(res.json())/api/trade-guide/{trade}.jsonTrade encyclopedia JSON companion
Minimal JSON mirror of /trades/{trade}/guide. Returns the Wave 64 trade encyclopedia entry: troubleshooting, maintenance schedule, cost components, hiring red flags, contract checklist, and warranty norms. CC-BY-4.0. CORS-enabled, 1h cache.
Parámetros
trade(path)requeridotipo:stringCanonical trade slug, for example plumber, hvac, electrician, roofing.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Trade guide JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/trade-guide/plumber.json"const res = await fetch("https://profixdirectory.com/api/trade-guide/plumber.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/trade-guide/plumber.json", timeout=10)
res.raise_for_status()
print(res.json())/api/voice/{q}Voice assistant single-question Q&A
GET endpoint for Alexa skills / Google Actions. Takes a URL-encoded natural-language question as a path segment and returns a 25-40 word voice-friendly answer in both English and Spanish, plus the canonical source URL and source type. Deterministic — no LLM call. Reuses the same search-query-expander + voice-answer collapse pipeline that powers /faq and /api/ask. Strong ETag; Cache-Control public max-age=3600, s-maxage=86400. No auth required.
Parámetros
q(path)requeridotipo:stringURL-encoded natural-language question (e.g. `how%20much%20does%20a%20plumber%20cost`).
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Voice answer JSON.)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/voice/example"const res = await fetch("https://profixdirectory.com/api/voice/example");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/voice/example", timeout=10)
res.raise_for_status()
print(res.json())/llms-full.txtFull LLM content dump
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Plain-text full content map)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/llms-full.txt"const res = await fetch("https://profixdirectory.com/llms-full.txt");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/llms-full.txt", timeout=10)
res.raise_for_status()
print(res.json())/llms.txtLLM content map (llmstxt.org spec)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Plain-text content map)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/llms.txt"const res = await fetch("https://profixdirectory.com/llms.txt");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/llms.txt", timeout=10)
res.raise_for_status()
print(res.json())Feeds de datos
Feeds JSON / CSV por recurso — profesionales, permisos, leads, deltas de verificación, reportes de costos, glosario, búsqueda, autocompletar y el recuperador determinístico /api/answer.
/api/answerDeterministic ProFix answer retrieval
Accepts a homeowner or agent question and returns top grounded matches from ProFix research, buyer guides, glossary, and cost guides. Pure deterministic text retrieval; no LLM call.
Cuerpo de ejemplo
{
"question": "¿Cómo encuentro un plomero licenciado en Toledo con historial reciente de permisos?",
"context": [
"toledo",
"plumbing"
]
}Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Grounded deterministic matches)"
}Ejemplos de código
curl -X POST "https://profixdirectory.com/api/answer" \
-H 'Content-Type: application/json' \
-d '{
"question": "¿Cómo encuentro un plomero licenciado en Toledo con historial reciente de permisos?",
"context": [
"toledo",
"plumbing"
]
}'const res = await fetch("https://profixdirectory.com/api/answer", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"question": "¿Cómo encuentro un plomero licenciado en Toledo con historial reciente de permisos?",
"context": [
"toledo",
"plumbing"
]
}),
});
const data = await res.json();
console.log(data);import requests
payload = {
"question": "¿Cómo encuentro un plomero licenciado en Toledo con historial reciente de permisos?",
"context": [
"toledo",
"plumbing"
]
}
res = requests.post("https://profixdirectory.com/api/answer", json=payload, timeout=10)
res.raise_for_status()
print(res.json())/api/askNatural-language Q&A endpoint
GET version of the answer engine. Accepts a single `q` parameter and returns a structured response with intent detection, a best_answer, related_answers, and related_routes pulled deterministically from FAQs, cost guides, license guides, glossary, buyer guides, and comparison guides. No LLM. Always returns 200 — when no match is found, intent is `unknown` and `match_status` is `no_answer`. Strong ETag; Cache-Control: public, max-age=3600.
Parámetros
q(query)tipo:stringNatural-language question (URL-encoded).
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Structured answer JSON.)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/ask"const res = await fetch("https://profixdirectory.com/api/ask");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/ask", timeout=10)
res.raise_for_status()
print(res.json())/api/autocompleteLightweight typeahead
Typeahead-shaped variant of /api/search — same scoring, smaller payload, strong ETag, designed for header search bars and agent prefix queries.
Parámetros
q(query)requeridotipo:stringlimit(query)tipo:integer
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Autocomplete suggestions JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/autocomplete"const res = await fetch("https://profixdirectory.com/api/autocomplete");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/autocomplete", timeout=10)
res.raise_for_status()
print(res.json())/api/badge/{slug}.svgEmbeddable 'ProFix Verified' trust badge SVG
Per-contractor 240×80 SVG badge displaying current ProFix trust tier (Elite/Solid/Starter/Minimal), 0-100 composite Trust Score, and recent permit count when > 0. Pure inline SVG using system fonts — no external assets. Designed to be embedded with a single `<img>` tag on a contractor's own website, Slack channel, or email signature. CORS-enabled. CC-BY-4.0; keep the wordmark visible. Returns a 404 SVG fallback for unknown slugs. 1h CDN cache.
Parámetros
slug(path)requeridotipo:stringPro slug (see /api/jsonld/local-business-index for the canonical list)
Respuesta de ejemplo
<!-- SVG badge -->
<svg xmlns="http://www.w3.org/2000/svg" ...>...</svg>Ejemplos de código
curl -sL "https://profixdirectory.com/api/badge/miller-plumbing-toledo.svg"const res = await fetch("https://profixdirectory.com/api/badge/miller-plumbing-toledo.svg");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/badge/miller-plumbing-toledo.svg", timeout=10)
res.raise_for_status()
print(res.json())/api/brand-assets.jsonBrand assets feed — logo URLs, color palette, fonts, attribution
Programmatic feed of ProFix Directory brand assets — logo SVG + icon SVG URLs, the brand color palette (primary, accent, background, foreground, neutral), font stack, and short/long/HTML attribution strings. Designed for partner integrations (Slack apps, Discord embeds, Zapier templates, widget hosts) that want a branded card. CC-BY-4.0 for editorial use; brand marks remain ProFix Directory LLC trademarks. 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Brand assets JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/brand-assets.json"const res = await fetch("https://profixdirectory.com/api/brand-assets.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/brand-assets.json", timeout=10)
res.raise_for_status()
print(res.json())/api/buyers-guides.jsonBuyer's guide index
Machine-readable index of every ProFix Directory buyer's guide — slug, title, summary, trade, last-reviewed date, and canonical URL. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Buyer's guides JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/buyers-guides.json"const res = await fetch("https://profixdirectory.com/api/buyers-guides.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/buyers-guides.json", timeout=10)
res.raise_for_status()
print(res.json())/api/changelog.atomNewsroom changelog — Atom 1.0 mirror of /api/newsroom.rss
Atom 1.0 feed of every public ProFix Directory changelog entry. Same data the RSS feed exposes, served in the Atom envelope for readers and AI engines that prefer Atom over RSS. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
# Changelog Atom 1.0
# Feed en texto plano (RSS / Atom / iCal).Ejemplos de código
curl -sL "https://profixdirectory.com/api/changelog.atom"const res = await fetch("https://profixdirectory.com/api/changelog.atom");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/changelog.atom", timeout=10)
res.raise_for_status()
print(res.json())/api/changelog.csvNewsroom changelog — CSV mirror of /api/changelog.json
RFC 4180 CSV mirror of /api/changelog.json. One row per CHANGELOG entry. Columns: `date,type,headline,slug,url`. Use when you want to drop the changelog into Excel/Sheets/pandas. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Changelog CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/changelog.csv"const res = await fetch("https://profixdirectory.com/api/changelog.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/changelog.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/changelog.icsNewsroom changelog — iCal (RFC 5545) calendar feed
iCal subscription of every ProFix Directory changelog milestone as an all-day VEVENT. Subscribe in Apple Calendar, Google Calendar, or Outlook via webcal://profixdirectory.com/api/changelog.ics. Each event carries SUMMARY, DESCRIPTION, URL, CATEGORIES, and a stable UID. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
# iCal calendar
# Feed en texto plano (RSS / Atom / iCal).Ejemplos de código
curl -sL "https://profixdirectory.com/api/changelog.ics"const res = await fetch("https://profixdirectory.com/api/changelog.ics");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/changelog.ics", timeout=10)
res.raise_for_status()
print(res.json())/api/compareSide-by-side contractor comparison
Normalized side-by-side comparison feed for up to three ProFix contractors. Pass `?pros=slug1,slug2,slug3` (comma-separated, ≤3 slugs). Returns each pro's Trust Score + tier, permit count over the last 12 months, license status + license number, rating + review count, insurance-verified flag, tenure, specialties, service area, photo count, featured flag, Spanish-speaking flag, profile URL, evidence-page URL, and last-verified date. Unknown slugs are silently dropped; `requested_slugs` echoes what was asked for. Same JSON shape powers the interactive /compare page. CC-BY-4.0, CORS-enabled, 1h cache.
Parámetros
pros(query)requeridotipo:stringComma-separated pro slugs (e.g. `miller-plumbing-toledo,atlas-butler-heating-cooling-columbus`). At most 3 slugs; returns 400 otherwise.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Comparison JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/compare"const res = await fetch("https://profixdirectory.com/api/compare");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/compare", timeout=10)
res.raise_for_status()
print(res.json())/api/contractors/by-county/{county}.csvBulk contractor feed — CSV mirror of /api/contractors/by-county/{county}.json
RFC 4180 CSV mirror of the per-county contractor JSON feed. Same row set, byte-different envelope for spreadsheet + pandas workflows. CC-BY-4.0.
Parámetros
county(path)requeridotipo:stringOne of the 88 ProFix Ohio county slugs
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Contractor CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/contractors/by-county/lucas.csv"const res = await fetch("https://profixdirectory.com/api/contractors/by-county/lucas.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/contractors/by-county/lucas.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/contractors/by-county/{county}.jsonBulk contractor feed for a single Ohio county
All public ProFix contractors who serve the given county. Pre-rendered for all 88 Ohio county slugs. Each row carries slug, name, trade + trades[], city, county, phone, rating + review_count, trust_score + trust_tier, permit_count_12mo, license_status + license_number, url, and evidence_url. CC-BY-4.0, 1h cache, CORS-enabled.
Parámetros
county(path)requeridotipo:stringOne of the 88 ProFix Ohio county slugs (lucas, cuyahoga, franklin, hamilton, …)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Contractor feed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/contractors/by-county/lucas.json"const res = await fetch("https://profixdirectory.com/api/contractors/by-county/lucas.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/contractors/by-county/lucas.json", timeout=10)
res.raise_for_status()
print(res.json())/api/contractors/by-trade/{trade}.csvBulk contractor feed — CSV mirror of /api/contractors/by-trade/{trade}.json
RFC 4180 CSV mirror of the per-trade contractor JSON feed. Same row set, byte-different envelope for spreadsheet + pandas workflows. CC-BY-4.0.
Parámetros
trade(path)requeridotipo:stringOne of the 37 ProFix trade slugs
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Contractor CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/contractors/by-trade/plumber.csv"const res = await fetch("https://profixdirectory.com/api/contractors/by-trade/plumber.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/contractors/by-trade/plumber.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/contractors/by-trade/{trade}.jsonBulk contractor feed for a single trade (statewide)
All public ProFix contractors whose declared trade list includes the given slug, statewide. Pre-rendered for all 37 ProFix trade slugs. Same row shape as /api/contractors/by-county/{county}.json. CC-BY-4.0, 1h cache, CORS-enabled.
Parámetros
trade(path)requeridotipo:stringOne of the 37 ProFix trade slugs (plumber, hvac, electrician, appliance-repair, gas-tech, concrete, roofing, tree-service, restoration, lead-abatement, fire-protection, water-well, septic-system, tech-repair, pest-control, landscaping, painting, foundation-repair, garage-door, deck-builder, patio-installer, pool-installer, fence-contractor, shed-builder, siding-contractor, window-door-installer, gutter-installer, pressure-washing, lawn-care, sealcoat, outdoor-lighting, solar-installer, ev-charger-installer, heat-pump-installer, insulation-contractor, general-contractor, handyman)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Contractor feed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/contractors/by-trade/plumber.json"const res = await fetch("https://profixdirectory.com/api/contractors/by-trade/plumber.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/contractors/by-trade/plumber.json", timeout=10)
res.raise_for_status()
print(res.json())/api/correctionsSubmit a correction to the editorial team
Public corrections submission endpoint. Accepts JSON or form-encoded payloads with `pro_slug` (optional), `field`, `correction`, and `evidence_url`. Returns 200 with a thank-you acknowledgement. No PII required.
Cuerpo de ejemplo
{
"pro_slug": "miller-plumbing-toledo",
"field": "phone",
"correction": "Teléfono comercial actualizado tras verificación por buzón de voz.",
"evidence_url": "https://example.com/captura-buzon.png",
"contact_email": "informante@example.com"
}Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Acknowledged)"
}Ejemplos de código
curl -X POST "https://profixdirectory.com/api/corrections" \
-H 'Content-Type: application/json' \
-d '{
"pro_slug": "miller-plumbing-toledo",
"field": "phone",
"correction": "Teléfono comercial actualizado tras verificación por buzón de voz.",
"evidence_url": "https://example.com/captura-buzon.png",
"contact_email": "informante@example.com"
}'const res = await fetch("https://profixdirectory.com/api/corrections", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"pro_slug": "miller-plumbing-toledo",
"field": "phone",
"correction": "Teléfono comercial actualizado tras verificación por buzón de voz.",
"evidence_url": "https://example.com/captura-buzon.png",
"contact_email": "informante@example.com"
}),
});
const data = await res.json();
console.log(data);import requests
payload = {
"pro_slug": "miller-plumbing-toledo",
"field": "phone",
"correction": "Teléfono comercial actualizado tras verificación por buzón de voz.",
"evidence_url": "https://example.com/captura-buzon.png",
"contact_email": "informante@example.com"
}
res = requests.post("https://profixdirectory.com/api/corrections", json=payload, timeout=10)
res.raise_for_status()
print(res.json())/api/cost-report.csvCost guide aggregate — CSV companion to /api/cost-report.json
RFC 4180 CSV mirror of the cost report JSON. One row per benchmark. CC-BY-4.0.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Cost report CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/cost-report.csv"const res = await fetch("https://profixdirectory.com/api/cost-report.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/cost-report.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/cost-report.jsonCost guide aggregate (Toledo + Findlay 2026 research)
Aggregate Toledo + Findlay home-services cost benchmarks from the 2026 NW Ohio cost research — 60 cost benchmarks across 8 trades with median + range + Findlay-vs-Toledo variance. CC-BY-4.0. CSV mirror at /api/cost-report.csv.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Cost report JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/cost-report.json"const res = await fetch("https://profixdirectory.com/api/cost-report.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/cost-report.json", timeout=10)
res.raise_for_status()
print(res.json())/api/coverage-stats.csvCoverage snapshot — CSV companion to /api/coverage-stats.json
RFC 4180 CSV with one row per Ohio county (slug, name, region, pro_count). CC-BY-4.0.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Coverage stats CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/coverage-stats.csv"const res = await fetch("https://profixdirectory.com/api/coverage-stats.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/coverage-stats.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/coverage-stats.jsonCoverage snapshot — pro counts by county / region / trade
Static aggregate of verified contractor counts grouped by Ohio county, region (Cleveland/Columbus/Cincinnati/Dayton/Toledo/Findlay/etc.), and trade. Completes the public-data trio (lead-feed + quality-stats + coverage-stats). 1h cache, CC-BY-4.0.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Coverage stats JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/coverage-stats.json"const res = await fetch("https://profixdirectory.com/api/coverage-stats.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/coverage-stats.json", timeout=10)
res.raise_for_status()
print(res.json())/api/data-studies/{slug}.csvData study — CSV download
RFC 4180-style CSV companion for a generated ProFix data-study route at /data-studies/{slug}. Uses rowGroup to distinguish primary and secondary row sets. CC-BY-4.0, CORS-enabled.
Parámetros
slug(path)requeridotipo:stringData-study slug, for example contractor-density-by-state-2026.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Data-study CSV payload
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/data-studies/miller-plumbing-toledo.csv"const res = await fetch("https://profixdirectory.com/api/data-studies/miller-plumbing-toledo.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/data-studies/miller-plumbing-toledo.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/data-studies/{slug}.jsonData study — JSON companion
Machine-readable JSON companion for a generated ProFix data-study route at /data-studies/{slug}. Includes methodology, limitations, source files, primary rows, download URLs, and CC-BY-4.0 attribution.
Parámetros
slug(path)requeridotipo:stringData-study slug, for example contractor-density-by-state-2026.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Data-study JSON payload)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/data-studies/miller-plumbing-toledo.json"const res = await fetch("https://profixdirectory.com/api/data-studies/miller-plumbing-toledo.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/data-studies/miller-plumbing-toledo.json", timeout=10)
res.raise_for_status()
print(res.json())/api/embed/{slug}.jsonPartner embed feed — top 5 pros for a trade × city pair
Returns the top 5 verified pros for a `{trade}-{city}` slug pair (e.g. `plumber-toledo`, `hvac-cleveland`). Designed for one-line third-party embeds — blogs, newsletters, HOA sites. Includes name, phone, rating, verification tier, and permit count. CC-BY-4.0. 1h cache.
Parámetros
slug(path)requeridotipo:stringSlug format `{trade}-{city}` (e.g. plumber-toledo)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Embed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/embed/miller-plumbing-toledo.json"const res = await fetch("https://profixdirectory.com/api/embed/miller-plumbing-toledo.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/embed/miller-plumbing-toledo.json", timeout=10)
res.raise_for_status()
print(res.json())/api/feeds-index.jsonFeeds index — catalog of every JSON/CSV/RSS/iCal feed with metadata
Catalog of every public ProFix Directory feed (JSON, CSV, RSS, iCal). Each entry carries `path`, absolute `url`, `format`, `category`, `description`, `license`, `refresh_cadence` (live / hourly / daily / weekly / monthly / static), `cors`, and an optional `openapi_id` cross-reference. Enumerated from the same `PUBLIC_API_FEED_PATHS` list that powers /sitemap.xml — a single fetch tells an agent every machine-readable surface ProFix exposes. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Feeds index JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/feeds-index.json"const res = await fetch("https://profixdirectory.com/api/feeds-index.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/feeds-index.json", timeout=10)
res.raise_for_status()
print(res.json())/api/glossary.jsonBilingual glossary — EN + ES home-services terminology
Programmatic feed of every glossary term in the ProFix bilingual reference: trade jargon, licensing (OCILB, EPA 608), permits, manufacturer certifications, legal terms, and pricing concepts. Each entry has term, slug, English + Spanish definitions, category, and optional related-term cross-refs. CC-BY-4.0. 1h cache. CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Glossary JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/glossary.json"const res = await fetch("https://profixdirectory.com/api/glossary.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/glossary.json", timeout=10)
res.raise_for_status()
print(res.json())/api/graph/coverage.jsonldOhio coverage Schema.org graph
Connected JSON-LD graph for Ohio, covered metros, counties, cities, ProFix Directory as LocalBusiness, and one Service node per trade. Built for Google Dataset Search and AI knowledge graph ingestion.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Coverage JSON-LD)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/graph/coverage.jsonld"const res = await fetch("https://profixdirectory.com/api/graph/coverage.jsonld");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/graph/coverage.jsonld", timeout=10)
res.raise_for_status()
print(res.json())/api/healthLiveness + dependency probe
Returns directory load status (pro count, county count) plus presence flags for Stripe, Supabase, PostHog, Resend env vars. Public — useful for monitors and partner status pages.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Service healthy)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/health"const res = await fetch("https://profixdirectory.com/api/health");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/health", timeout=10)
res.raise_for_status()
print(res.json())/api/jsonld/datasetDataset JSON-LD — Google Dataset Search registration document
Top-level Schema.org Dataset document describing the 21,898-record ProFix Ohio Home-Services Pros dataset. Names creator + publisher (ProFix Directory / ProFix Directory LLC), declares CC-BY-4.0 license, lists three DataDownload distributions (JSON, CSV, Hugging Face), Ohio spatialCoverage as a GeoShape, 2026/.. temporalCoverage, and five variableMeasured PropertyValue entries (license status, permit count, verification tier, trust score, review aggregate). Designed for Google Dataset Search registration + academic-search tooling that crawl JSON-LD Dataset shapes. Daily revalidate. CORS open.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Dataset JSON-LD)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/jsonld/dataset"const res = await fetch("https://profixdirectory.com/api/jsonld/dataset");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/jsonld/dataset", timeout=10)
res.raise_for_status()
print(res.json())/api/lead-feed.csvLead feed — CSV companion to /api/lead-feed.json
Long-format CSV (window_days, bucket, key, value) for lead aggregate metrics — pivot-friendly. Zero PII. CC-BY-4.0.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Lead feed CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/lead-feed.csv"const res = await fetch("https://profixdirectory.com/api/lead-feed.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/lead-feed.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/lead-feed.jsonLead volume + quality-tier aggregate feed
30-day rolling aggregate of homeowner lead submissions, grouped by trade, quality tier (premium/standard/low/needs_review), urgency, and counties with active demand. Zero PII. Refreshes hourly. Useful for sizing local home-services market or summarizing demand signals.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Lead feed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/lead-feed.json"const res = await fetch("https://profixdirectory.com/api/lead-feed.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/lead-feed.json", timeout=10)
res.raise_for_status()
print(res.json())/api/license-revocations.jsonAnonymized license-status change patterns
Programmatic feed behind /license-watch. Returns anonymized contractor license, registration, and credential status-change patterns across ProFix trades: id, trade, status_change, pattern, reason_category, date_of_change, county, and homeowner_action. No business names, personal names, license numbers, addresses, or docket numbers. CC-BY-4.0 editorial assembly, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(License revocations and suspensions JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/license-revocations.json"const res = await fetch("https://profixdirectory.com/api/license-revocations.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/license-revocations.json", timeout=10)
res.raise_for_status()
print(res.json())/api/match/{trade}/{state}Agent-native ranked pro matching for (trade, state)
Returns up to 50 gold-tier contractors (combined `national_gold` + `regional_gold` — national gold = confidence ≥ 80 with multi-source aggregation; regional gold = single-source + license + phone-state exact match) for a (trade, state) query, sorted by confidence descending. Same per-pro dossier shape as /api/pro/{slug} — no PII beyond what's on the public profile. Validates trade against TRADES and state against SUPPORTED_STATES (case-insensitive). 400 on invalid input. 404 when the state isn't supportedByDirectory OR the (trade, state) pool has fewer than 3 pros. Optional filters: `?limit=` (default 10, max 50), `?city=` (case-insensitive), `?emergency=true` (24/7 pros only). Strong ETag covers the full filter set + a pool snapshot hash so deploys that refresh the seed bust the cache. 1h browser / 24h CDN / 7d SWR. CORS-enabled. CC-BY-4.0.
Parámetros
trade(path)requeridotipo:stringTrade slug (e.g. 'plumber', 'hvac', 'electrician'). See TRADES.state(path)requeridotipo:stringTwo-letter postal code (e.g. 'OH'). Case-insensitive.limit(query)tipo:integerMax number of pros to return (1-50, default 10).city(query)tipo:stringFilter to a single city (case-insensitive).emergency(query)tipo:booleanWhen true, only return pros flagged emergency24h.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Ranked match payload)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/match/plumber/OH"const res = await fetch("https://profixdirectory.com/api/match/plumber/OH");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/match/plumber/OH", timeout=10)
res.raise_for_status()
print(res.json())/api/metrics.jsonDirectory growth metrics — totals, per-trade, per-metro
Machine-readable mirror of /metrics. Build-time aggregate of total contractors, license-linked share, permit pulls in the last 12 months, trades / counties / cities covered, research articles, buyer's guides, glossary terms, public API endpoints, data sources, plus per-trade and per-metro rows. CC-BY-4.0, CORS-enabled, 1h cache.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Metrics JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/metrics.json"const res = await fetch("https://profixdirectory.com/api/metrics.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/metrics.json", timeout=10)
res.raise_for_status()
print(res.json())/api/openapi.yamlOpenAPI 3.1 spec — YAML mirror of /api/openapi.json
YAML serialization of the canonical OpenAPI 3.1 document at /api/openapi.json. Same spec object, byte-different envelope — for partners and AI tooling that prefer YAML over JSON. CC-BY-4.0, 24h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(OpenAPI 3.1 YAML)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/openapi.yaml"const res = await fetch("https://profixdirectory.com/api/openapi.yaml");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/openapi.yaml", timeout=10)
res.raise_for_status()
print(res.json())/api/outage-statusActive utility outage status
Real-time-ish outage status for major Ohio utilities serving NW Ohio.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Outage status JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/outage-status"const res = await fetch("https://profixdirectory.com/api/outage-status");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/outage-status", timeout=10)
res.raise_for_status()
print(res.json())/api/permit-leaderboard.csvPermit-pull leaderboard — CSV companion to /api/permit-leaderboard.json
RFC 4180 CSV mirror of the permit leaderboard JSON feed. Same query-param filtering (`?trade=&county=&window=&top=`). One row per leaderboard entry. CC-BY-4.0.
Parámetros
trade(query)tipo:stringcounty(query)tipo:stringwindow(query)tipo:integertop(query)tipo:integer
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Permit leaderboard CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/permit-leaderboard.csv"const res = await fetch("https://profixdirectory.com/api/permit-leaderboard.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/permit-leaderboard.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/permit-leaderboard.jsonPermit-pull leaderboard — pro rankings by verified building permits
Ranks Ohio contractors by VERIFIED public building permits pulled in the last 365 days (proof of work, not stars). Per-trade, per-county leaderboards across Lucas / Cuyahoga / Franklin / Hamilton counties. Filter via query params: `?trade=<slug>&county=<slug>|ohio&window=<days>&top=<n>`. Use `county=ohio` for statewide aggregates. CC-BY-4.0. 1h cache.
Parámetros
trade(query)tipo:stringFilter to a single trade slug (plumber, hvac, etc.)county(query)tipo:stringFilter to a single county slug, or `ohio` for statewide aggregateswindow(query)tipo:integerDays back to count permits (max 1095)top(query)tipo:integerTop N entries per leaderboard (max 100)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Permit leaderboard JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/permit-leaderboard.json"const res = await fetch("https://profixdirectory.com/api/permit-leaderboard.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/permit-leaderboard.json", timeout=10)
res.raise_for_status()
print(res.json())/api/permits.jsonPermit office directory (Toledo + Findlay metros)
Permit-issuing offices with phone, hours, and per-trade guidance. Currently scoped to Toledo + Findlay metros (other Ohio metros forthcoming).
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Permits JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/permits.json"const res = await fetch("https://profixdirectory.com/api/permits.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/permits.json", timeout=10)
res.raise_for_status()
print(res.json())/api/permits/by-county/{county}.jsonRolling 365-day permit feed for a single Ohio county
Public building permits over the last 365 days attributed to contractors who serve the given Ohio county. Pre-rendered for all 88 county slugs. Each row carries permit_id, issued_date, contractor_slug, address, trade, value_usd, url. CC-BY-4.0, 1h cache, CORS-enabled.
Parámetros
county(path)requeridotipo:stringOne of the 88 ProFix Ohio county slugs
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Permit feed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/permits/by-county/lucas.json"const res = await fetch("https://profixdirectory.com/api/permits/by-county/lucas.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/permits/by-county/lucas.json", timeout=10)
res.raise_for_status()
print(res.json())/api/permits/by-trade/{trade}.jsonRolling 365-day permit feed for a single trade (statewide)
Public building permits over the last 365 days attributed to contractors whose declared trade list includes the given slug, statewide. Pre-rendered for all 37 trade slugs. Same row shape as /api/permits/by-county/{county}.json. CC-BY-4.0, 1h cache, CORS-enabled.
Parámetros
trade(path)requeridotipo:stringOne of the 37 ProFix trade slugs
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Permit feed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/permits/by-trade/plumber.json"const res = await fetch("https://profixdirectory.com/api/permits/by-trade/plumber.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/permits/by-trade/plumber.json", timeout=10)
res.raise_for_status()
print(res.json())/api/pro/{slug}Structured per-pro dossier (gold-tier, national)
Structured JSON mirror of /state/{state}/pro/{slug} for every gold-tier contractor in the ProFix Directory. Gold-tier is the combined `national_gold` + `regional_gold` set: national gold is confidence >= 80 with multi-source aggregation; regional gold is single-source + license + phone-state exact match (single-source `verified` listings are not exposed here). Returns identity, trades, verification tier, license evidence + verify URL, evidence (confidence score + corroborating source count + program badges), photo manifest entry, permit footprint, and outbound source URLs. Phone is included and tagged as `phone_verification: "directory-verified" | "self-attested"`. No PII beyond what's on the public profile. Strong ETag + 1h browser / 24h CDN / 7d SWR cache. CORS-enabled. CC-BY-4.0.
Parámetros
slug(path)requeridotipo:stringGold-tier pro slug
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Pro JSON dossier)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/pro/miller-plumbing-toledo"const res = await fetch("https://profixdirectory.com/api/pro/miller-plumbing-toledo");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pro/miller-plumbing-toledo", timeout=10)
res.raise_for_status()
print(res.json())/api/pro/{slug}.jsonPer-pro JSON dossier
Canonical per-contractor dossier as JSON. Returns name, location, license + verification details, source URLs, permit count + verified status, the read-only Google Places rating (source: google_places), and a first-party `reviews` block — count, mean, star histogram, and up to 5 recent snippets from APPROVED ProFix-moderated homeowner reviews (source: first_party_moderated). Zero PII beyond what /pro/{slug} already shows publicly. CC-BY-4.0. 1h cache.
Parámetros
slug(path)requeridotipo:stringPro slug (see /api/jsonld/local-business-index for the canonical list)
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Pro JSON dossier)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/pro/miller-plumbing-toledo.json"const res = await fetch("https://profixdirectory.com/api/pro/miller-plumbing-toledo.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pro/miller-plumbing-toledo.json", timeout=10)
res.raise_for_status()
print(res.json())/api/pro/{slug}/permitsPer-pro permit-pull history (rolling 365d)
Targeted child endpoint of /api/pro/{slug}: returns the permit-pull history for the given gold-tier pro. Each row carries issued_date, permit_type, jurisdiction, address, job_value_usd, source_url, and synthetic flag. Includes a summary block with `count_total`, `count_12mo`, and `permit_verified`. Strong ETag + 1h/24h/7d cache. CORS-enabled. CC-BY-4.0.
Parámetros
slug(path)requeridotipo:stringGold-tier pro slug
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Permit feed)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/pro/miller-plumbing-toledo/permits"const res = await fetch("https://profixdirectory.com/api/pro/miller-plumbing-toledo/permits");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pro/miller-plumbing-toledo/permits", timeout=10)
res.raise_for_status()
print(res.json())/api/pro/{slug}/photosPer-pro photo manifest entry
Targeted child endpoint of /api/pro/{slug}: returns just the photo manifest entry for the given gold-tier pro (`photo_url`, `thumb_url`, `alt`, `source_type`, `trusted`). Returns `photo: null` (200) when the manifest has no entry. Strong ETag + 1h/24h/7d cache. CORS-enabled. CC-BY-4.0.
Parámetros
slug(path)requeridotipo:stringGold-tier pro slug
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Photo manifest entry)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/pro/miller-plumbing-toledo/photos"const res = await fetch("https://profixdirectory.com/api/pro/miller-plumbing-toledo/photos");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pro/miller-plumbing-toledo/photos", timeout=10)
res.raise_for_status()
print(res.json())/api/prompts.jsonProFix Prompt Library — copy-paste prompts for AI engines
Machine-readable mirror of the /prompts library. Returns 23 ready-to-ship prompts for ChatGPT, Claude, Perplexity, and Gemini that ground their answers in public ProFix endpoints. Each entry includes id, category (homeowner / developer / press), title, description, the literal prompt text, referenced endpoints, tags, and an anchor URL into /prompts. CC-BY-4.0. 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Prompt library JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/prompts.json"const res = await fetch("https://profixdirectory.com/api/prompts.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/prompts.json", timeout=10)
res.raise_for_status()
print(res.json())/api/pros.csvBulk dataset — every public pro as CSV
RFC 4180 CSV mirror of /api/pros.json. One row per published contractor. Use when you want to drop the dataset into Excel, Sheets, or pandas. CC-BY-4.0.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Pros dataset CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/pros.csv"const res = await fetch("https://profixdirectory.com/api/pros.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pros.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/pros.jsonBulk dataset — every public pro as JSON
Full ProFix Directory pro dataset as one JSON document. One entry per published contractor with the public-surface columns (slug, name, address, phone, trades, license, rating, verification, trust). Mirror of the Hugging Face dataset `Pisces89/ohio-home-services-pros`. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Pros dataset JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/pros.json"const res = await fetch("https://profixdirectory.com/api/pros.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pros.json", timeout=10)
res.raise_for_status()
print(res.json())/api/quality-stats.jsonLead-quality score histogram + median per trade
90-day rolling aggregate of lead-quality scores — histogram by 20-point buckets, tier breakdown, overall median, and median per trade (requires ≥3 scored leads per trade to avoid noise). Zero PII. Refreshes hourly. Companion to /api/lead-feed.json.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Quality stats JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/quality-stats.json"const res = await fetch("https://profixdirectory.com/api/quality-stats.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/quality-stats.json", timeout=10)
res.raise_for_status()
print(res.json())/api/recently-verified.jsonRecently-verified pros — rolling 30-day feed
Feed of pros whose verifiedAt timestamp falls within the last 30 days. Includes verification tier, permit-verified flag, and trust score. Useful for 'what's new' surfaces + partner freshness checks. CC-BY-4.0. 1h cache.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Recently-verified pros JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/recently-verified.json"const res = await fetch("https://profixdirectory.com/api/recently-verified.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/recently-verified.json", timeout=10)
res.raise_for_status()
print(res.json())/api/reports/permits-this-month.jsonMonthly recap — last 30 days of Ohio contractor permit activity
Machine-readable mirror of /reports/permits-this-month. Rolling 30-day window over the real matched permit-by-pro dataset (5,004 public permits joined to 554 contractors across 22 county jurisdictions; in Ohio: Cuyahoga, Franklin, Hamilton). Returns generated_at, license, window (start/end/days), top_pros (top 25 by permit count), by_trade (top 3 per trade), by_county (top 3 per county). Real public-record permits only. CC-BY-4.0. Daily refresh.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Permits-this-month recap JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/reports/permits-this-month.json"const res = await fetch("https://profixdirectory.com/api/reports/permits-this-month.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/reports/permits-this-month.json", timeout=10)
res.raise_for_status()
print(res.json())/api/reports/this-week.jsonWeekly recap — last 7 days of newsroom changelog + research publications
Machine-readable mirror of /reports/this-week. Rolling 7-day window over the public CHANGELOG and RESEARCH_ARTICLES datasets. Returns generated_at, license, window (start/end/days), changelog_entries (date/type/headline/url), research_published (slug/title/url/publishedAt), and counts. Honest about empty windows. CC-BY-4.0. Daily refresh.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(This-week recap JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/reports/this-week.json"const res = await fetch("https://profixdirectory.com/api/reports/this-week.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/reports/this-week.json", timeout=10)
res.raise_for_status()
print(res.json())/api/research-publications.icsResearch publications — iCal (RFC 5545) calendar feed
iCal subscription of every ProFix Directory research-article publication date as an all-day VEVENT. Subscribe in Apple Calendar, Google Calendar, or Outlook via webcal://profixdirectory.com/api/research-publications.ics. Each event links to the canonical /research/<slug> URL. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
# iCal calendar
# Feed en texto plano (RSS / Atom / iCal).Ejemplos de código
curl -sL "https://profixdirectory.com/api/research-publications.ics"const res = await fetch("https://profixdirectory.com/api/research-publications.ics");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/research-publications.ics", timeout=10)
res.raise_for_status()
print(res.json())/api/research.csvResearch articles — CSV mirror of /api/research.json
RFC 4180 CSV mirror of /api/research.json. One row per published research article. Columns: `slug,publishedAt,wordCount,title,summary,keywords,url` where `keywords` is `;`-joined since CSV cannot nest arrays. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
# Respuesta CSV — RFC 4180. La primera fila es el encabezado.
# Research CSV
slug,name,city,county,state,phone,verification_tier
miller-plumbing-toledo,Miller Plumbing,Toledo,Lucas,OH,419-555-0144,license-linkedEjemplos de código
curl -sL "https://profixdirectory.com/api/research.csv"const res = await fetch("https://profixdirectory.com/api/research.csv");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/research.csv", timeout=10)
res.raise_for_status()
print(res.json())/api/research.jsonResearch articles — JSON index
Machine-readable index of authored ProFix Directory research articles. Returns slug, title, publishedAt, wordCount, summary, keywords, and canonical URL for each /research/{slug} article. Generated data-study Markdown entries are exposed through /api/markdown-corpus?type=research when the data-studies seed exists. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Research article JSON index)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/research.json"const res = await fetch("https://profixdirectory.com/api/research.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/research.json", timeout=10)
res.raise_for_status()
print(res.json())/api/reviews/aggregates.jsonFirst-party review aggregates — every reviewed pro
Corpus-wide aggregates of APPROVED, ProFix-moderated homeowner reviews: one row per pro with count, mean rating, star histogram, and newest-review timestamp, plus a corpus summary (rated_pros, total_reviews, volume-weighted corpus_average). Aggregate-only, zero PII. DISTINCT from the read-only Google Places rating the directory surfaces — those are never re-emitted as ProFix aggregates. Per-pro recent review snippets live on /api/pro/{slug}.json. 1h cache, CORS-open, CC-BY-4.0.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(First-party review aggregates JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/reviews/aggregates.json"const res = await fetch("https://profixdirectory.com/api/reviews/aggregates.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/reviews/aggregates.json", timeout=10)
res.raise_for_status()
print(res.json())/api/searchSite-wide deterministic search
Deterministic full-text search across states, cities, costs, license guides, pros, best-of pages, and trades. Same scoring as /api/autocomplete with a richer response body. Strong ETag cache; 5-minute browser, 1h CDN, day-long SWR.
Parámetros
q(query)requeridotipo:stringQuery stringlimit(query)tipo:integerMaximum results to return (cap 200)type(query)tipo:stringFilter results to a single entry typestate(query)tipo:stringFilter results to a state postal codetrade(query)tipo:stringFilter results to a trade slug
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Search results JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/search"const res = await fetch("https://profixdirectory.com/api/search");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/search", timeout=10)
res.raise_for_status()
print(res.json())/api/site-graph.jsonSite graph — major sections with their pages + data endpoints
High-level link graph of ProFix Directory grouped into 10 sections (trust, permits, research, buyer's guides, trades, metros, agent-native, transparency, Spanish, tools). Each section bundles canonical HTML hub URLs with their machine-readable data endpoints, plus a top-level `agent_discovery` block pointing at llms.txt, llms-full.txt, OpenAPI, MCP, and the sitemap index. Designed for AI engines and partners that want to understand the site structure without crawling 20K+ pages. CC-BY-4.0, 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Site graph JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/site-graph.json"const res = await fetch("https://profixdirectory.com/api/site-graph.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/site-graph.json", timeout=10)
res.raise_for_status()
print(res.json())/api/sources.jsonData source registry — provenance index for every external source ProFix uses
Programmatic mirror of /sources. Returns the canonical registry of every external data source ProFix Directory uses to assemble its Ohio home-services contractor directory — licensing (Ohio eLicense, OCILB, ODH, SFM), permits (Lucas, Cuyahoga, Franklin, Hamilton county portals), reviews (Google Business Profiles, BBB), profiles (Google Places API), cost guides (primary research, U.S. BLS), local content (NOAA storm events, county building departments, ARPA lead-line programs), and open data (U.S. Census Geocoder, ACS). Each entry includes id, category, URL, license, optional license URL, refresh cadence, fields used, an explicit 'what we don't pull' list, and a stable /sources anchor. CC-BY-4.0 editorial assembly; underlying sources retain their own licenses. 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Sources registry JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/sources.json"const res = await fetch("https://profixdirectory.com/api/sources.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/sources.json", timeout=10)
res.raise_for_status()
print(res.json())/api/storm-events.jsonOhio storm events historical feed
Programmatic feed of ProFix's illustrative Ohio storm-event registry for 2020-2026. Returns date, type, severity, affected metros/counties, description, NOAA/NWS source URL, and canonical /storm-history/{slug} URL for each event. Editorial assembly is CC-BY-4.0; NOAA/NWS records retain public-domain source status. 1h cache, CORS-enabled.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Storm events JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/storm-events.json"const res = await fetch("https://profixdirectory.com/api/storm-events.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/storm-events.json", timeout=10)
res.raise_for_status()
print(res.json())/api/trades.jsonTrade taxonomy — 37 canonical home-services trades
Public registry of the 37 canonical trades ProFix Directory tracks. Per trade: slug, English + Spanish label, federal NAICS codes that crosswalk to it, CSLB classes (California), the 2-letter state codes where at least one gold-tier pro offers the trade, and the national pro count. Strong ETag. CC-BY-4.0. 1h browser / 24h CDN / 7d SWR.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Trades registry JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/trades.json"const res = await fetch("https://profixdirectory.com/api/trades.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/trades.json", timeout=10)
res.raise_for_status()
print(res.json())/api/trust-scores.jsonProFix Trust Score aggregate — every pro's composite 0-100 score + tier
Bulk feed of every pro's ProFix Trust Score (0-100) and tier (elite/solid/starter/minimal). Composite of verification tier, license status, rating × review count, photos/hours/specialties/tenure, permit-verified flag. Methodology at /methodology. Zero PII. CC-BY-4.0. 1h cache.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Trust scores JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/trust-scores.json"const res = await fetch("https://profixdirectory.com/api/trust-scores.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/trust-scores.json", timeout=10)
res.raise_for_status()
print(res.json())/api/verification-feed.jsonVerification deltas feed
Live JSON feed of license-status changes, new permits, and audit deltas. Refreshed hourly.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Verification feed JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/verification-feed.json"const res = await fetch("https://profixdirectory.com/api/verification-feed.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/verification-feed.json", timeout=10)
res.raise_for_status()
print(res.json())/api/voice-answers.jsonVoice assistant Q&A answers
Short spoken contractor answers for Alexa, Google Assistant, Siri, and other voice systems. Each answer is capped for spoken delivery and includes speakable JSON-LD.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Voice answer feed)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/voice-answers.json"const res = await fetch("https://profixdirectory.com/api/voice-answers.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/voice-answers.json", timeout=10)
res.raise_for_status()
print(res.json())/api/widgets.jsonWidget catalog — every embeddable trade × city slug
Programmatic catalog of every ProFix partner widget slug. Returns `TRADES × ALL_CITIES` entries with `{trade}-{city}` slug, JavaScript embed URL, and matching `/api/embed/{slug}.json` data URL. CC-BY-4.0. 1h cache. CORS-enabled for partner discovery.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Widget catalog JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/widgets.json"const res = await fetch("https://profixdirectory.com/api/widgets.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/widgets.json", timeout=10)
res.raise_for_status()
print(res.json())/api/zip/{zipcode}.jsonZIP-level Ohio coverage lookup
Returns city, county, nearest metro, utility contacts, permit office, and top five pros by trade for a covered Ohio ZIP code. Designed for AI agents that start from a homeowner ZIP.
Parámetros
zipcode(path)requeridotipo:stringFive-digit Ohio ZIP code, for example 43615.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(ZIP coverage match)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/zip/43615.json"const res = await fetch("https://profixdirectory.com/api/zip/43615.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/zip/43615.json", timeout=10)
res.raise_for_status()
print(res.json())Taxonomía geográfica
Estados, ciudades, cobertura por código postal y registro de taxonomía urbana.
/api/cities.jsonCity registry — every incorporated place + CDP nationally
Paginated public registry of every U.S. city ProFix Directory has loaded into its national taxonomy (15,614 records sourced from Census ACS Places). Use `?cursor=<slug>&limit=<n>` to walk large pulls (default limit 500, max 5000). Returns next_cursor null when exhausted. Each city carries: state, English + (optional) Spanish name, slug, 7-digit FIPS code, population, primary county, and the gold-tier pro count for the city. Strong ETag. CC-BY-4.0. 1h browser / 24h CDN / 7d SWR.
Parámetros
cursor(query)tipo:stringOpaque cursor (slug of the last city emitted on the previous page).limit(query)tipo:integerPage size — defaults to 500, capped at 5000.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(Cities registry JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/cities.json"const res = await fetch("https://profixdirectory.com/api/cities.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/cities.json", timeout=10)
res.raise_for_status()
print(res.json())/api/city-taxonomy.jsonCity taxonomy
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(City taxonomy JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/city-taxonomy.json"const res = await fetch("https://profixdirectory.com/api/city-taxonomy.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/city-taxonomy.json", timeout=10)
res.raise_for_status()
print(res.json())/api/states.jsonState registry — 50 states + DC + 5 territories
Public registry of every U.S. state ProFix Directory tracks. Per entry: 2-letter code, English + Spanish name, launched flag, gold-tier pro count, total pro count, distinct cities covered, top 5 metros (by population), and the primary licensing-board name + URL. Strong ETag (`W/"states-…"`) supports If-None-Match short-circuiting. CC-BY-4.0. 1h browser / 24h CDN / 7d SWR.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(States registry JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/states.json"const res = await fetch("https://profixdirectory.com/api/states.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/states.json", timeout=10)
res.raise_for_status()
print(res.json())Verificación
Comprobaciones cruzadas contra fuentes oficiales e índices de evidencia.
/api/license-evidence.jsonLicense evidence index
Per-pro license evidence: license number, source URL, last verified.
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(License evidence JSON)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/license-evidence.json"const res = await fetch("https://profixdirectory.com/api/license-evidence.json");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/license-evidence.json", timeout=10)
res.raise_for_status()
print(res.json())Activos generados
Insignias SVG por profesional e imágenes de tarjeta compartibles.
/api/pro-card/{slug}Generated pro card SVG
Parámetros
slug(path)requeridotipo:string
Respuesta de ejemplo
{
"ok": true,
"license": "CC-BY-4.0",
"generated_at": "2026-06-08T00:00:00Z",
"example": "(SVG image)"
}Ejemplos de código
curl -sL "https://profixdirectory.com/api/pro-card/miller-plumbing-toledo"const res = await fetch("https://profixdirectory.com/api/pro-card/miller-plumbing-toledo");
if (!res.ok) throw new Error(`ProFix ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://profixdirectory.com/api/pro-card/miller-plumbing-toledo", timeout=10)
res.raise_for_status()
print(res.json())Esquemas de componentes
18 esquemas reutilizables definidos en components.schemas. Inspecciona cualquiera en JSON crudo en /api/openapi.json.
- Pro
- ProList
- City
- State
- CostGuide
- LicenseGuide
- BuyerGuide
- FAQ
- ResearchArticle
- TradeGuide
- EmergencyPlaybook
- SearchResponse
- CorrectionSubmission
- ErrorResponse
- ProDossier
- ProPhotos
- MatchResponse
- ProPermits