Multi-region uptime
Watching a dozen sites one monitor at a time gets unwieldy fast. This endpoint registers a single scheduled monitor over a list of URLs: on each run it checks every address on the list and calls your webhook when any of them changes state, so a whole portfolio stays covered from one task instead of one monitor per site.
One monitor for a whole list
A classic setup means one uptime monitor per site, and once you are watching ten or twenty of them the bookkeeping becomes the job. Anyone managing a portfolio — an agency, a shop network, a developer with many side projects — wants the opposite: a single monitor that carries the whole list. web.uptime_multi exists so one scheduled task covers every URL you hand it, with a separate verdict per address rather than one blurred average.
What you send, what comes back
Register the monitor with the target URLs and a cadence. It runs asynchronously: you get a schedule_id immediately, and from then on every address on the list is checked on that schedule. When any URL's reachability changes, a webhook lands naming which one changed, so you don't have to reconcile a pile of separate monitors by hand.
Who actually needs this
Teams running their own status pages, agencies watching dozens of client sites, and SaaS platforms that bake uptime data into a customer dashboard all hit the same wall with one-monitor-per-site: the management overhead grows faster than the value. A single list-based monitor is the standard fix used by serious monitoring setups, and now it's available as a plain API call instead of a whole platform you have to adopt.
Built for pipelines, not dashboards
Because it registers asynchronously and delivers by webhook, this fits naturally into a cron-driven setup, a status-page generator, or an incident-response bot — no polling required. Register the monitor, let the change webhook land in your alerting system, and decide your own threshold for what counts as 'down' (any URL on the list failing, or a specific critical one, depending on how paranoid you want to be).
Pricing that matches the workload
At $0.002 per request you can register frequent monitors across many endpoints without doing mental math about your bill. Failed tasks — meaning our task failed to execute, not that your site was down — are retried automatically up to three times and are never charged, so a transient hiccup on our side never costs you a cent.
What you can do with it
Public status page backend
Feed a customer-facing status page from the change webhooks of one monitor that covers your whole list of endpoints.
Agency client watch
An agency managing 40 client sites registers one monitor that checks every domain every five minutes and routes webhook alerts into its ticketing system.
Onboarding new sites
As each new client site goes live, it is added to the existing monitor list, so coverage grows without standing up a fresh monitor every time.
Spotting the one that's down
When a whole portfolio is on one monitor, the change webhook names exactly which URL dropped, so you go straight to the affected site instead of checking them one by one.
FAQ
How many URLs can one monitor watch?
You add as many addresses as you need to the list; each is checked on the monitor's schedule and reported separately, so the list never collapses into a single average.
Is there a free tier for this uptime API?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How do I get the results?
Via a signed webhook to your endpoint when a URL's state changes (recommended for automation), or a signed link valid for 24 hours if you'd rather pull the latest result.
What counts as 'down' in the response?
You get the per-URL reachability and status codes; you decide your own threshold (any URL on the list unreachable, a specific critical one, or all of them) since that depends on your tolerance.
Can I check non-HTTP ports?
This endpoint focuses on HTTP/HTTPS reachability with configurable method and expected status; it is not a raw TCP/ping scanner.
Am I charged if a check fails?
Only if your target is genuinely unreachable — that's a valid result, not a failure. If our task itself fails to run, it retries automatically up to three times and is never billed.
Can I run this every minute for many domains?
Yes, that's exactly the intended use; at $0.002 per request it's built for high-frequency, multi-domain monitoring.
How is this different from a simple uptime cron script?
A hand-rolled script means one job and one list you maintain yourself; this registers a single monitor that checks your whole list on a schedule and delivers a change webhook, without you maintaining the infrastructure.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
One authenticated POST creates the task; the result comes back by webhook or a signed link. This capability is currently available through the API, not as an interactive Web tool.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/uptime-multi \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'const res = await fetch("https://api.kit.forhosting.com/web/uptime-multi", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"url": "https://example.com"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/uptime-multi",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"url": "https://example.com"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/uptime-multi", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"url":"https://example.com"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"url":"https://example.com"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/uptime-multi", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"url": "https://example.com"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.uptime_multi",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
timeout_sec | 30 |
max_crawl_pages | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |