---
title: "Get Blocklist Schedule"
method: GET
path: "/blocklist/schedule"
tags: ["blocklist"]
---

# Get Blocklist Schedule

`GET /blocklist/schedule`

## Request

- Base URL: `https://api.ismalicious.com`
- URL: `https://api.ismalicious.com/blocklist/schedule`
- Auth: none required

When the blocklists are regenerated: the configured interval, the last
run of the generation job, the newest list's `lastUpdated`, and when the
next run is expected. The job runs on an interval placed relative to its
last run, not at a fixed hour of the day.

`expectedNextRunAt` is `startedAt + intervalHours` after a `success`, and
`intervalHours` after the end of a `failed` or `timeout` run. It is
`null` — the next run cannot be dated from outside the worker — while a run
is `running`, after an `interrupted` one (the worker retries it shortly
after its next start), with no run history, or with the scheduler off.
`overdue` is `true` once now is more than an hour past
`expectedNextRunAt`.

**No authentication required.** Not metered.

**Per-IP ceiling.** 120 requests a minute per IP (per /64 for IPv6),
shared by `/stats`, `/blocklist/stats`, `/blocklist/schedule`,
`/analytics`, `/cve/stats/epss`, `/cve/stats/timeseries` and `/license`,
with or without a key. Over it, `429` with `Retry-After`. Computed on each
call.

## Response `200`

The regeneration schedule

- BlocklistSchedule: When the blocklists are regenerated (`api/blocklist.rs::schedule_body`).
  - `expectedNextRunAt` string, nullable: When the next run is expected; `null` when it cannot be known (the scheduler is off, a run is in flight or was cut short, or the last run was started by hand and the worker has not published its next tick)
  - `expectedNextRunBasis` string, nullable: Where `expectedNextRunAt` comes from: `armedTick` (the tick the worker's scheduler armed) or `lastScheduledRun` (computed from the last run the scheduler started); `null` with no date
  - `intervalHours` integer, required: Hours between two runs of the generation job (`BLOCKLIST_SCHEDULER_INTERVAL_HOURS`)
  - `lastRegeneratedAt` string, nullable: The newest `lastUpdated` among the lists; `null` when none was ever generated
  - `lastRun` BlocklistLastRun: The last run of the blocklist generation job (`jobs:last-run:generate-blocklists`).
    - `completedAt` string, nullable: `null` while the run is in flight
    - `initiator` string, nullable: Who started it: `interval-scheduler` (the worker's ticker), `blocklist-api` (`POST /blocklist`), …; `null` when not recorded
    - `startedAt` string, required
    - `status` string, required: `running` | `success` | `failed` | `timeout` | `interrupted`
  - `overdue` boolean, required: More than an hour past `expectedNextRunAt`
  - `schedulerEnabled` boolean, required: Whether the scheduler is on (`BLOCKLIST_SCHEDULER_ENABLED`)

## Other responses

- `429`: Over the per-IP ceiling of the public data routes (120 a minute; `Retry-After`, `X-RateLimit-Type: public`)
- `503`: The schedule could not be read: `{"error": "Blocklist schedule unavailable"}`

## Changes

- **2026-11-08** `7485d30743d2`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/changes/blocklist/schedule/get.md)

---

[API](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api.md) - [All operations](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ismalicious/apis/ismalicious-threat-intelligence-api/revisions/7485d30743d2?raw)
