RelayAPI
GuidesAutomations

Templates

Eight validated starter graphs, including four channel-specific quick automations.

How templates work

Pass template to POST /v1/automations. RelayAPI validates the template's exact config shape, builds a canonical graph, creates any generated entrypoints, and stores the original wizard input in template_config for reference. The resulting automation starts as draft; activate it explicitly after reviewing the graph.

Template output is ordinary automation data. After creation, edit the graph and entrypoints directly—there is no separate template runtime or “regenerate” operation.

{
  "name": "Pizza promo",
  "channel": "instagram",
  "template": {
    "kind": "comment_to_dm",
    "config": {
      "social_account_id": "acc_...",
      "post_ids": ["17895..."],
      "keyword_filter": ["link", "menu"],
      "public_reply": "Sent—check your DMs!",
      "dm_message": {
        "blocks": [
          { "id": "b1", "type": "text", "text": "Here is the link, {{contact.name}}!" }
        ]
      },
      "once_per_user": true,
      "daily_cap": 500
    }
  }
}

Generic scaffolds

These templates work on every automation channel. They intentionally create no entrypoint, so attach a trigger or binding before activation.

KindConfigGenerated graph
blank{}Empty canvas
welcome_flow{}Greeting message → end
faq_botOptional FAQ list and fallbackGreeting → input → keyword conditions → reply → end
lead_captureOptional contact field and tagMessage → validated input → persist contact field + tag → confirmation

faq_bot

{
  "kind": "faq_bot",
  "config": {
    "keywords": [
      { "label": "hours", "keyword": "hours", "reply": "We are open 9–6." },
      { "label": "price", "keyword": "price", "reply": "See our pricing page." }
    ],
    "fallback_reply": "Try asking about hours or pricing."
  }
}

Omit keywords to use the built-in hours, price, and location examples.

lead_capture

{
  "kind": "lead_capture",
  "config": {
    "capture_field": "email",
    "tag": "lead"
  }
}

capture_field is email or phone. The input validator checks that type, then contact_field_set persists the value on the contact and tag_add adds the configured tag.

Quick-automation presets

KindChannelsGenerated trigger and behavior
comment_to_dmInstagram, FacebookMatching comment → optional public reply → provider private reply
story_leadsInstagramStory reply → capture email/phone → persist + tag
follower_growthInstagramContest comment → validate mentions → private reply → optional story-mention wait → qualify
follow_to_dmInstagramFirst inbound DM → live follow check → welcome confirmed follower

comment_to_dm

{
  "kind": "comment_to_dm",
  "config": {
    "social_account_id": "acc_...",
    "post_ids": ["17895..."],
    "keyword_filter": ["link", "info"],
    "public_reply": "Sent!",
    "dm_message": {
      "blocks": [
        { "id": "b1", "type": "text", "text": "Here is the information you requested." }
      ]
    },
    "once_per_user": true,
    "fallback_message": "I could not send the private reply—please message us.",
    "daily_cap": 500
  }
}

The generated comment_created entrypoint stores keyword_filter as its runtime keywords config. once_per_user: true disables re-entry. A private reply must contain exactly one button-free text block because that is the provider-supported comment-reply shape. If provider delivery fails and fallback_message is set, the graph routes through its error port and posts the public fallback.

story_leads

{
  "kind": "story_leads",
  "config": {
    "social_account_id": "acc_...",
    "story_ids": null,
    "keyword_filter": ["guide"],
    "dm_message": {
      "blocks": [
        { "id": "b1", "type": "text", "text": "Reply with your email and we will follow up." }
      ]
    },
    "capture_field": "email",
    "success_tag": "story_lead",
    "daily_cap": 200
  }
}

story_ids: null matches any story. capture_field is email or phone; the captured value is persisted to that built-in contact field.

follower_growth

{
  "kind": "follower_growth",
  "config": {
    "social_account_id": "acc_...",
    "post_ids": ["17895..."],
    "trigger_keyword": "enter",
    "public_reply": "Entry received!",
    "dm_message": {
      "blocks": [
        { "id": "b1", "type": "text", "text": "Thanks for entering." }
      ]
    },
    "entry_requirements": {
      "must_tag_friends": 2,
      "must_share_story": true
    },
    "winner_tag": "contest_qualified",
    "daily_cap": 1000
  }
}

The preset counts @mentions in the triggering comment when must_tag_friends is non-zero. When must_share_story is true, it waits up to seven days for a story_mention event from the same contact before adding winner_tag; timeout exits through the incomplete branch.

follow_to_dm

{
  "kind": "follow_to_dm",
  "config": {
    "social_account_id": "acc_...",
    "dm_message": {
      "blocks": [
        { "id": "b1", "type": "text", "text": "Thanks for following, {{contact.name}}!" }
      ]
    },
    "daily_cap": 200,
    "cooldown_hours": 24
  }
}

Instagram does not provide a reliable “new follower” automation webhook for this flow. The preset therefore starts only on the contact's first inbound DM, queries the live is_user_follow_business profile field for the triggering account, and sends the message only when the relationship is confirmed. It never initiates an unsolicited DM merely because someone followed the account.

Safety and admission controls

  • Template configs are strict: misspelled or retired fields return validation errors instead of being ignored.
  • Preset messages reject unwired branch buttons. Comment private replies additionally reject quick replies, multiple blocks, and buttons.
  • daily_cap is enforced atomically per generated entrypoint and UTC day.
  • Re-entry and cooldown checks are serialized per contact and automation, preventing concurrent events from double-enrolling the same contact.
  • Reactive messages use explicit automation consent or the bounded customer-service reply window opened by the triggering inbound conversation; a suppression remains an absolute veto.

Insights and editing

created_from_template remains on the automation, so insights can be rolled up by preset:

GET /v1/automations/insights?created_from_template=comment_to_dm&period=30d

Use PUT /v1/automations/{id}/graph to edit the generated graph and the automation-entrypoint endpoints to tune or replace its trigger.

Found something wrong? Help us improve this page.

On this page