AI Job Scheduling
Scheduler0's AI-powered prompt scheduling allows you to create jobs using natural language descriptions. Instead of writing complex cron expressions or managing timing logic, you can simply describe what you want in plain English, and Scheduler0's AI will generate the appropriate job configuration.
Overview
AI Prompt Job Scheduling transforms natural language requests into structured job configurations. This feature is perfect for:
- End-user interfaces: Let users describe scheduling needs in their own words
- Chatbots and assistants: Process natural language scheduling requests
- Rapid prototyping: Quickly create jobs without learning cron syntax
- Complex scheduling: Handle relative timing and event-based scheduling
How It Works
- Natural Language Input: You provide a description of what you want scheduled
- AI Processing: Scheduler0's AI analyzes the prompt and context
- Structured Output: AI returns a complete job configuration
- Job Creation: Use the AI output to create the actual job
Prompt Request Schema
{
"prompt": "Follow up 2 days after the demo",
"purposes": ["sales_follow_up", "customer_engagement"],
"events": ["demo_scheduled"],
"recipients": ["john@acme.com"],
"channels": ["email"],
"timezone": "America/New_York"
}
Request Fields
- prompt (required): Natural language description of the scheduling need. Must be between 1 and 160 characters (after trimming whitespace).
- purposes (optional): Array of business purposes for the job. Maximum 5 items, each item must be 36 characters or less.
- events (optional): Array of event types that trigger this job. Maximum 5 items, each item must be 36 characters or less.
- recipients (optional): Array of recipient identifiers. Maximum 5 items, each item must be 36 characters or less.
- channels (optional): Array of delivery channels. Maximum 5 items, each item must be 36 characters or less.
- timezone (optional): IANA timezone name (e.g.,
"UTC","America/New_York"). The AI interprets relative phrases ("today","tomorrow","9am") and emitsnextRunAt/startDate/endDatewith this timezone's offset. Defaults to"UTC"when omitted. Invalid timezone strings are rejected with400 Bad Request.
Note: This endpoint requires credits. Each prompt execution consumes 1 credit. Ensure your account has sufficient credits before making requests.
Timezone Behavior
The timezone field controls how the AI interprets time-relative phrases in your prompt:
- Omitted or empty: defaults to
UTC. A prompt like "send a reminder at 9am" schedules at09:00:00Z. - Provided (e.g.,
"America/New_York"): the same prompt schedules at09:00:00-05:00. Returned timestamps include the timezone's numeric offset, and the response'stimezonefield echoes the value you sent.
The Scheduler0 SaaS UI automatically detects the user's browser timezone (via Intl.DateTimeFormat().resolvedOptions().timeZone) and forwards it on every prompt request. If you build your own UI on top of the API, you should do the same so users see schedules in their local time without having to think about timezone math.
AI Response Schema
The AI returns an array of structured job configurations based on the job type:
[{
"kind": "FOLLOW_UP",
"purpose": "sales_follow_up",
"subject": "How was your demo?",
"nextRunAt": "2024-01-17T14:00:00Z",
"recurrence": "none",
"event": "demo_scheduled",
"delivery": "email",
"cronExpression": "0 14 17 1 *",
"channel": "primary",
"recipients": ["john@acme.com"],
"startDate": "2024-01-17T14:00:00Z",
"endDate": null,
"timezone": "America/New_York",
"metadata": {
"eventId": "event_123",
"calculatedOffset": "2 days"
}
}]
Response Fields
- kind: Job type (
FOLLOW_UP,REMINDER,DIGEST) - purpose: Primary business purpose
- subject: Subject line or title (optional)
- nextRunAt: Calculated execution time (RFC3339 format, optional)
- recurrence: Recurrence pattern (
every minute,every hour,every day,every week,every month,every year,none) - event: Associated event type (optional)
- delivery: Delivery method (optional)
- cronExpression: Generated cron expression for scheduling (optional)
- channel: Delivery channel (optional)
- recipients: Array of recipient identifiers (optional)
- startDate: Start date for the job (RFC3339 format, optional)
- endDate: End date for the job (RFC3339 format, optional)
- timezone: Timezone for the job (optional)
- metadata: Additional AI-generated context (optional object)
Job Types
1. FOLLOW_UP Jobs
One-time jobs triggered by specific events with calculated timing.
Characteristics:
- Require offset or absolute start time
- Subject line recommended
- Event-driven execution
Example Prompts:
- "Follow up 2 days after the demo"
- "Send a reminder 1 hour before the meeting"
- "Check in 3 days after the trial starts"
2. REMINDER Jobs
Recurring jobs with specified schedules and delivery windows.
Characteristics:
- Require recurrence pattern
- Include cron expression in Job.Spec
- Can be time-based or event-triggered
Example Prompts:
- "Send weekly check-ins every Monday"
- "Remind me to review reports every Friday at 3 PM"
- "Send monthly summaries on the 1st of each month"
3. DIGEST Jobs
Aggregated content delivery jobs with regular schedules.
Characteristics:
- Require cron expression in Job.Spec
- Include delivery configuration
- Content aggregation focus
Example Prompts:
- "Send daily digest of all activities"
- "Weekly summary of project updates"
- "Monthly report compilation"
Delivery Types
The AI supports multiple delivery methods:
Email Delivery
{
"type": "email",
"channel": "primary",
"recipients": ["user@example.com"],
"template": "welcome_template",
"payload": {
"userName": "John Doe",
"companyName": "Acme Corp"
}
}
Push Notification
{
"type": "push",
"channel": "mobile_app",
"recipients": ["device_token_123"],
"template": "notification_template",
"payload": {
"title": "Meeting Reminder",
"body": "Your meeting starts in 15 minutes"
}
}
SMS Delivery
{
"type": "sms",
"channel": "primary",
"recipients": ["+1234567890"],
"template": "sms_template",
"payload": {
"message": "Your appointment is tomorrow at 2 PM"
}
}
Slack Integration
{
"type": "slack",
"channel": "#general",
"recipients": ["@john.doe"],
"template": "slack_template",
"payload": {
"text": "Daily standup in 10 minutes",
"channel": "#engineering"
}
}
Webhook Delivery
{
"type": "webhook",
"webhookUrl": "https://api.example.com/webhook",
"template": "webhook_template",
"payload": {
"event": "scheduled_task",
"data": {
"taskId": "task_123",
"timestamp": "2024-01-15T14:00:00Z"
}
}
}
API Usage
Creating Jobs from Prompts
curl -X POST "https://api.scheduler0.com/v1/prompt" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Secret-Key: YOUR_API_SECRET" \
-H "X-Account-ID: YOUR_ACCOUNT_ID" \
-d '{
"prompt": "Follow up 2 days after the demo",
"purposes": ["sales_follow_up"],
"events": ["demo_scheduled"],
"recipients": ["john@acme.com"],
"channels": ["email"],
"timezone": "America/New_York"
}'
Note: This endpoint requires credits. Each request consumes 1 credit. If you have insufficient credits, you'll receive a 402 Payment Required response.
Client Library Usage
Node.js
const client = new Scheduler0Client({
baseUrl: 'https://api.scheduler0.com',
apiVersion: 'v1',
accountId: 'your-account-id',
apiKey: process.env.SCHEDULER0_API_KEY,
apiSecret: process.env.SCHEDULER0_API_SECRET,
});
// Create a follow-up job from natural language
const promptResponses = await client.ai.createJobFromPrompt({
prompt: "Follow up 2 days after the demo",
purposes: ["sales_follow_up", "customer_engagement"],
events: ["demo_scheduled"],
recipients: ["john@acme.com"],
channels: ["email"],
timezone: "America/New_York"
});
// Process each job configuration returned by AI
for (const promptResponse of promptResponses) {
// Use the AI response to create the job
const requestId = await client.jobs.create([{
projectId: 123,
timezone: promptResponse.timezone,
spec: promptResponse.cronExpression,
startDate: promptResponse.startDate || promptResponse.nextRunAt,
data: JSON.stringify({
subject: promptResponse.subject,
purpose: promptResponse.purpose,
delivery: promptResponse.delivery,
recipients: promptResponse.recipients
}),
retryMax: 2,
status: 'active',
executorId: 'email-executor-id',
createdBy: 'user123'
}]);
console.log('Job creation request ID:', requestId);
}
Go
package main
import (
"fmt"
"github.com/scheduler0/scheduler0-go-client"
)
func main() {
client, err := scheduler0_go_client.NewClient(
"https://api.scheduler0.com",
"v1",
scheduler0_go_client.WithAPIKey("your-api-key"),
scheduler0_go_client.WithAPISecret("your-api-secret"),
scheduler0_go_client.WithAccountID("your-account-id"),
)
if err != nil {
panic(err)
}
// Create job from prompt
promptResponses, err := client.CreateJobFromPrompt(&scheduler0_go_client.PromptJobRequest{
Prompt: "Send weekly reports every Monday at 9 AM",
Purposes: []string{"reporting", "communication"},
Events: []string{"weekly_cycle"},
Channels: []string{"email"},
Timezone: "America/New_York",
})
if err != nil {
panic(err)
}
// Process each job configuration returned by AI
for _, promptResponse := range promptResponses {
// Create the actual job using the AI-generated configuration
jobResponse, err := client.BatchCreateJobs([]scheduler0_go_client.JobRequestBody{
{
ProjectID: 123,
Timezone: promptResponse.Timezone,
Spec: promptResponse.CronExpression,
StartDate: *promptResponse.StartDate,
Data: fmt.Sprintf(`{"subject": "%s", "purpose": "%s"}`, promptResponse.Subject, promptResponse.Purpose),
RetryMax: 2,
Status: "active",
ExecutorID: &[]int64{456}[0],
CreatedBy: "user123",
},
})
if err != nil {
panic(err)
}
fmt.Printf("Created job with request ID: %s\n", jobResponse.Data)
}
}
AI Provider Settings (Bring Your Own Key)
By default, POST /prompt uses the model provider configured on the server. With BYOK you can instead supply your own model provider and API key per account; when configured, prompt execution uses your credentials and model.
Supported providers: OpenAI, Anthropic, and AWS Bedrock.
Getting AI Settings
Endpoint: GET /api/v1/account/ai-settings (scope: read)
Returns the account's AI configuration so a UI can pre-populate a settings form. Credential fields are never returned in plaintext — when a key is configured it is returned as a "•" sentinel so callers can tell "configured" from "not configured" without receiving any key material. If no settings have been saved, an object with just account_id is returned.
curl -X GET "https://api.scheduler0.com/v1/account/ai-settings" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Secret-Key: YOUR_API_SECRET" \
-H "X-Account-ID: YOUR_ACCOUNT_ID"
Response:
{
"success": true,
"data": {
"account_id": 1,
"provider": "anthropic",
"model": "claude-sonnet-4-5",
"anthropic_api_key": "•",
"bedrock_region": "us-east-1",
"date_created": "2024-01-15T10:30:00Z"
}
}
Saving AI Settings
Creates or replaces the account's AI settings (upsert). The account_id is always taken from the authenticated context — any value in the body is ignored.
Endpoint: PUT /api/v1/account/ai-settings (scope: write)
Request Body:
{
"provider": "anthropic",
"model": "claude-sonnet-4-5",
"openai_api_key": "",
"anthropic_api_key": "sk-ant-...",
"bedrock_access_key_id": "",
"bedrock_secret_key": "",
"bedrock_region": ""
}
Body Fields:
| Field | Description |
|---|---|
provider | One of openai, anthropic, or bedrock (case-insensitive). |
model | Model identifier. Optional — when empty, the provider default is used: gpt-4.1-mini (OpenAI), claude-sonnet-4-5 (Anthropic), global.anthropic.claude-sonnet-4-5-20250929-v1:0 (Bedrock). |
openai_api_key | API key, required when provider is openai. |
anthropic_api_key | API key, required when provider is anthropic. |
bedrock_access_key_id, bedrock_secret_key, bedrock_region | AWS credentials and region, required when provider is bedrock. |
Credential fields are encrypted at rest and are only ever decrypted inside the POST /prompt execution path.
Example:
curl -X PUT "https://api.scheduler0.com/v1/account/ai-settings" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Secret-Key: YOUR_API_SECRET" \
-H "X-Account-ID: YOUR_ACCOUNT_ID" \
-d '{
"provider": "anthropic",
"model": "claude-sonnet-4-5",
"anthropic_api_key": "sk-ant-..."
}'
Response:
{
"success": true,
"data": {
"message": "AI settings saved"
}
}
Note: If a prompt request comes in and the account has no valid AI settings (or the selected provider is missing its key), Scheduler0 falls back to the server's global provider configuration.
Common Use Cases
1. Sales Follow-ups
// Customer demo scheduled
const demoEvent = await client.events.create({
event: "demo_scheduled",
data: {
customerName: "Acme Corp",
customerEmail: "john@acme.com",
demoDate: "2024-01-15T14:00:00Z",
product: "Enterprise Plan"
},
projectId: 123,
startDate: "2024-01-15T14:00:00Z",
endDate: "2024-01-15T15:00:00Z",
timezone: "America/New_York"
});
// AI-generated follow-up
const followUp = await client.ai.createJobFromPrompt({
prompt: "Follow up 2 days after the demo with pricing information",
purposes: ["sales_follow_up", "lead_nurturing"],
events: ["demo_scheduled"],
metadata: {
eventId: demoEvent.data.id,
customerEmail: "john@acme.com",
product: "Enterprise Plan"
},
timezone: "America/New_York"
});
2. Customer Success
// Trial started event
const trialEvent = await client.events.create({
event: "trial_started",
data: {
customerName: "Beta Corp",
customerEmail: "jane@beta.com",
trialStartDate: "2024-01-15T00:00:00Z",
plan: "Pro Trial"
},
projectId: 123,
startDate: "2024-01-15T00:00:00Z",
endDate: "2024-01-15T00:00:00Z",
timezone: "America/New_York"
});
// AI-generated check-in schedule
const checkIns = await client.ai.createJobFromPrompt({
prompt: "Send weekly check-ins every Monday after the trial starts",
purposes: ["customer_success", "trial_engagement"],
events: ["trial_started"],
metadata: {
eventId: trialEvent.data.id,
customerEmail: "jane@beta.com",
trialDuration: "30 days"
},
timezone: "America/New_York"
});
3. File Delivery
// User requests file delivery
const fileDelivery = await client.ai.createJobFromPrompt({
prompt: "Send the quarterly report to john@company.com tomorrow at 2 PM",
purposes: ["file_delivery", "document_sharing"],
events: ["user_request"],
metadata: {
filePath: "/reports/q4-2024-report.pdf",
recipientEmail: "john@company.com",
senderEmail: "bot@company.com"
},
timezone: "America/New_York"
});
4. Recurring Tasks
// Regular maintenance tasks
const maintenance = await client.ai.createJobFromPrompt({
prompt: "Run database cleanup every Sunday at 2 AM",
purposes: ["maintenance", "database_health"],
events: ["weekly_cycle"],
metadata: {
environment: "production",
database: "main_db"
},
timezone: "UTC"
});
Best Practices
Prompt Writing
- Be Specific: Include timing, recipients, and context
- Use Natural Language: Write as you would speak
- Include Context: Provide relevant metadata
- Specify Timezone: Always include timezone information
Good Prompts
- "Send a follow-up email 2 days after the demo to john@acme.com"
- "Remind the team about the weekly standup every Monday at 9 AM"
- "Send monthly reports to managers on the 1st of each month"
- "Check in with trial users every 3 days after they sign up"
Poor Prompts
- "Send email" (too vague)
- "Remind me" (no timing specified)
- "Send report" (no recipients or schedule)
Error Handling
try {
const promptResponse = await client.ai.createJobFromPrompt({
prompt: "Follow up after demo",
purposes: ["sales"],
events: ["demo_scheduled"],
timezone: "America/New_York"
});
} catch (error) {
if (error.code === 'INVALID_PROMPT') {
console.error('Prompt could not be processed:', error.message);
} else if (error.code === 'MISSING_CONTEXT') {
console.error('Additional context required:', error.requiredFields);
} else {
console.error('Unexpected error:', error);
}
}
Limitations
- Language Support: Currently supports English prompts
- Complex Scheduling: Very complex scheduling logic may need manual configuration
- Context Dependency: Requires sufficient context for accurate interpretation
- Rate Limits: Subject to API rate limiting
Troubleshooting
Common Issues
- Ambiguous Prompts: Provide more specific timing and context
- Missing Context: Include relevant metadata and event information
- Timezone Issues: Ensure timezone is correctly specified
- Invalid Purposes: Use recognized purpose categories
Debug Mode
Enable debug logging to see AI processing details:
const client = new Scheduler0Client({
// ... other config
debug: true
});
const response = await client.ai.createJobFromPrompt({
// ... prompt config
});
console.log('AI Processing Details:', response.debug);
API Reference
For complete API documentation, see the Scheduler0 API Reference.