Recurring schedules API
Schedules create normal Stormedo requests at recurring times. Each occurrence receives its own req_ ID, delivery lifecycle, retries, and attempt history.
All schedule endpoints use the project selected by the bearer API key.
| Operation | Success response |
|---|---|
POST /schedules |
201, schedule summary inside data. |
GET /schedules |
200, array of summaries inside data. |
GET /schedules/{id} |
200, schedule detail inside data. |
PATCH /schedules/{id} |
200, updated summary inside data. |
POST /schedules/{id}/pause or /resume |
200, updated summary inside data. |
DELETE /schedules/{id} |
204, no body. |
Create a schedule
Section titled “Create a schedule”POST https://api.stormedo.com/schedulesContent-Type: application/jsonIdempotency-Key is required and must contain between 1 and 255 bytes.
curl --request POST \ 'https://api.stormedo.com/schedules' \ --header "Authorization: Bearer $STORMEDO_TOKEN" \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: inventory-sync-schedule' \ --data '{ "name": "Inventory sync", "timing": { "type": "cron", "expression": "0 */6 * * *", "timezone": "Asia/Kolkata" }, "request": { "url": "https://your-app.example/inventory/sync", "body": { "full_sync": true }, "headers": { "Authorization": "Bearer destination-token" }, "retry": 3 } }'Top-level fields
Section titled “Top-level fields”| Field | Required | Description |
|---|---|---|
name |
Yes | Display name containing 1 to 120 bytes. Leading and trailing whitespace is removed. |
timing |
Yes | Cron or fixed-interval timing definition. |
request |
Yes | HTTP request created for every occurrence. |
Request fields
Section titled “Request fields”| Field | Required | Default | Description |
|---|---|---|---|
url |
Yes | None | Public HTTPS destination. Schedule deliveries use POST. |
body |
No | No body | A non-null JSON value, delivered as application/json, up to 256 KiB serialized. Omission or null sends no body. |
headers |
No | {} |
Destination headers stored with the schedule. Values are redacted in detail responses. |
retry |
No | 0 |
Additional retries after the first attempt, from 0 through 19. |
Destination headers are limited to 64 entries and 32 KiB combined. The reserved destination headers cannot be supplied. Occurrences use a 50-second per-attempt timeout and the default queue; schedules do not expose custom method, timeout, metadata, or queue fields.
Cron timing
Section titled “Cron timing”{ "type": "cron", "expression": "0 9 * * *", "timezone": "Asia/Kolkata"}Cron expressions use exactly five fields: minute, hour, day of month, month, and day of week. timezone must be a valid IANA timezone.
For a daily fixed local time, the current scheduler moves a time inside a spring-forward gap to the first valid instant after that gap. For example, 30 2 * * * in America/New_York runs at 03:00 local on March 8, 2026. During a fall-back overlap, a daily fixed time runs at its first occurrence: 30 1 * * * runs at 01:30 EDT on November 1, 2026, then 01:30 EST the following day. Wildcard/interval cron patterns can behave differently across repeated hours. Use a fixed interval or UTC when elapsed-time cadence is the requirement, and inspect next_run_at for the configured expression.
Interval timing
Section titled “Interval timing”{ "type": "interval", "every_seconds": 900}every_seconds must be a whole number of minutes from 60 seconds through 30 days. On creation, starts_at must be a future RFC 3339 timestamp. If omitted, the first occurrence happens one complete interval after creation.
Response
Section titled “Response”Schedule creation returns 201 Created:
{ "success": true, "data": { "id": "sch_2dV8nB1mQ4sK7xH9pL3cF", "name": "Inventory sync", "timing": { "type": "cron", "expression": "0 */6 * * *", "timezone": "Asia/Kolkata" }, "status": "active", "url": "https://your-app.example/inventory/sync", "retry": 3, "next_run_at": "2026-08-28T12:30:00Z", "last_run_at": null, "last_run_outcome": null, "created_at": "2026-08-28T10:15:30Z", "updated_at": "2026-08-28T10:15:30Z" }, "error": null, "meta": null, "request_id": "95c07a5c-3d44-4b89-84a6-c5a71313bff2"}Repeating the same definition and key returns the same schedule. Reusing the key with different input returns 409 Conflict.
List schedules
Section titled “List schedules”GET https://api.stormedo.com/schedulesReturns an array of schedule summaries for the API key project.
Retrieve a schedule
Section titled “Retrieve a schedule”GET https://api.stormedo.com/schedules/{schedule_id}Returns the summary fields with top-level url and retry replaced by the complete request definition. This includes the configured JSON body; destination header values appear as [REDACTED].
Update a schedule
Section titled “Update a schedule”PATCH https://api.stormedo.com/schedules/{schedule_id}Content-Type: application/jsonSend at least one of name, timing, or request:
curl --request PATCH \ 'https://api.stormedo.com/schedules/sch_2dV8nB1mQ4sK7xH9pL3cF' \ --header "Authorization: Bearer $STORMEDO_TOKEN" \ --header 'Content-Type: application/json' \ --data '{ "timing": { "type": "interval", "every_seconds": 14400 } }'When request is supplied, include the complete new URL, body, and retry definition. Omitting headers preserves the stored destination headers; headers: {} clears them. Do not round-trip [REDACTED] values. The update replaces the next timer when the schedule is active.
Missed occurrences are skipped without a catch-up burst. Interval schedules retain their timing anchor. New occurrences may overlap requests still delivering from earlier runs. Pausing or deleting stops future occurrences, not requests already created.
Pause and resume
Section titled “Pause and resume”POST https://api.stormedo.com/schedules/{schedule_id}/pausePOST https://api.stormedo.com/schedules/{schedule_id}/resumeBoth actions return 200 OK with an updated schedule summary. A paused schedule has status: "paused" and next_run_at: null. Existing request and attempt history remains unchanged.
Delete a schedule
Section titled “Delete a schedule”DELETE https://api.stormedo.com/schedules/{schedule_id}Returns 204 No Content and cancels future occurrences. Requests created by previous occurrences remain available according to the workspace history retention period.
Schedule outcomes and errors
Section titled “Schedule outcomes and errors”last_run_outcome is enqueued, skipped_usage_limit, or null. Reaching the monthly request allowance skips that occurrence without pausing the schedule. Later occurrences can resume when capacity becomes available.
| Status | When it occurs |
|---|---|
401 |
The project API key is missing or invalid. |
404 |
The schedule does not exist in the API key project. |
409 |
A schedule idempotency key was reused with a different definition. |
413 |
The complete structured schedule request exceeds 512 KiB. |
422 |
The name, timing, request definition, destination headers, or key is invalid. |
429 |
Creating a schedule would exceed the workspace schedule allowance. |
500, 502, or 503 |
The operation outcome may be unknown. Recover creation with the original key and definition; inspect schedule state before repeating other operations. |