Schedule a delayed callback
Some steps in a workflow can't run immediately — a trial reminder three days out, a cart abandonment nudge after two hours, a compliance check thirty days ahead. The Delayed Callback API takes a payload and a wait time, then fires the webhook exactly when you asked, so you never have to run your own scheduler for a single deferred event.
The gap most stacks paper over
Most applications are built to react to things happening right now: a form submit, a payment, a signup. The moment you need something to happen later — not on a fixed calendar date, but a relative delay from an event — teams either bolt on a cron job, stand up a message queue, or write a row in a database table and poll it every minute. All three work, and all three are overkill for firing one callback. dev.delay exists for that exact gap: you describe the wait, we hold the clock.
What happens after you call it
You send a delay duration and whatever payload you want echoed back, from a few seconds up to 30 days out. The task is accepted immediately and given a task_id so your calling code can move on without blocking. Internally the request sits until the requested moment arrives, and then it fires — as a signed webhook to the endpoint you configured, or as a signed link you can fetch, valid for 24 hours. Nothing runs early, and nothing charges you if the delivery attempt fails; we retry three times before surfacing a clear error.
Where this actually gets used
Onboarding sequences that need a nudge if a user hasn't finished setup by day two. Order systems that auto-cancel unpaid invoices after a grace window. Rate-limited retries where you deliberately want to wait before trying an external call again. Reminder emails, trial-expiry warnings, escalation timers for support tickets that go unanswered — anywhere the logic is 'do this, unless something else happens first, after N minutes.'
A short note on how delay queues evolved
Delayed message delivery is an old idea in messaging systems — most queue technologies added a 'visibility timeout' or 'scheduled delivery' feature only after developers kept building the same workaround: write now, wake up later. We took that primitive and exposed it as a single stateless endpoint, so you don't need to adopt an entire queueing platform just to delay one callback.
Fitting it into pipelines you already run
Because the call is async and returns a task_id right away, it composes cleanly with orchestration you already have: fire a delay task as one step in a larger chain, keep the task_id for auditing, and let the webhook resume the next step whenever it lands. No polling loop to maintain, no cron entry to remember to remove.
What you can do with it
Trial expiry reminders
Schedule a callback for 24 hours before a trial ends so your billing system can send the right warning without a background job checking dates all day.
Abandoned cart follow-up
Delay a callback by two hours after checkout starts; if the order webhook never fires first, the delayed callback triggers your recovery email.
Grace-period cancellations
Hold an unpaid invoice for 30 days, then let the delayed callback automatically trigger the cancellation flow if payment never posted.
Support ticket escalation
Set a delay when a ticket opens; if it's still unresolved when the callback lands, escalate it to a supervisor queue automatically.
FAQ
How long can a delay last?
Anywhere from about 60 seconds up to 30 days from the moment the request is accepted.
Is there a free tier for testing?
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 result back?
Either a signed webhook to your endpoint (recommended for production) or a signed link you retrieve manually, valid for 24 hours.
What happens if my webhook endpoint is down?
We retry delivery three times; if all three fail, you get a clear error and you are not charged for that task.
Can I cancel a scheduled callback once it's queued?
The task runs to completion once accepted; if your workflow might change its mind, keep the task_id and gate the downstream action on current state rather than relying on cancellation.
Is the payload stored anywhere long-term?
No. Data tied to the task is deleted after the retention window and is never used for training.
What does it cost?
0.002 dollars per request, billed only on successful delivery — failed tasks are never charged.
Can I use this instead of running my own cron jobs?
For one-off, event-relative delays, yes — it replaces the need to stand up a scheduler just to fire a single callback later.
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
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/delay \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/dev/delay", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/delay",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/delay", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/delay", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.delay",
"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.
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. |