> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/stormkit-io/stormkit-io/llms.txt
> Use this file to discover all available pages before exploring further.

# Periodic Triggers

> Periodic Triggers allow you to set up automated HTTP requests to your endpoints on a scheduled basis using cron expressions.

## Overview

Periodic Triggers allow you to set up automated HTTP requests to your endpoints on a scheduled basis. These triggers can be used to:

* Automate recurring tasks
* Perform health checks
* Schedule data synchronization
* Run cleanup jobs
* Generate reports
* Send scheduled notifications
* Execute any API calls that need to run at regular intervals

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/stormkit-io-stormkit-io/assets/docs/features/periodic-triggers.png" alt="Periodic Triggers interface" />
</Frame>

<Warning>
  Trigger Functions can only be called on your custom domains.
</Warning>

## Setting Up a Trigger

<Steps>
  <Step title="Navigate to Triggers">
    Go to **Application** > **Environment** > **Triggers**
  </Step>

  <Step title="Create new trigger">
    Click on **New trigger** button
  </Step>

  <Step title="Configure trigger">
    Fill in the inputs in the modal:

    * **Name**: Descriptive name for the trigger
    * **URL**: The endpoint to call (must be on your custom domain)
    * **Cron expression**: When to run the trigger
    * **HTTP Method**: GET, POST, PUT, DELETE, etc.
    * **Headers** (optional): Custom headers to include
    * **Body** (optional): Request body for POST/PUT requests
  </Step>

  <Step title="Create trigger">
    Click on **Create** button to activate the trigger
  </Step>
</Steps>

This will call the specified endpoint with the configured cron periodicity. The timezone is **UTC**.

## Cron Expression Format

Periodic triggers use standard cron expressions to define schedules:

```
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, Sunday = 0 or 7)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
```

## Common Cron Examples

<CardGroup cols={2}>
  <Card title="Every Hour" icon="clock">
    ```
    0 * * * *
    ```

    Runs at the start of every hour
  </Card>

  <Card title="Every Day at Midnight" icon="moon">
    ```
    0 0 * * *
    ```

    Runs daily at 00:00 UTC
  </Card>

  <Card title="Every Monday at 9 AM" icon="calendar-week">
    ```
    0 9 * * 1
    ```

    Runs every Monday at 09:00 UTC
  </Card>

  <Card title="Every 15 Minutes" icon="stopwatch">
    ```
    */15 * * * *
    ```

    Runs every 15 minutes
  </Card>
</CardGroup>

### More Examples

| Schedule           | Cron Expression | Description         |
| ------------------ | --------------- | ------------------- |
| Every 5 minutes    | `*/5 * * * *`   | Frequent monitoring |
| Every 30 minutes   | `*/30 * * * *`  | Regular checks      |
| Every 6 hours      | `0 */6 * * *`   | Periodic sync       |
| Daily at 2 AM      | `0 2 * * *`     | Nightly cleanup     |
| Weekly on Sunday   | `0 0 * * 0`     | Weekly reports      |
| First day of month | `0 0 1 * *`     | Monthly tasks       |
| Weekdays at 8 AM   | `0 8 * * 1-5`   | Business hours      |

## Use Cases

### Health Checks

```json theme={null}
{
  "name": "API Health Check",
  "url": "https://example.com/api/health",
  "cron": "*/5 * * * *",
  "method": "GET"
}
```

### Data Synchronization

```json theme={null}
{
  "name": "Sync User Data",
  "url": "https://example.com/api/sync/users",
  "cron": "0 */6 * * *",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer <token>"
  }
}
```

### Cleanup Jobs

```json theme={null}
{
  "name": "Clean Old Sessions",
  "url": "https://example.com/api/cleanup/sessions",
  "cron": "0 2 * * *",
  "method": "POST"
}
```

### Report Generation

```json theme={null}
{
  "name": "Weekly Report",
  "url": "https://example.com/api/reports/weekly",
  "cron": "0 0 * * 0",
  "method": "POST",
  "body": {
    "format": "pdf",
    "recipients": ["admin@example.com"]
  }
}
```

## Debugging

Stormkit saves the request and response for each periodic task. You can view the last 25 logs for each trigger:

<Steps>
  <Step title="Locate trigger">
    Find the trigger in your Triggers list
  </Step>

  <Step title="Open menu">
    Expand the dot menu `(...)` next to the trigger
  </Step>

  <Step title="View logs">
    Click on the **Past triggers** menu item
  </Step>
</Steps>

The logs include:

* Timestamp
* Request details (URL, method, headers, body)
* Response status code
* Response body
* Execution duration
* Any errors encountered

<Info>
  Logs are retained for the last 25 executions per trigger.
</Info>

## Best Practices

### 1. Use Idempotent Endpoints

Ensure your endpoints can be safely called multiple times:

```javascript theme={null}
// Good: Idempotent cleanup
app.post('/api/cleanup/sessions', async (req, res) => {
  await Session.deleteMany({ expiresAt: { $lt: new Date() } });
  res.json({ ok: true });
});
```

### 2. Implement Authentication

Secure your trigger endpoints:

```javascript theme={null}
const TRIGGER_SECRET = process.env.TRIGGER_SECRET;

app.post('/api/trigger/cleanup', async (req, res) => {
  const auth = req.headers.authorization;
  
  if (auth !== `Bearer ${TRIGGER_SECRET}`) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  // Process trigger
});
```

### 3. Handle Errors Gracefully

```javascript theme={null}
app.post('/api/trigger/sync', async (req, res) => {
  try {
    await syncData();
    res.json({ success: true });
  } catch (error) {
    console.error('Sync failed:', error);
    res.status(500).json({ error: error.message });
  }
});
```

### 4. Set Appropriate Timeouts

Ensure long-running tasks complete within timeout limits:

```javascript theme={null}
// For long tasks, process in batches
app.post('/api/trigger/process', async (req, res) => {
  const batch = await getBatch(100); // Process in small batches
  await processBatch(batch);
  res.json({ processed: batch.length });
});
```

### 5. Monitor Execution

Log trigger executions for monitoring:

```javascript theme={null}
app.post('/api/trigger/cleanup', async (req, res) => {
  const startTime = Date.now();
  
  const result = await performCleanup();
  
  const duration = Date.now() - startTime;
  console.log(`Cleanup completed in ${duration}ms:`, result);
  
  res.json({ duration, ...result });
});
```

## Self-Hosting

<Info>
  If you are self-hosting Stormkit, the periodic jobs are handled by the workerserver.
</Info>

Ensure the workerserver is running and properly configured to execute periodic triggers.

## Limitations

* **Custom domains only** - Triggers must call endpoints on custom domains
* **UTC timezone** - All cron schedules run in UTC timezone
* **Execution logs** - Only the last 25 executions are stored
* **Timeout** - Triggered requests must complete within standard timeout limits

## Troubleshooting

<AccordionGroup>
  <Accordion title="Trigger not firing">
    * Verify the cron expression is correct using a [cron validator](https://crontab.guru/)
    * Check that the trigger is enabled
    * Ensure the URL points to a custom domain (not preview URL)
    * Review the trigger logs for errors
  </Accordion>

  <Accordion title="Endpoint returning errors">
    * Check the Past Triggers logs for error details
    * Verify the endpoint URL is correct and accessible
    * Ensure authentication headers are properly configured
    * Check server logs for the endpoint
  </Accordion>

  <Accordion title="Wrong timing">
    * Remember: all schedules are in UTC timezone
    * Convert your local time to UTC
    * Verify the cron expression matches your intent
    * Check Past Triggers for actual execution times
  </Accordion>

  <Accordion title="Timeout errors">
    * Optimize endpoint to complete faster
    * Process data in smaller batches
    * Consider async processing for long tasks
    * Check server timeout configurations
  </Accordion>
</AccordionGroup>

## Security Considerations

* **Authentication** - Always authenticate trigger requests
* **Rate limiting** - Implement rate limiting on trigger endpoints
* **Validation** - Validate all inputs even from scheduled triggers
* **Secrets** - Use environment variables for sensitive data
* **HTTPS only** - Always use HTTPS URLs for triggers
