Smithable websitedocsGitHub
Menu

Tell people and other systems

When something happens in an app, it can say so: a mail to a person, or a call to another system. You write what should happen in smithable.yml. The app keeps each message in an outbox, sends it after the change is saved, and tries again when it can't get through.

1. Mail a person

outgoing:
  bookingMade:
    when: Booking created            # created | changed | deleted, or an action's name
    to: mail
    recipient: owner                 # the record's owner, a role (admin), or an email field

From the command line: smithable op addOutgoing bookingMade "Booking created" --to mail --recipient owner.

2. Call another system

outgoing:
  incidentResolved:
    when: Incident changed
    where: { status: resolved }
    to: statusFeed                   # a name; its address and secret are settings

The app posts JSON to the address set for statusFeed:

{ "event": "incidentResolved", "model": "Incident", "happened": "changed",
  "at": "2026-10-13T08:00:00.000Z", "record": { "id": 12, "title": "…", "status": "resolved" } }

The record is as the API shows it. Each call carries three headers:

A receiver checks the signature like this:

import { createHmac, timingSafeEqual } from "node:crypto";
const expected = `sha256=${createHmac("sha256", secret).update(rawBody).digest("hex")}`;
const ok = expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));

Settings. A target's address and secret are two settings named after it: OUTGOING_STATUSFEED_URL and OUTGOING_STATUSFEED_SECRET.

Which addresses the app will call. Only http or https. Never the app itself, and in a published app never a private or local network. The address checked is the one connected to. On smithable.ai, the app reaches the internet only through the service's egress proxy, and only for the Connections you added.

3. Delivery and its history

4. In the preview

The preview sends no mail and makes no calls. Mails stay in its outbox, and calls to a target are skipped. Activity shows both as what a published app would do.