Skip to content

Documentation

Update schedule

PATCH /api/v1/schedules/{schedule}

Change supplied fields. The next run time is recalculated only when timing, zone, allowed hours or activation changes. A retry-policy or name change does not move a due run.

Access

A Bearer API key for this workspace with write permission is required. The server also checks the owner’s permission for this resource and action. An inaccessible object is not disclosed.

Parameters

Path parameters: schedule. Use IDs from your own installation.

Example request parameters or JSON body:

{
  "name": "Twice daily",
  "kind": "cron",
  "preset": {
    "cron": "0 2,12 * * *"
  },
  "timezone": "Europe/Moscow"
}

script_id is immutable. Create another schedule for a different scenario.

Response 200

The example is shortened; actual responses may include more fields. Sample IDs are placeholders.

{
  "id": 5,
  "name": "Nightly collection",
  "cron": "0 0 * * *",
  "timezone": "Europe/Moscow",
  "is_active": true
}

Send the request

Set BASE to your installation URL without a trailing slash and API_KEY to a secret stored on your server. Client setup and browser JavaScript.

curl

curl --fail-with-body -X PATCH "$BASE/api/v1/schedules/5" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "name": "Twice daily",
  "kind": "cron",
  "preset": {
    "cron": "0 2,12 * * *"
  },
  "timezone": "Europe/Moscow"
}
JSON

Node.js · server

// Node.js server example. Save as request.mjs.
const response = await fetch(process.env.BASE + "/api/v1/schedules/5", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.API_KEY}`,
    Accept: "application/json",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({"name":"Twice daily","kind":"cron","preset":{"cron":"0 2,12 * * *"},"timezone":"Europe/Moscow"}),
  signal: AbortSignal.timeout(120000)
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
console.log(await response.json());

Python

import json
import os
import urllib.request
import urllib.error

body = '{"name":"Twice daily","kind":"cron","preset":{"cron":"0 2,12 * * *"},"timezone":"Europe/Moscow"}'.encode("utf-8")
request = urllib.request.Request(
    os.environ["BASE"] + "/api/v1/schedules/5",
    method="PATCH",
    headers={"Authorization": "Bearer " + os.environ["API_KEY"],
             "Accept": "application/json", "Content-Type": "application/json"},
    data=body,
)
try:
    with urllib.request.urlopen(request, timeout=120) as response:
        print(json.load(response))
except urllib.error.HTTPError as error:
    print(error.code, error.read().decode("utf-8", errors="replace"))
    raise

PHP · external client

<?php
$handle = curl_init(getenv("BASE") . "/api/v1/schedules/5");
curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("API_KEY"),
        "Accept: application/json",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => <<<'JSON'
{"name":"Twice daily","kind":"cron","preset":{"cron":"0 2,12 * * *"},"timezone":"Europe/Moscow"}
JSON,
]);
$content = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
if ($content === false) {
    throw new RuntimeException(curl_error($handle));
}
curl_close($handle);
if ($status < 200 || $status >= 300) {
    throw new RuntimeException("HTTP $status: $content");
}
print_r(json_decode($content, true, 512, JSON_THROW_ON_ERROR));

Go

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
    "strings"
)

func main() {
    body := strings.NewReader(`{"name":"Twice daily","kind":"cron","preset":{"cron":"0 2,12 * * *"},"timezone":"Europe/Moscow"}`)
    request, err := http.NewRequest("PATCH", os.Getenv("BASE") + "/api/v1/schedules/5", body)
    if err != nil { panic(err) }
    request.Header.Set("Authorization", "Bearer " + os.Getenv("API_KEY"))
    request.Header.Set("Accept", "application/json")
    request.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 120 * time.Second}
    response, err := client.Do(request)
    if err != nil { panic(err) }
    defer response.Body.Close()
    content, err := io.ReadAll(response.Body)
    if err != nil { panic(err) }
    if response.StatusCode < 200 || response.StatusCode >= 300 {
        panic(fmt.Sprintf("HTTP %d: %s", response.StatusCode, content))
    }
    fmt.Println(string(content))
}

If the request fails

401: check the key and its expiry. 403: check permissions, read/write scope, and 2FA. 404: check the ID and workspace. 422: check fields and resource state. 429: respect Retry-After. Errors and retries.

Retry a failure

To retry transient failures, supply retry_policy: "transient", retry_limit: 2, retry_delay_seconds: 300: two additional attempts with a five-minute delay. never disables retries; inherit preserves site rules. Code errors and explicit access restrictions are not retried. timezone_city is a display label; the required IANA timezone controls timing. Detailed rules.