Forget cron jobs.
Schedule anything reliably.
Webhooks that fire on time — from 30 seconds to 6 months out. Human approvals via Teams, Slack, or email. Multi-step workflows that just work. All with automatic retries and full audit trails.
Free tier includes 100 actions/month. No credit card required.
curl -X POST https://api.callmelater.io/v1/actions \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Trial expiration",
"schedule": { "wait": "14d" },
"request": {
"url": "https://your-app.com/webhooks/trial-expired",
"method": "POST",
"body": { "user_id": 42 }
}
}'
<?php
$response = Http::withToken('sk_live_...')
->post('https://api.callmelater.io/v1/actions', [
'name' => 'Trial expiration',
'schedule' => ['wait' => '14d'],
'request' => [
'url' => 'https://your-app.com/webhooks/trial-expired',
'method' => 'POST',
'body' => ['user_id' => 42],
],
]);
import requests
response = requests.post(
"https://api.callmelater.io/v1/actions",
headers={"Authorization": "Bearer sk_live_..."},
json={
"name": "Trial expiration",
"schedule": {"wait": "14d"},
"request": {
"url": "https://your-app.com/webhooks/trial-expired",
"body": {"user_id": 42},
},
},
)
const action = await fetch('https://api.callmelater.io/v1/actions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Trial expiration',
schedule: { wait: '14d' },
request: {
url: 'https://your-app.com/webhooks/trial-expired',
body: { user_id: 42 },
},
}),
});
const axios = require('axios');
const { data } = await axios.post(
'https://api.callmelater.io/v1/actions',
{
name: 'Trial expiration',
schedule: { wait: '14d' },
request: {
url: 'https://your-app.com/webhooks/trial-expired',
body: { user_id: 42 },
},
},
{ headers: { Authorization: 'Bearer sk_live_...' } }
);
payload := map[string]interface{}{
"name": "Trial expiration",
"schedule": map[string]string{"wait": "14d"},
"request": map[string]interface{}{
"url": "https://your-app.com/webhooks/trial-expired",
"body": map[string]interface{}{"user_id": 42},
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://api.callmelater.io/v1/actions", bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer sk_live_...")
req.Header.Set("Content-Type", "application/json")
response = HTTParty.post(
'https://api.callmelater.io/v1/actions',
headers: { 'Authorization' => 'Bearer sk_live_...' },
body: {
name: 'Trial expiration',
schedule: { wait: '14d' },
request: {
url: 'https://your-app.com/webhooks/trial-expired',
body: { user_id: 42 }
}
}.to_json
)
"Do this later" is where things break
You need to call an API in three days, clean up data after a trial ends, or remind someone to approve a deployment. So you set up a queue, write retry logic, add monitoring — and then: the worker crashes, a job fails silently, the reminder is ignored. No one knows what happened. There's a simpler alternative.
Built for reliability
Automatic Retries
Exponential backoff when things fail. Configure attempts and timing to match your needs.
Durable Storage
Actions survive restarts and crashes. Your scheduled work is never lost.
Full Audit Trail
See every attempt, response code, and timing. Debug with confidence.
Secure by Default
HMAC signatures, SSRF protection, and encrypted storage. Ship with confidence.
Teams & Slack
Send approval requests directly to your channels. Interactive buttons for instant responses.
Workflows
Chain webhooks, approvals, and wait steps into powerful multi-step sequences.
Seconds to Months
Schedule from 30 seconds to 6 months out, in any timezone. Short delays fire with second-level precision.
Manual Retry
Failed actions can be retried with one click. No data loss, no re-creation needed.
Action Templates
Create reusable configurations with unique URLs. Trigger from CI/CD without API keys.
Trigger any API at the right time
Schedule any HTTP request to fire at a specific time — from seconds to months out. Perfect for trial expirations, follow-up sequences, cleanup jobs, or any delayed API call.
- Seconds-level precision for short delays
- Automatic retries with exponential backoff
- Custom headers and JSON body
- HMAC signature verification
// Fire in 30 seconds
{ "schedule": { "wait": "30s" }, "request": { ... } }
// Or in 14 days — same API
{
"name": "Expire trial subscription",
"schedule": { "wait": "14d" },
"request": {
"url": "https://api.example.com/subscriptions/expire",
"method": "POST",
"body": { "user_id": 12345 }
},
"max_attempts": 5
}
Get sign-off before acting
Sometimes a human needs to approve first. Send approval requests via Teams, Slack, email, or SMS with one-click Yes/No/Snooze buttons. No account needed to respond.
- Teams and Slack integration
- Email and SMS delivery
- One-click response buttons
- Snooze and escalation support
{
"mode": "approval",
"name": "Approve production deploy",
"schedule": { "wait": "5m" },
"gate": {
"message": "Ready to deploy v2.1 to production?",
"recipients": ["channel:slack-ops-123", "ops@example.com"],
"channels": ["slack", "email"]
}
}
Common use cases
A simple alternative to cron jobs, self-managed queues, and manual reminders
Trial Expirations
Automatically trigger downgrade logic when free trials end.
Async Callbacks
A lightweight alternative to async queues. Fire a webhook in 30 seconds or 30 days — without managing workers or retry logic.
Deployment Approvals
Get human sign-off before releases go live.
Deferred Processing
An alternative to SQS, RabbitMQ, or background workers for delayed API calls.
Invoice Reminders
Ping customers about upcoming or overdue payments.
Scheduled Cleanup
Delete temporary data after retention periods — a reliable alternative to cron jobs you have to babysit.
Integrate in minutes
Official SDKs and integrations — or use the REST API from any language
Stop babysitting your scheduled jobs
One API call. We handle the rest. Start free, scale as you grow.