Foyer API · Recipe
Search everything a caller said
Find the call where someone mentioned "the roof", a policy number, or a name, across everything callers said to Foyer and to you.
You need: a key with calls:read and transcripts:read (any plan). With calls:read alone, search covers names, numbers and summaries only.
Search for words
GET /v1/search?q=… matches the whole phrase, ignoring case, in the caller's name, caller ID name, company, number and Foyer's summary. With transcripts:read it also looks in voicemail text, the screening conversation and the recorded call's transcript, and each hit has a short excerpt around the match and matched_in, the places it matched.
curl "https://api.hifoyer.com/v1/search?q=roof" \
-H "Authorization: Bearer $FOYER_API_KEY"Calls are stored encrypted, so one search request examines up to 400 calls, newest first. If next_cursor is not null, there is older history: pass it back as cursor to keep going. search.reached_oldest_call is true when nothing older is left.
import os
import time
import requests
API = "https://api.hifoyer.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['FOYER_API_KEY']}"}
def search(q, **filters):
cursor = None
while True:
params = {"q": q, "limit": 50, **filters, **({"cursor": cursor} if cursor else {})}
resp = requests.get(f"{API}/search", headers=HEADERS, params=params, timeout=30)
if resp.status_code == 429:
time.sleep(int(resp.headers.get("Retry-After", "5")))
continue
resp.raise_for_status()
page = resp.json()
yield from page["data"]
cursor = page["next_cursor"]
if not cursor:
return
for hit in search("roof"):
call = hit["call"]
who = call["caller"]["name"] or call["caller"]["number"] or "Unknown caller"
print(call["started_at"][:10], who, "|", ", ".join(hit["matched_in"]), "|", hit["excerpt"] or call["summary"])Search counts against its own limit of 20 a minute. Narrow a long search with since, until or outcome.
Everything one caller said
List one caller's calls with GET /v1/calls?caller=… (the full number), then read each in full:
number = "+16175550142"
calls = requests.get(f"{API}/calls", headers=HEADERS, params={"caller": number, "limit": 100}, timeout=30)
calls.raise_for_status()
for item in reversed(calls.json()["data"]):
detail = requests.get(f"{API}/calls/{item['id']}", headers=HEADERS, timeout=30)
detail.raise_for_status()
call = detail.json()["data"]
print(f"\n{call['started_at']}: {call['outcome_label']}")
for turn in call.get("screening_conversation", []):
print(f" {turn['speaker']}: {turn['text']}")
if call["voicemail"].get("transcript"):
print(f" voicemail: {call['voicemail']['transcript']}")
for turn in (call.get("connected_call") or {}).get("transcript", []):
print(f" {turn['speaker']}: {turn['text']}")In the screening conversation, speaker is caller or foyer. In a recorded call it is caller or you.
Ask an assistant instead
With Foyer connected to Claude or ChatGPT, ask: "Find the call where someone talked about the roof, and tell me what they said." See Connect Claude or ChatGPT.