Auto-Reply API
The Auto-Reply system evaluates every incoming text message against a set of rules and sends automatic responses when a rule matches. Rules are stored in the main database (DB_PATH) in the auto_reply_rules table. All endpoints are mounted at /api/auto_reply.
Rule Data Model
id (int)trigger_phrase (str, required)match_type (str, required)contains — phrase appears anywhere in the message (case-insensitive)exact — message equals the phrase exactly (case-insensitive)regex — full re.search() with re.IGNORECASEresponse_message (str, required)cooldown_seconds (int)60. Set to 0 to disable cooldown.is_enabled (bool)true.created_at / updated_atCreate Rule
POST /api/auto_reply/rules
POST /api/auto_reply/rules
Content-Type: application/json
{
"trigger_phrase": "status?",
"match_type": "contains",
"response_message": "All systems operational.",
"cooldown_seconds": 60,
"is_enabled": true
}
Returns HTTP 201 with the created rule including its id.
Regex example:
{
"trigger_phrase": "^ping$",
"match_type": "regex",
"response_message": "PONG!",
"cooldown_seconds": 15,
"is_enabled": true
}
match_type is regex, the pattern is validated with re.compile() on write. An invalid regex returns 422 Unprocessable Entity with a descriptive error.List Rules
GET /api/auto_reply/rules
only_enabled (bool, optional)true, returns only enabled rules. If false, only disabled. If omitted, returns all rules.GET /api/auto_reply/rules
GET /api/auto_reply/rules?only_enabled=true
Returns an array of rule objects ordered by id ASC.
Get Single Rule
GET /api/auto_reply/rules/{rule_id}
GET /api/auto_reply/rules/3
→ Rule object, or 404
Update Rule
PUT /api/auto_reply/rules/{rule_id}
Full replacement of all rule fields — provide all fields, not just the ones being changed.
PUT /api/auto_reply/rules/3
Content-Type: application/json
{
"trigger_phrase": "status?",
"match_type": "contains",
"response_message": "System OK. Battery: {battery_level}%",
"cooldown_seconds": 120,
"is_enabled": true
}
The response_message field supports placeholder substitution when processed by the auto-reply engine. Available placeholders: {node_id}, {short_name}, {long_name}, {latitude}, {longitude}, {battery_level}, {voltage}.
Delete Rule
DELETE /api/auto_reply/rules/{rule_id}
DELETE /api/auto_reply/rules/3
→ {"detail": "Auto-reply rule with ID 3 successfully deleted."}
Returns 404 if not found.
Bulk Enable / Disable
PUT /api/auto_reply/rules/bulk/enable
Enables or disables all rules at once.
enable (bool, required)true to enable all, false to disable all.PUT /api/auto_reply/rules/bulk/enable?enable=false
→ {"detail": "Successfully set 'is_enabled' to False for 5 rules."}
How Matching Works
Every incoming TEXT_MESSAGE_APP packet is checked against all enabled rules in the background packet processing worker. The matching logic (from auto_reply.py):
- Skip disabled rules.
- Check per-sender cooldown — if the same sender triggered this rule within
cooldown_seconds, skip. - Match the message text using the rule's
match_type:contains:trigger.lower() in message.lower()exact:trigger.lower() == message.lower()regex:re.search(trigger, message, re.IGNORECASE)
- On match: send response, update cooldown tracker, continue to next rule (multiple rules can fire for one message).
Response Placeholders
The response_message supports {placeholder} tokens that are replaced with live node data at send time:
| Placeholder | Value |
|---|---|
{node_id} | Sender's node ID e.g. !aabbccdd |
{short_name} | Sender's short name (4-char) |
{long_name} | Sender's long name |
{latitude} | Sender's last known latitude |
{longitude} | Sender's last known longitude |
{battery_level} | Sender's battery percentage |
{voltage} | Sender's voltage (2 decimal places) |
Example: "Hello {short_name}! Your battery is at {battery_level}%."