puter.events.updateSchedule()Changes a schedule created with puter.events.onSchedule(), or a notification stored to send later with puter.notifications.notify(). The schedule keeps its scheduleId, its kind and its handler, so ids you saved elsewhere stay valid.
An app can change only the schedules it created. An account session can change any of the user's schedules. A scoped access token can't change any. On a website with nobody signed in, the call asks the user to sign in first, as other Puter.js calls do.
puter.events.updateSchedule(scheduleId, changes)
scheduleId (String) (required)
The scheduleId from onSchedule(), notify() or listSchedules().
changes (Object) (required)
For a schedule from onSchedule(), pass new timing, a new context, or both:
at, every, cron, tz, startAt, expiresAt and maxRuns replaces the whole timing, so pass exactly one of at, every or cron, together with every other timing option you want to keep. They take the same values as in onSchedule(). A recurring schedule can switch between every and cron, and an at schedule stays a one-time schedule. Without timing options, the timing stays as it is.context (Object | null): Replaces the whole context. Pass null to clear it. Up to 4 KB serialized, as in onSchedule().For a stored notification, pass a new sendAt, new content, or both:
sendAt (Number | String | Date): The new time to send it, as in notify(). A time within 5 seconds, or in the past, sends it now, with the retries of any stored notification.title, text, icon, target, data, group, channel, sensitive, priority, ttl: Replace the stored values, with the same rules as notify(). Fields you leave out keep their values. Pass null to clear an optional field. The title can't be cleared.The handler and the recipient can't change. Passing handler, handlerName, handlerScope, handlerHash, handlerSource or to rejects with invalid_request. To run different code, remove the schedule and create a new one.
A Promise that resolves to the updated schedule, in the shape getSchedule() returns. Its nextRunAt is the next run under the new timing. It describes the context by its key names and a hash, and never includes a stored notification's content. A stored notification whose new sendAt is due now is sent during the call, so the schedule can come back already ended.
The promise rejects with { message, code }:
code |
Meaning |
|---|---|
events_schedule_not_found |
No such schedule, it isn't this caller's, or it already ended. Also for an empty scheduleId. |
events_schedule_sending |
The stored notification has started to go out. If the attempt fails and it returns to active, it can be changed while it waits to retry. |
invalid_request |
changes isn't an object, it has a field that can't change, or the new timing would turn a one-time schedule into a recurring one or the other way round. |
events_schedule_invalid |
A timing option or sendAt is malformed, or too far ahead. |
events_schedule_never_fires |
The new timing would never run. |
events_schedule_too_frequent |
The new timing would run more often than the user's plan allows. |
events_schedule_limit |
The new timing goes over the number of schedules the user's plan allows. |
events_schedule_budget |
The new timing goes over the runs per hour the user's plan allows. |
events_schedule_busy |
Puter is checking too many cron expressions at once. Try again in a moment. |
events_context_invalid |
context can't be serialized as JSON. |
events_context_too_large |
The serialized context is over 4 KB. |
bad_request |
A notification field is over its limit or has the wrong type. The message names the field. |
notification_value_too_large, events_value_too_large |
The stored notification would be over 16 KB as JSON. |
too_many_requests |
Over the rate limit, which is shared with onSchedule(). See Rate Limits and Quotas. |
auth_canceled |
Nobody was signed in, and the user closed the sign-in without finishing it. |
events_disabled |
Changing schedules isn't available on this server. |
events_failed |
Other changes to the schedule kept getting in the way, or the server sent a response the SDK couldn't read. |
getSchedule() to check.Move a reminder to a later time
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<script>
(async () => {
// (1) Store a reminder for an hour from now
const reminder = await puter.notifications.notify({
title: 'Review your notes',
sendAt: Date.now() + 60 * 60 * 1000,
});
if (typeof reminder !== 'object' || !reminder) return; // due now, so it was sent at once
puter.print(`goes out ${new Date(reminder.sendAt).toLocaleTimeString()}<br>`);
// (2) Move it an hour later and change what it says, keeping its id
const updated = await puter.events.updateSchedule(reminder.scheduleId, {
sendAt: Date.now() + 2 * 60 * 60 * 1000,
title: 'Review your meeting notes',
});
puter.print(`now goes out ${new Date(updated.nextRunAt).toLocaleTimeString()}<br>`);
// (3) Cleanup
await puter.notifications.cancel(reminder.scheduleId);
puter.print('cancelled<br>');
})();
</script>
</body>
</html>
Move a weekday schedule to another time
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<script>
(async () => {
if (!await puter.perms.request('backgroundEvents')) {
puter.print('background events were not allowed<br>');
return;
}
// (1) Weekdays at 09:00 in this browser's time zone
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
const schedule = await puter.events.onSchedule({
cron: '0 9 * * 1-5',
tz,
handler: async ({ user }) => {
await user.notifications.notify({ title: 'Check your tasks' });
},
});
puter.print(`next run: ${new Date(schedule.nextRunAt).toLocaleString()}<br>`);
// (2) Move it to 10:00, keeping the same id and handler
const updated = await puter.events.updateSchedule(schedule.scheduleId, {
cron: '0 10 * * 1-5',
tz,
});
puter.print(`next run: ${new Date(updated.nextRunAt).toLocaleString()}<br>`);
// (3) Cleanup: end the schedule, then remove the handler it created
await schedule.off();
await puter.events.handlers.remove(schedule.handlerName, { scope: 'user' });
puter.print('removed<br>');
})();
</script>
</body>
</html>