Menu

Recipes

Copy, set LIFEBUTLER_KEY and the workspace ID, run.

Shopping list from Home Assistant#

configuration.yaml:

YAML
rest_command:
  lifebutler_add_item:
    url: "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/lists/L1st1d/items"
    method: POST
    headers:
      Authorization: !secret lifebutler_auth   # "Bearer lb_live_…"
      Content-Type: application/json
    payload: '{"items": ["{{ item }}"]}'

Then call rest_command.lifebutler_add_item with item: Milch from any automation – a fridge sensor, a button, a voice command. Find the list ID with GET /workspaces/{id}/lists. Key scope: lists:write.

Import appointments (Python)#

Python
import os, requests

API = "https://api.lifebutler.io/v1"
WS = "f8Hn3wQz0a"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['LIFEBUTLER_KEY']}"

def add(title, start, end, location=""):
    r = s.post(f"{API}/workspaces/{WS}/events",
               json={"title": title, "start": start, "end": end, "location": location})
    r.raise_for_status()
    return r.json()["id"]

add("Elternabend 3b", "2026-11-24T19:30", "2026-11-24T21:00", "Grundschule Am Park")

# All-day, several days: dates, end inclusive
s.post(f"{API}/workspaces/{WS}/events",
       json={"title": "Herbstferien", "allDay": True, "start": "2026-10-26", "end": "2026-10-30"}).raise_for_status()

Times without an offset are Berlin time. Key scope: calendar:write.

Scanning folder (Node.js)#

Uploads every new PDF from a folder; LifeButler names and analyses it if AI is on.

JavaScript
import { readdir, readFile, rename } from "node:fs/promises";

const API = "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents";
const headers = { Authorization: `Bearer ${process.env.LIFEBUTLER_KEY}`, "Content-Type": "application/pdf" };

for (const name of await readdir("scans")) {
  if (!name.endsWith(".pdf")) continue;
  const res = await fetch(`${API}?fileName=${encodeURIComponent(name)}`, {
    method: "POST", headers, body: await readFile(`scans/${name}`),
  });
  if (res.ok || res.status === 409) await rename(`scans/${name}`, `scans/done/${name}`); // 409 = already stored
  else console.error(name, res.status, await res.json());
}

Key scope: documents:write.

Weekly digest (n8n, Make, cron)#

  1. GET /workspaces/{id}/events?from=<monday>&to=<sunday> – the week's appointments, series expanded.
  2. GET /workspaces/{id}/tasks?status=open – open tasks, by due date.
  3. Format and send it by e-mail or chat.

Key scopes: calendar:read, tasks:read.

Ask the butler and let it act#

Shell
curl -X POST https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/butler \
  -H "Authorization: Bearer $LIFEBUTLER_KEY" -H "Content-Type: application/json" \
  -d '{"question": "Wir grillen Samstag mit 8 Leuten. Setz alles auf die Einkaufsliste und erinnere mich Freitag ans Fleisch.", "apply": true}'
JSON
{
  "answer": "Ich habe 9 Dinge auf die Einkaufsliste gesetzt und dich für Freitag ans Fleisch erinnert.",
  "actions": [ { "type": "addListItems", "listName": "Einkauf", "items": [ … ] }, { "type": "createTask", "title": "Fleisch beim Metzger abholen", "date": "2026-11-20", … } ],
  "applied": 2,
  "credits": 2
}

Without apply, the actions are only proposals you can show or create yourself. Key scope: butler.