The Only API docs

Automations

Condition operators, payload templating, and the six action types.

An automation is a rule stored on your panel: when an event of a given type arrives and every condition matches, run an action. No infrastructure needed on your side.

curl -X POST "$BASE/api/crm/$CRM/automations" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Thank big tippers on Discord",
        "trigger_event": "new_tip",
        "conditions": [
          { "field": "payload.amount", "op": "gt", "value": 20 }
        ],
        "action_type": "discord",
        "action_params": {
          "url": "https://discord.com/api/webhooks/…",
          "message": "💸 {payload.fan.username} tipped ${payload.amount}"
        },
        "is_active": true
      }'

Conditions

A list, joined with AND. Every condition must match for the action to run. An empty list matches every event of that type.

{
  "conditions": [
    { "field": "payload.amount", "op": "gt", "value": 5 },
    { "field": "payload.fan.username", "op": "neq", "value": "banned_user" }
  ]
}

field is a dotted path into the event envelope, so event_type, of_user_id, occurred_at and anything under payload. are all addressable.

Operators

opMeaning
eqequal
neqnot equal
gt / gtegreater than / or equal
lt / lteless than / or equal
containssubstring
startswithprefix
inthe field's value appears in the list you supply

Actions

action_typeaction_params
webhook{ "url", "method"?, "headers"?, "body"? }unsigned and un-retried, unlike a first-party webhook
discord{ "url", "message", "username"? }
slack{ "url", "message" }
telegram{ "bot_token", "chat_id", "message" }
send_dm{ "message", "to_fan_id"? } — defaults to payload.fan.id
tag_fan{ "tag": "vip" }

Templating

Any message supports {dotted.path} interpolation against the event, resolved at dispatch:

"💸 {payload.fan.username} tipped ${payload.amount} on {occurred_at}"

Templating applies to every string in action_paramsurl, tag, to_fan_id, nested objects and arrays — not just message. Credential keys (bot_token, secret, token, api_key, password) are deliberately excluded and passed through byte-for-byte.

An unresolvable path renders as an empty string, not as literal {…}. A typo silently leaves a hole in the message ("💸 tipped $") rather than announcing itself — check the first delivery.

send_dm needs write actions enabled

send_dm is an OnlyFans write and is gated per account by allow_of_write_actions. Enable it via PATCH /accounts/{of_user_id}/polling. Otherwise the action is logged as a failed run in GET /automations/{id}/runs with error_snippet: "send_dm blocked: account has allow_of_write_actions=false". There is no HTTP error to observe — automations run in the event fan-out, not in a request. See Connect an account.

Managing automations

GET    /automations                    # list
POST   /automations                    # create
GET    /automations/{id}               # read one
PATCH  /automations/{id}               # update (send {"is_active": false} to pause)
DELETE /automations/{id}
POST   /automations/{id}/run-now       # fire the action immediately, for testing
GET    /automations/{id}/runs          # run history

run-now validates an action without waiting for a real event — but it builds a synthetic event from the sample_payload you supply, so send one. Without it the payload is empty, every payload.* condition fails, and the run is recorded as skipped.

curl -X POST "$BASE/api/crm/$CRM/automations/$ID/run-now" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"sample_payload": {"amount": 25, "fan": {"id": "987", "username": "somefan"}}}'

The response is {"status": "success" | "skipped" | "failed"}. GET /runs (default 50, max 200) has the history.

POST /automations also accepts of_user_id to scope a rule to one connected account — the per-account routing that webhooks cannot do.

Condition operators are not validated on create

An unknown or misspelled op is accepted, then fails every comparison at dispatch, so the automation silently never fires. Check /runs after creating a rule.

Worked examples

Automations, webhooks, or your own code?

Automations are the right tool when the reaction is a notification or a simple one-step side effect. Once you need branching logic, external data, or state, use a webhook and do the work in your own service.

Both run from the same event emission, so you can use them together — an automation for the Discord ping, a webhook for your database.

On this page