Forum automation

Embed
Preview of the card
<a href="https://forumulate.com/guides/automation"><img src="https://forumulate.com/guides/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/36aa4df0-1e95-4cef-8ae9-795169441345/pages/ed165156-0de5-4e99-a0b1-bb32ccfd2941/social-card.svg?v=3e7ae33eec8b" alt="Forum automation" width="600" height="315"></a>

An automation is a rule that watches your community and acts on its own: tag a topic that mentions a keyword, close one that has gone quiet, welcome a new member with a message, post to a chat channel when an incident opens. Each rule has one trigger, up to twenty conditions that must all match, and one action. This page covers how to write one, what you can trigger on and do, and how to fire a rule from your own systems.

All of these routes need forum.moderate, the capability that lets a person do these things by hand. A personal access token that carries it is how an external system authenticates.

Create a rule

POST /orgs/{orgId}/forum-automations
{
  "name": "Tag billing questions",
  "spaceId": null,
  "trigger": "topic.created",
  "conditions": [
    { "field": "title", "op": "contains", "value": "invoice" }
  ],
  "action": "add_tag",
  "config": { "tags": ["billing"] }
}

Field

Required

Notes

name

yes

1 to 200 characters. Also the default subject or reason on actions.

trigger

yes

One of the triggers below.

action

yes

One of the actions below.

spaceId

no

Confine the rule to one space. null or absent for the org.

conditions

no

Up to 20. Every condition must match for the action to run.

config

no

Settings for the action (and some triggers). See below.

enabled

no

Turn a rule off without deleting it.

A condition is { field, op, value }. The operators are eq, neq, contains, not_contains, has, not_has, lt and gte. Topic fields are title, body, kind, category, tags and tagCount. Depending on the event you can also test userId, trustLevel, isNewUser, isFirstTopicOrPost, userGroups, emailDomain, groupId, postAuthorId, isReply and hasLink. A condition on a field the event does not carry simply does not match.

Triggers

Group

Triggers

Topics

topic.created, topic.edited, topic.moved, topic.deleted, topic.solved, topic.stalled

Posts

post.created, post.edited, post.flagged

People

user.joined, user.promoted, badge.granted, group.member_added, group.member_removed, pm_created, category.created

Time

recurring (every config.intervalMinutes, default 1440), point_in_time (once, at config.fireAt, an ISO datetime, otherwise 422)

Inbound

api_call, fired only by the invoke route below

Status

status.incident.created, status.incident.updated, status.incident.resolved

topic.stalled waits for a quiet period set by config.stalledHours (default 72, between 1 and 8760), and stalled topics are looked for once an hour. recurring and point_in_time rules are swept every ten minutes, so expect them to fire within that window rather than to the second. Status triggers carry no topic, so use them with notify, send_webhook or send_chat_message.

Actions

Kind

Actions

Topic

add_tag, remove_tag (config.tags), recategorize (config.categoryId), close, reopen, open, pin, unpin, unlist, archive, banner_topic, set_timer

Posting

reply (config.message), notify (config.roles, config.message), flag

People

add_to_group, remove_from_group (config.groupId), send_message, suspend_user

Outbound

send_webhook (config.event, config.payload), send_chat_message (config.channelId, config.message)

Unknown triggers or actions are refused with a 422.

Run history and management

Call

What it does

GET /orgs/{orgId}/forum-automations?spaceId=

List rules, with runCount and lastRunAt.

GET /orgs/{orgId}/forum-automations/{id}

One rule.

PATCH /orgs/{orgId}/forum-automations/{id}

Change any field.

DELETE /orgs/{orgId}/forum-automations/{id}

Remove it.

GET /orgs/{orgId}/forum-automations/{id}/runs

Run log, newest first. limit 1 to 200 (default 50), walk with cursor. Each run has status of ok, skipped or error, and a detail.

When a rule does not seem to fire, read its runs first: a skipped run with the detail conditions not met means the event arrived and a condition failed.

Fire a rule from your own system

A rule with the api_call trigger runs only when something calls it:

POST /orgs/{orgId}/forum-automations/{id}/invoke
{ "payload": { "userId": "…", "reason": "chargeback" } }

The payload becomes the context the rule's conditions and action read, so a suspend_user rule can take its userId from the call. The response is the run, with its status and detail. Invoking a rule whose trigger is anything other than api_call is refused; this route cannot be used to fire an event-driven rule out of band.

In the API

Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go clients are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP call_api tool. Where a CLI command or MCP tool exists too, the last column names it. Operation names link to the API reference.

Automation

Operation

Request

What it does

Shortcuts

Automation_list

GET /orgs/{orgId}/forum-automations

List forum automations in an organization

client.forum.automations.list()

Automation_create

POST /orgs/{orgId}/forum-automations

Create a forum automation in an organization

client.forum.automations.create()

Automation_get

GET /orgs/{orgId}/forum-automations/{id}

Get the forum automation

client.forum.automations.get()

Automation_update

PATCH /orgs/{orgId}/forum-automations/{id}

Update the forum automation

client.forum.automations.update()

Automation_remove

DELETE /orgs/{orgId}/forum-automations/{id}

Delete the forum automation

client.forum.automations.remove()

Automation_runs

GET /orgs/{orgId}/forum-automations/{id}/runs

List runs in an organization (forum automations)

client.forum.automations.runs()

Automation_invoke

POST /orgs/{orgId}/forum-automations/{id}/invoke

Create the invoke in an organization

client.forum.automations.invoke()

The Forumulate teamUpdated