syntax = "v1" type ( JobTemplatePath { Type string `path:"type" validate:"required"` // template type } JobIDPath { ID string `path:"id" validate:"required"` // job run id } JobScheduleIDPath { ID string `path:"id" validate:"required"` // schedule id } ListJobsReq { Scope string `form:"scope,optional"` // filter by scope ScopeID string `form:"scope_id,optional"` // filter by scope id Page int64 `form:"page,optional"` // page number starting at 1 PageSize int64 `form:"pageSize,optional"` // page size } ListJobSchedulesReq { Scope string `form:"scope,optional"` // filter by scope ScopeID string `form:"scope_id,optional"` // filter by scope id Page int64 `form:"page,optional"` // page number starting at 1 PageSize int64 `form:"pageSize,optional"` // page size } ListJobEventsReq { ID string `path:"id" validate:"required"` // job run id Limit int64 `form:"limit,optional"` // max events } CancelJobReq { ID string `path:"id" validate:"required"` // job run id Reason string `json:"reason,optional"` // cancel reason } CreateJobReq { TemplateType string `json:"template_type" validate:"required"` // job template type Scope string `json:"scope" validate:"required,oneof=user account system persona brand"` // job scope ScopeID string `json:"scope_id" validate:"required"` // scope id Payload map[string]interface{} `json:"payload,optional"` // job payload } UpsertJobTemplateReq { Type string `path:"type" validate:"required"` // template type Version int `json:"version,optional"` // template version Name string `json:"name" validate:"required"` // display name Description string `json:"description,optional"` // description Enabled bool `json:"enabled"` // enabled flag Repeatable bool `json:"repeatable"` // repeatable flag ConcurrencyPolicy string `json:"concurrency_policy,optional"` // concurrency policy DedupeKeys []string `json:"dedupe_keys,optional"` // dedupe keys TimeoutSeconds int `json:"timeout_seconds,optional"` // timeout seconds CancelPolicy JobCancelPolicyData `json:"cancel_policy,optional"` // cancel policy RetryPolicy JobRetryPolicyData `json:"retry_policy,optional"` // retry policy Steps []JobTemplateStepData `json:"steps" validate:"required,min=1,dive"` // steps } CreateJobScheduleReq { TemplateType string `json:"template_type" validate:"required"` // template type Scope string `json:"scope" validate:"required,oneof=user account system persona brand"` // scope ScopeID string `json:"scope_id" validate:"required"` // scope id Cron string `json:"cron" validate:"required"` // cron expression Timezone string `json:"timezone,optional"` // timezone PayloadTemplate map[string]interface{} `json:"payload_template,optional"` // payload template Enabled bool `json:"enabled"` // enabled flag } UpdateJobScheduleReq { ID string `path:"id" validate:"required"` // schedule id Cron string `json:"cron,optional"` // cron expression Timezone string `json:"timezone,optional"` // timezone PayloadTemplate map[string]interface{} `json:"payload_template,optional"` // payload template Enabled *bool `json:"enabled,optional"` // enabled flag } JobCancelPolicyData { Supported bool `json:"supported"` Mode string `json:"mode"` GraceSeconds int `json:"grace_seconds"` } JobRetryPolicyData { MaxAttempts int `json:"max_attempts"` BackoffSeconds []int `json:"backoff_seconds"` } JobTemplateStepData { ID string `json:"id"` Name string `json:"name"` WorkerType string `json:"worker_type"` TimeoutSeconds int `json:"timeout_seconds"` Cancelable bool `json:"cancelable"` } JobTemplateData { Type string `json:"type"` Version int `json:"version"` Name string `json:"name"` Description string `json:"description"` Enabled bool `json:"enabled"` Repeatable bool `json:"repeatable"` ConcurrencyPolicy string `json:"concurrency_policy"` DedupeKeys []string `json:"dedupe_keys"` TimeoutSeconds int `json:"timeout_seconds"` CancelPolicy JobCancelPolicyData `json:"cancel_policy"` RetryPolicy JobRetryPolicyData `json:"retry_policy"` Steps []JobTemplateStepData `json:"steps"` } JobTemplateListData { List []JobTemplateData `json:"list"` } JobStepProgressData { ID string `json:"id"` Status string `json:"status"` StartedAt *int64 `json:"started_at,optional"` EndedAt *int64 `json:"ended_at,optional"` Message string `json:"message,optional"` } JobProgressData { Summary string `json:"summary"` Percentage int `json:"percentage"` Steps []JobStepProgressData `json:"steps"` } JobData { ID string `json:"id"` TemplateType string `json:"template_type"` TemplateVersion int `json:"template_version"` Scope string `json:"scope"` ScopeID string `json:"scope_id"` Status string `json:"status"` Phase string `json:"phase"` WorkerType string `json:"worker_type"` Payload map[string]interface{} `json:"payload"` Progress JobProgressData `json:"progress"` Result map[string]interface{} `json:"result,optional"` Error string `json:"error,optional"` Attempt int `json:"attempt"` MaxAttempts int `json:"max_attempts"` CancelRequestedAt *int64 `json:"cancel_requested_at,optional"` CancelReason string `json:"cancel_reason,optional"` StartedAt *int64 `json:"started_at,optional"` CompletedAt *int64 `json:"completed_at,optional"` CreateAt int64 `json:"create_at"` UpdateAt int64 `json:"update_at"` } JobListData { Pagination PaginationData `json:"pagination"` List []JobData `json:"list"` } JobScheduleData { ID string `json:"id"` TemplateType string `json:"template_type"` Scope string `json:"scope"` ScopeID string `json:"scope_id"` Enabled bool `json:"enabled"` Cron string `json:"cron"` Timezone string `json:"timezone"` PayloadTemplate map[string]interface{} `json:"payload_template"` LastRunAt *int64 `json:"last_run_at,optional"` NextRunAt int64 `json:"next_run_at"` CreateAt int64 `json:"create_at"` UpdateAt int64 `json:"update_at"` } JobScheduleListData { Pagination PaginationData `json:"pagination"` List []JobScheduleData `json:"list"` } JobEventData { ID string `json:"id"` JobID string `json:"job_id"` Type string `json:"type"` From string `json:"from,optional"` To string `json:"to,optional"` Message string `json:"message"` Metadata map[string]interface{} `json:"metadata,optional"` CreateAt int64 `json:"create_at"` } JobEventListData { List []JobEventData `json:"list"` } ) @server( group: job prefix: /api/v1 middleware: AuthJWT tags: "Job - Core" summary: "Generic job templates, runs, schedules, cancel, and retry. Requires Bearer JWT." ) service gateway { @handler listJobTemplates get /job/templates returns (JobTemplateListData) @handler getJobTemplate get /job/templates/:type (JobTemplatePath) returns (JobTemplateData) @handler upsertJobTemplate put /job/templates/:type (UpsertJobTemplateReq) returns (JobTemplateData) @handler createJob post /jobs (CreateJobReq) returns (JobData) @handler getJob get /jobs/:id (JobIDPath) returns (JobData) @handler listJobs get /jobs (ListJobsReq) returns (JobListData) @handler listJobEvents get /jobs/:id/events (ListJobEventsReq) returns (JobEventListData) @handler cancelJob post /jobs/:id/cancel (CancelJobReq) returns (JobData) @handler retryJob post /jobs/:id/retry (JobIDPath) returns (JobData) @handler listJobSchedules get /job/schedules (ListJobSchedulesReq) returns (JobScheduleListData) @handler createJobSchedule post /job/schedules (CreateJobScheduleReq) returns (JobScheduleData) @handler updateJobSchedule put /job/schedules/:id (UpdateJobScheduleReq) returns (JobScheduleData) @handler enableJobSchedule post /job/schedules/:id/enable (JobScheduleIDPath) returns (JobScheduleData) @handler disableJobSchedule post /job/schedules/:id/disable (JobScheduleIDPath) returns (JobScheduleData) @handler deleteJobSchedule delete /job/schedules/:id (JobScheduleIDPath) }