---
title: "POST /v1/automation-rules"
method: POST
path: "/v1/automation-rules"
tags: ["Automation Rules"]
---

# POST /v1/automation-rules

`POST /v1/automation-rules`

## Request

- Base URL: `https://api.yardstick.team`
- URL: `https://api.yardstick.team/v1/automation-rules`
- Auth: HTTP bearer

POST /v1/automation-rules

**Required scopes:** `automation_rules:write` Assigned interviewer changes (assignment_changed) and Update scheduling (update_scheduling) belong to job rules targeting candidate interviews. The action accepts template_key (default updated_scheduling_invitation), delivery (auto_send or auto_draft_review, default review), and task: { assignee: recruiter or { user_id }, title, due_in?: { value, unit: days or hours } }. Timing is always immediate and delivery_mode mirrors action.delivery. Enabled Update scheduling rules cannot overlap steps on the same job. The recommended starter begins disabled. Saved-rule preview makes no changes and uses the current interview state; manually shared links without a recorded send cannot be detected.

## Headers

- `Idempotency-Key` string
- `X-Request-Id` string

## Request body

- object
  - `pipeline_template_id` string, nullable
  - `job_id` string, nullable
  - `needs_step_pick` boolean
  - `name` string
  - `starter_key` string, nullable
  - `job_scope` 'all_compatible' | 'selected'
  - `job_posting_ids` string[]
  - `delivery_mode` 'auto_send' | 'auto_draft_review'
  - `timing` union
    - object
      - `type` 'immediate', required
    - object
      - `type` 'delay', required
      - `delayMinutes` integer, required
    - object
      - `type` 'interview_relative', required
      - `anchor` 'start' | 'end', required
      - `offsetMinutes` integer, required
  - `pipeline_stage_id` string, nullable
  - `trigger` 'stage_enter' | 'stage_exit' | 'step_ready' | 'booking_created' | 'booking_changed' | 'step_completed' | 'feedback_submitted' | 'all_scorecards_submitted' | 'interview_time' | 'assignment_changed' | 'booking_cancelled' | 'scorecard_due' | 'scorecard_overdue' | 'decision_brief_ready' | 'coaching_report_ready' | 'offer_approval_due' | 'offer_approval_escalation_due', required
  - `action` union, required
    - object
      - `type` 'create_task', required
      - `task_type` string, required: Add to My Tasks: scorecard_review on feedback_submitted, or coordination for a general follow-up. Same-kind tasks are stacked.
      - `task_title` string, required: Task title; {candidate} resolves to the candidate name.
      - `assigned_user_email` string
      - `assigned_role` 'assigned_interviewer' | 'recruiter' | 'hiring_manager' | 'team_owner'
      - `due_date` string: Existing fixed deadline; use due_in for recurring rules.
      - `due_in` object: Due this many days or hours after the rule fires; at most 365 days or 8760 hours. Cannot combine with due_date.
        - `value` integer, required
        - `unit` 'days' | 'hours', required
      - `context` object
    - object
      - `type` 'update_scheduling', required
      - `template_key` string
      - `delivery` 'auto_send' | 'auto_draft_review'
      - `task` object, required
        - `assignee` union, required
          - 'recruiter'
          - object
            - `user_id` string, uuid, required
        - `title` string, required
        - `due_in` object
          - `value` integer, required
          - `unit` 'days' | 'hours', required
    - object
      - `type` 'send_email', required
      - `email_type` 'acknowledgment' | 'advancement' | 'interview_confirmation' | 'rejection' | 'offer_declined' | 'offer' | 'hired' | 'withdrawn' | 'on_hold' | 'interview_cancellation'
      - `template_key` string
    - object
      - `type` 'send_scheduling_invitation', required
      - `interview_ids` string[], required
      - `format` 'combined' | 'separate', required
      - `template_key` string
    - object
      - `type` 'send_preparation_email', required
      - `template_key` 'candidate_preparation' | 'onsite_logistics' | 'technical_preparation'
    - object
      - `type` 'send_internal_email', required
      - `audience` 'assigned_interviewer' | 'recruiter' | 'hiring_manager' | 'team_owner' | 'offer_approver' | 'offer_requester', required
      - `template` string, required
    - object
      - `type` 'verify_calendar_event', required
  - `condition` object
    - `step_position` union
      - object
        - `which` 'next', required
      - object
        - `which` 'first', required
        - `kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
      - object
        - `which` 'last', required
        - `kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
      - object
        - `which` 'last_before', required
        - `kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
        - `anchor_kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
    - `public_application_only` boolean
    - `interview_ids` string[]
    - `step_kinds` string[]
  - `is_active` boolean
  - `position` integer

## Response `201`

Success

- AutomationRule
  - `pipeline_template_id` string, nullable, required
  - `job_id` string, nullable, required
  - `needs_step_pick` boolean, required
  - `name` string, required
  - `starter_key` string, nullable, required
  - `job_scope` 'all_compatible' | 'selected', required
  - `job_posting_ids` string[], required
  - `delivery_mode` 'auto_send' | 'auto_draft_review', required
  - `timing` union, required
    - object
      - `type` 'immediate', required
    - object
      - `type` 'delay', required
      - `delayMinutes` integer, required
    - object
      - `type` 'interview_relative', required
      - `anchor` 'start' | 'end', required
      - `offsetMinutes` integer, required
  - `pipeline_stage_id` string, nullable, required
  - `trigger` 'stage_enter' | 'stage_exit' | 'step_ready' | 'booking_created' | 'booking_changed' | 'step_completed' | 'feedback_submitted' | 'all_scorecards_submitted' | 'interview_time' | 'booking_cancelled' | 'scorecard_due' | 'scorecard_overdue' | 'decision_brief_ready' | 'coaching_report_ready' | 'offer_approval_due' | 'offer_approval_escalation_due', required
  - `action` union, required
    - object
      - `type` 'create_task', required
      - `task_type` string, required: Add to My Tasks: scorecard_review on feedback_submitted, or coordination for a general follow-up. Same-kind tasks are stacked.
      - `task_title` string, required: Task title; {candidate} resolves to the candidate name.
      - `assigned_user_email` string
      - `assigned_role` 'assigned_interviewer' | 'recruiter' | 'hiring_manager' | 'team_owner'
      - `due_date` string: Existing fixed deadline; use due_in for recurring rules.
      - `due_in` object: Due this many days or hours after the rule fires; at most 365 days or 8760 hours. Cannot combine with due_date.
        - `value` integer, required
        - `unit` 'days' | 'hours', required
      - `context` object
    - object
      - `type` 'send_email', required
      - `email_type` 'acknowledgment' | 'advancement' | 'interview_confirmation' | 'rejection' | 'offer_declined' | 'offer' | 'hired' | 'withdrawn' | 'on_hold' | 'interview_cancellation'
      - `template_key` string
    - object
      - `type` 'send_scheduling_invitation', required
      - `interview_ids` string[], required
      - `format` 'combined' | 'separate', required
      - `template_key` string
    - object
      - `type` 'send_preparation_email', required
      - `template_key` 'candidate_preparation' | 'onsite_logistics' | 'technical_preparation'
    - object
      - `type` 'send_internal_email', required
      - `audience` 'assigned_interviewer' | 'recruiter' | 'hiring_manager' | 'team_owner' | 'offer_approver' | 'offer_requester', required
      - `template` string, required
    - object
      - `type` 'verify_calendar_event', required
  - `condition` object, required
    - `step_position` union
      - object
        - `which` 'next', required
      - object
        - `which` 'first', required
        - `kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
      - object
        - `which` 'last', required
        - `kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
      - object
        - `which` 'last_before', required
        - `kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
        - `anchor_kind` 'candidate_interview' | 'reference_check' | 'internal_debrief' | 'offer_meeting', required
    - `public_application_only` boolean
    - `interview_ids` string[]
    - `step_kinds` string[]
  - `is_active` boolean, required
  - `position` integer, nullable, required
  - `id` string, required
  - `object` 'automation_rule', required
  - `created_at` string, nullable, required
  - `updated_at` string, nullable, required

## Other responses

- `400`: Invalid request
- `401`: Authentication failure
- `403`: Permission denied (scope or feature flag)
- `404`: Resource not found. The error uses the resource-specific code and param names the exact body field or path parameter that referenced it.
- `409`: Conflict: idempotency key reuse, or an enabled Update scheduling rule already covers these interview steps. An automation_rule_overlap error includes blocking_rule with its id, name and url.
- `429`: Rate limited
- `500`: Internal error

---

[API](https://skmtc.dev/yardstick/apis/yardstick-public-api.md) · [All operations](https://skmtc.dev/yardstick/apis/yardstick-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/yardstick/apis/yardstick-public-api/revisions/35b5a6e88b35?raw)
