# Schedule recurring HTTP requests

Source: https://stormedo.com/docs/how-to/schedule-requests/

Create an interval or cron schedule, inspect each delivery, pause future runs, and handle missed occurrences and usage limits.

A schedule creates a separate HTTP `POST` request on each occurrence. Each request gets its own ID and retry budget. You need a project API key and available [workspace schedule allowance](https://stormedo.com/docs/reference/plans-and-limits/).

## Create a five-minute schedule

```bash
curl --request POST \
  'https://api.stormedo.com/schedules' \
  --header "Authorization: Bearer $STORMEDO_TOKEN" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: five-minute-ping-001' \
  --data '{
    "name": "Five-minute ping",
    "timing": {"type": "interval", "every_seconds": 300},
    "request": {
      "url": "https://api.stormedo.com/ping",
      "body": {"message": "Scheduled delivery"},
      "retry": 3
    }
  }'
```

Expect `201 Created`. Keep `data.id`, which starts with `sch_`, and `data.next_run_at`. With no `starts_at`, the first run is one interval after creation. `retry: 3` permits four attempts for each occurrence.

The SDK equivalents use `intervalTiming({ minutes: 5 })` in JavaScript and `interval_timing(timedelta(minutes=5))` in Python. See the [SDK guides](https://stormedo.com/docs/sdks/javascript/) for complete client examples.

## Use a local wall-clock time

For 09:00 each day in Kolkata, use this timing object instead:

```json
{
  "type": "cron",
  "expression": "0 9 * * *",
  "timezone": "Asia/Kolkata"
}
```

Cron uses five fields: minute, hour, day of month, month, day of week. Supply an IANA timezone. Use UTC or a fixed interval when elapsed time matters more than a local wall-clock time. See [cron timing](https://stormedo.com/docs/api-reference/schedules/#cron-timing) for daylight-saving behavior.

## Inspect an occurrence

Retrieve the schedule with `GET /schedules/{schedule_id}`. `last_run_outcome: "enqueued"` means an occurrence created a request, not that the destination succeeded. Inspect recurring requests with `GET /requests?source=recurring`; match each item’s `schedule_id` to your schedule and inspect its attempts.

Intervals preserve their timing anchor. Missed occurrences are skipped, not replayed in a catch-up burst. A previous occurrence can still be delivering when the next starts. Schedules do not serialize your business work.

## Pause, resume, or remove it

```bash
curl --request POST \
  "https://api.stormedo.com/schedules/$SCHEDULE_ID/pause" \
  --header "Authorization: Bearer $STORMEDO_TOKEN"
```

Set `SCHEDULE_ID` to the returned `sch_...` value. Pause returns an updated summary with `status: "paused"` and `next_run_at: null`. Replace `/pause` with `/resume` to restart future occurrences. Missed paused runs are not backfilled.

To clean up this test, send `DELETE /schedules/{schedule_id}`. Deletion returns `204` and stops future occurrences. Pause and deletion do not cancel requests already created; cancel those requests separately if necessary. Paused schedules still consume schedule allowance.

## Change the definition safely

Use `PATCH /schedules/{schedule_id}`. A supplied `request` replaces its URL, body, and retry settings. Include the full intended request. Omitted `headers` preserves secrets, while `headers: {}` clears them. Never write the `[REDACTED]` values from a detail response back into a definition.

At the monthly request limit, an occurrence records `skipped_usage_limit` and creates no request. The schedule stays active. Upgrade or wait for allowance to reset; the skipped occurrence is not retried later. Full fields and errors are in the [schedule API reference](https://stormedo.com/docs/api-reference/schedules/).
