Automation API
Rule-Based Automation
Create rules, inspect executions, trigger webhooks, and manage approvals
PrimeCal automation is built around user-owned rules with triggers, conditions, and actions. This page documents the full non-admin automation surface directly from the controller and DTOs.
JWT or user API keyPublic webhook triggerAudit logs and statsSmart values
Source
- Controller:
backend-nestjs/src/automation/automation.controller.ts - Rule DTOs:
backend-nestjs/src/automation/dto/automation-rule.dto.ts - Request DTOs:
backend-nestjs/src/automation/dto/automation-requests.dto.ts - Audit DTOs:
backend-nestjs/src/automation/dto/automation-audit-log.dto.ts - Enums:
backend-nestjs/src/entities/automation-rule.entity.ts,backend-nestjs/src/entities/automation-condition.entity.ts,backend-nestjs/src/entities/automation-action.entity.ts
Authentication and Permissions
- All rule-management routes require authentication.
POST /api/automation/webhook/:tokenis explicitly public via@Public().- Rules are scoped to the authenticated user.
- Sensitive rules can require explicit approval before execution.
- The controller uses the API validation pipe for create and update operations.
Endpoint Reference
| Method | Path | Purpose | Request or query | Auth | Source |
|---|---|---|---|---|---|
POST | /api/automation/rules | Create a rule. | Body: rule create payload | JWT or user API key | automation/automation.controller.ts |
GET | /api/automation/rules | List rules with pagination and optional enabled filter. | Query: page,limit,enabled | JWT or user API key | automation/automation.controller.ts |
GET | /api/automation/rules/:id | Get one rule. | Path: id | JWT or user API key | automation/automation.controller.ts |
PUT | /api/automation/rules/:id | Update a rule. | Path: id, body: partial rule payload | JWT or user API key | automation/automation.controller.ts |
DELETE | /api/automation/rules/:id | Delete a rule. | Path: id | JWT or user API key | automation/automation.controller.ts |
POST | /api/automation/rules/:id/execute | Run a rule immediately. | Path: id | JWT or user API key | automation/automation.controller.ts |
GET | /api/automation/rules/:id/audit-logs | List audit logs for one rule. | Path: id, query from AuditLogQueryDto | JWT or user API key | automation/automation.controller.ts |
GET | /api/automation/audit-logs/:logId | Get one audit log entry. | Path: logId | JWT or user API key | automation/automation.controller.ts |
GET | /api/automation/rules/:id/stats | Get execution statistics for a rule. | Path: id | JWT or user API key | automation/automation.controller.ts |
POST | /api/automation/webhook/:token | Trigger a webhook-backed rule. | Path: token, JSON payload | Public | automation/automation.controller.ts |
POST | /api/automation/rules/:id/webhook/regenerate | Regenerate the rule's webhook token. | Path: id | JWT or user API key | automation/automation.controller.ts |
POST | /api/automation/rules/:id/webhook/rotate-secret | Rotate the webhook signing secret. | Path: id | JWT or user API key | automation/automation.controller.ts |
POST | /api/automation/rules/:id/approve | Approve a sensitive rule. | Path: id, body: note | JWT or user API key | automation/automation.controller.ts |
GET | /api/automation/smart-values/:triggerType | List smart values for a trigger type. | Path: triggerType | JWT or user API key | automation/automation.controller.ts |
Request Shapes
List and approval queries
ListAutomationRulesQueryDto.page: optional int, minimum1, default1ListAutomationRulesQueryDto.limit: optional int,1..100, default20ListAutomationRulesQueryDto.enabled: optional booleanApproveAutomationRuleDto.note: optional string, max 500 chars
Rule definition
CreateAutomationRuleDto in backend-nestjs/src/automation/dto/automation-rule.dto.ts
name: required,1..200charsdescription: optional, max 1000 charstriggerType: required enumtriggerConfig: optional objectisEnabled: optional booleanconditionLogic: optional enumAND|ORconditions: optional array, max 10 itemsactions: required array,1..5items
UpdateAutomationRuleDto keeps the same structure but makes all fields optional.
Trigger types
From backend-nestjs/src/entities/automation-rule.entity.ts
event.createdevent.updatedevent.deletedevent.starts_inevent.ends_inrelative_time_to_eventcalendar.importedscheduled.timewebhook.incoming
Relative time trigger config
The relative-time trigger config has nested validation for:
eventFilter.calendarIdseventFilter.titleContainseventFilter.descriptionContainseventFilter.tagseventFilter.labelseventFilter.isAllDayOnlyeventFilter.isRecurringOnlyreferenceTime.base:start|endoffset.direction:before|afteroffset.value: int>= 0offset.unit:minutes|hours|days|weeksexecution.runOncePerEventexecution.fireForEveryOccurrenceOfRecurringEventexecution.skipPastexecution.pastDueGraceMinutes:0..60execution.schedulingWindowDays:1..730
Conditions
CreateConditionDto
field: required enumoperator: required enumvalue: required string, max 1000 charsgroupId: optional stringlogicOperator: required enumAND|OR|NOTorder: optional number
Current condition fields:
event.titleevent.descriptionevent.locationevent.notesevent.durationevent.is_all_dayevent.colorevent.statusevent.calendar.idevent.calendar.namewebhook.data
Current operators include:
contains,not_contains,matches,not_matchesequals,not_equalsstarts_with,ends_withis_empty,is_not_emptygreater_than,less_thangreater_than_or_equal,less_than_or_equalis_true,is_falsein,not_in,in_list,not_in_list
Actions
CreateActionDto
actionType: required enumactionConfig: optional objectorder: optional number
Current action types:
set_event_coloradd_event_tagsend_notificationupdate_event_titleupdate_event_descriptioncancel_eventmove_to_calendarcreate_taskwebhook
Example Calls
Create a rule
curl -X POST "$PRIMECAL_API/api/automation/rules" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Highlight school pickups",
"triggerType": "event.created",
"conditionLogic": "AND",
"conditions": [
{
"field": "event.title",
"operator": "contains",
"value": "pickup",
"logicOperator": "AND"
}
],
"actions": [
{
"actionType": "set_event_color",
"actionConfig": { "color": "#f59e0b" }
}
]
}'
Run a rule now
curl -X POST "$PRIMECAL_API/api/automation/rules/14/execute" \
-H "Authorization: Bearer $TOKEN"
Trigger a webhook rule
curl -X POST "$PRIMECAL_API/api/automation/webhook/$WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"payload": {
"source": "school-system",
"message": "Late pickup today"
}
}'
Read smart values
curl "$PRIMECAL_API/api/automation/smart-values/event.created" \
-H "Authorization: Bearer $TOKEN"
Response and Behavior Notes
DELETE /api/automation/rules/:idreturns204 No Content.POST /api/automation/rules/:id/executereturns a message and updated execution count.POST /api/automation/rules/:id/webhook/regeneratereturns the newwebhookToken.POST /api/automation/rules/:id/webhook/rotate-secretreturns the newwebhookSecretandgraceUntil.- Public webhook execution uses the raw body and headers when evaluating the rule.
Best Practices
- Keep actions narrow and deterministic. Rules with too many side effects become hard to debug.
- Use smart values and the catalog returned by
GET /api/automation/smart-values/:triggerTypeinstead of hard-coding tokens. - Prefer
GET /api/automation/rules/:id/audit-logsand/statswhen troubleshooting before editing the rule itself. - Regenerate webhook tokens if a URL leaks. Rotate webhook secrets if the signing secret leaks.
- When building UI, treat relative-time triggers as a first-class subtype because their config is far richer than basic event triggers.