Foyer API pages

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

  1. Every few minutes, ask Foyer for voicemails from the last day: GET /v1/voicemails?since=….
  2. Skip any you have already posted, and any whose text is not ready yet. A voicemail's voicemail.state becomes transcribed when its text is ready.
  3. Read the message text from GET /v1/calls/{id} (voicemail.transcript).
  4. Post it, then remember the call's id.

The script (Slack)

foyer_voicemails_to_slack.py
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:

crontab -e
*/5 * * * * cd /path/to/script && FOYER_API_KEY=fyr_… SLACK_WEBHOOK_URL=https://hooks.slack.com/… python3 foyer_voicemails_to_slack.py

That 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.

Post to Notion
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

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.