Foyer API · Recipe
Send my voicemails to Slack or Notion
Post each new voicemail to a Slack channel, or add it to a Notion database, with who called, Foyer's summary and the message text.
You need: a Foyer key with calls:read and transcripts:read (any plan), and a Slack incoming webhook URL or a Notion integration token and database.
How it works
- Every few minutes, ask Foyer for voicemails from the last day:
GET /v1/voicemails?since=…. - Skip any you have already posted, and any whose text is not ready yet. A voicemail's
voicemail.statebecomestranscribedwhen its text is ready. - Read the message text from
GET /v1/calls/{id}(voicemail.transcript). - Post it, then remember the call's
id.
The script (Slack)
import json
import os
import pathlib
from datetime import datetime, timedelta, timezone
import requests
API = "https://api.hifoyer.com/v1"
FOYER = {"Authorization": f"Bearer {os.environ['FOYER_API_KEY']}"}
SLACK_WEBHOOK_URL = os.environ["SLACK_WEBHOOK_URL"]
STATE = pathlib.Path("foyer-voicemails-posted.json")
posted = set(json.loads(STATE.read_text())) if STATE.exists() else set()
since = (datetime.now(timezone.utc) - timedelta(days=1)).isoformat()
resp = requests.get(f"{API}/voicemails", headers=FOYER, params={"since": since, "limit": 100}, timeout=30)
resp.raise_for_status()
for call in reversed(resp.json()["data"]): # oldest first
if call["id"] in posted or call["voicemail"]["state"] != "transcribed":
continue
detail = requests.get(f"{API}/calls/{call['id']}", headers=FOYER, timeout=30)
detail.raise_for_status()
transcript = detail.json()["data"]["voicemail"].get("transcript", "")
who = call["caller"]["name"] or call["caller"]["number"] or "Unknown caller"
quoted = "\n".join(f"> {line}" for line in transcript.splitlines())
message = f"*Voicemail from {who}*\n{call['summary']}\n{quoted}"
requests.post(SLACK_WEBHOOK_URL, json={"text": message}, timeout=30).raise_for_status()
posted.add(call["id"])
STATE.write_text(json.dumps(sorted(posted)))Run it every five minutes, for example with cron:
*/5 * * * * cd /path/to/script && FOYER_API_KEY=fyr_… SLACK_WEBHOOK_URL=https://hooks.slack.com/… python3 foyer_voicemails_to_slack.pyThat is about 300 requests a day, plus one per voicemail: well within the limits.
Notion instead
Replace the Slack post with a new page in a Notion database that has a Name title and a Called date property. Share the database with your Notion integration first.
def post_to_notion(call, who, transcript):
requests.post(
"https://api.notion.com/v1/pages",
headers={
"Authorization": f"Bearer {os.environ['NOTION_TOKEN']}",
"Notion-Version": "2022-06-28",
},
json={
"parent": {"database_id": os.environ["NOTION_DATABASE_ID"]},
"properties": {
"Name": {"title": [{"text": {"content": f"Voicemail from {who}"}}]},
"Called": {"date": {"start": call["started_at"]}},
},
"children": [
{"object": "block", "type": "paragraph",
"paragraph": {"rich_text": [{"text": {"content": call["summary"]}}]}},
{"object": "block", "type": "quote",
"quote": {"rich_text": [{"text": {"content": transcript[:2000]}}]}},
],
},
timeout=30,
).raise_for_status()Check Notion's API documentation for the current Notion-Version.
Variations
- No code: any automation tool that can make an HTTPS request on a schedule, with a header, can do the same steps.
- Mark it heard: add
calls:write(Concierge or Chief of Staff) and callPOST /v1/calls/{id}/voicemail/mark-reviewedafter posting, if the channel is where you listen now. - Messages without text: a voicemail whose
statestaysaudio_onlyhas no text. Post its summary, or a five-minute recording link fromGET /v1/calls/{id}/audio?part=voicemail(needsaudio:read). Anyone in the channel could play that link until it expires.
Before you turn it on
Everyone who can read the Slack channel or Notion database will read what your callers said. Choose a private channel. See Privacy.