API Reference
Everything you need to schedule webhook calls with CronCoco.
Overview
CronCoco is a REST API for scheduling recurring HTTP webhook calls. You define a cron expression and a target URL — CronCoco fires a POST request to that URL on your schedule.
There is no dashboard. Everything is done via API.
Base URL
Authentication
Most endpoints require a bearer token.
Your API key is returned once at registration. It cannot be retrieved again — use key rotation if you lose it.
Errors
All errors return standard HTTP status codes with a JSON body:
Register
Submit your email to receive a verification token, then exchange it for your API key. The token is single-use and expires in 15 minutes.
Step 1 — Request a verification token
/register
Step 2 — Exchange token for API key
/verify-email
Key rotation
If you lose your API key, request a rotation token by email. The token is single-use and expires in 15 minutes.
Step 1 — Request a rotation token
/request-key-rotation
Step 2 — Exchange token for new key
/rotate-key
Delete
Request a deletion token by email, then confirm with the token to permanently delete your account. All jobs and execution history are removed immediately.
Step 1 — Request a deletion token
/account/delete-request
Step 2 — Confirm deletion
/account
Account settings
Read and update account-level settings. Currently supports toggling failure email notifications.
Get account
/account
{
"email": "you@example.com",
"plan": "pro",
"failure_email_enabled": true
}
Update account
/account
| Field | Type | Description |
|---|---|---|
| failure_email_enabled | boolean | Set to false to stop receiving failure emails for all jobs. Defaults to true. |
Failure emails go to the address used at registration. For per-job webhook alerts, set failure_webhook_url on the job itself.
Failure webhook payload
When a job fails and failure_webhook_url is set, CronCoco POSTs this JSON body to that URL:
{
"job_id": 1,
"job_name": "hourly-sync",
"status": "failure",
"response_code": 503,
"error": "HTTP 503",
"failed_at": "2026-05-11T14:00:00+00:00"
}
Create job
/jobs
Create a new scheduled job. CronCoco will POST to your webhook_url on the schedule defined by cron_expression. Minimum intervals depend on your plan.
Request body
| Field | Type | Description |
|---|---|---|
| name required | string | A label for the job. Max 100 characters. |
| cron_expression required | string | Standard 5-field cron expression. E.g. 0 * * * * (every hour). |
| webhook_url required | string | The URL to POST to. Must be publicly reachable (https recommended). Max 2048 chars. |
| headers | object | Optional HTTP headers to include. Max 20 headers, keys ≤100 chars, values ≤500 chars. |
| payload | object | Optional JSON body to POST. Max 10KB. |
| failure_webhook_url | string | Optional URL to POST a failure payload to when this job fails. Must be publicly reachable. Max 2048 chars. |
Cron expression reference
| Expression | Schedule |
|---|---|
| * * * * * | Every minute (Pro and Business) |
| 0 * * * * | Every hour |
| 0 9 * * * | Daily at 09:00 UTC |
| 0 9 * * 1 | Every Monday at 09:00 UTC |
| 0 0 1 * * | First day of every month |
| */15 * * * * | Every 15 minutes |
All times are UTC. Free jobs must run no more often than every 15 minutes. Pro and Business jobs can run every minute.
Example
{
"id": 1,
"name": "hourly-sync",
"cron_expression": "0 * * * *",
"webhook_url": "https://your-app.com/sync",
"headers": {"X-Secret": "mytoken"},
"payload": null,
"failure_webhook_url": null,
"enabled": true,
"last_run_at": null,
"next_run_at": "2026-05-09T14:00:00+00:00",
"created_at": "2026-05-09T13:22:10+00:00"
}
List jobs
/jobs
Returns all jobs for your account, ordered by creation date descending.
Update job
/jobs/{id}
Update any fields on a job. All fields are optional — only send what you want to change.
Request body
| Field | Type | Description |
|---|---|---|
| name | string | New job name. |
| cron_expression | string | New cron schedule. Recalculates next_run_at immediately. |
| webhook_url | string | New webhook target URL. |
| headers | object | Replace all headers. |
| payload | object | Replace the payload body. Max 10KB. |
| enabled | boolean | Pause (false) or resume (true) the job. |
| failure_webhook_url | string | Update the failure notification webhook URL for this job. Send "" to clear it. |
Example — pause a job
Delete job
/jobs/{id}
Permanently delete a job and stop all future executions. Returns 204 No Content on success.
List executions
/jobs/{id}/executions
Returns executions for a job within your plan's history window, paginated. Use this to check if your webhook is being called and whether it's succeeding.
| Plan | History window |
|---|---|
| Free | 7 days |
| Pro | 30 days |
| Business | 30 days |
Query parameters
| Parameter | Default | Description |
|---|---|---|
| limit | 100 | Number of results to return. Max 500. |
| offset | 0 | Number of results to skip. Use to page through history. |
When the response contains fewer results than your limit, you have reached the last page.
[
{
"triggered_at": "2026-05-09T13:00:00+00:00",
"completed_at": "2026-05-09T13:00:00+00:00",
"status": "success",
"response_code": 200,
"duration_ms": 312,
"error": null
},
{
"triggered_at": "2026-05-09T12:00:00+00:00",
"completed_at": "2026-05-09T12:00:01+00:00",
"status": "failure",
"response_code": 503,
"duration_ms": 1043,
"error": "HTTP 503"
}
]
Execution status values
| Status | Meaning |
|---|---|
| pending | Queued, not yet fired |
| success | Webhook responded with 2xx or 3xx |
| failure | Webhook responded 4xx/5xx, timed out, or URL was blocked |
| skipped | Execution was not attempted because a monthly or capacity limit was reached |
Billing
All billing is managed via API using your existing API key. Upgrades require visiting a Stripe Checkout page to enter payment — everything else (check plan, downgrade, cancel) is handled directly from the terminal.
| Plan | Price | Active jobs | Stored jobs | Executions/month | Min interval | Concurrency | Burst/min | Timeout | History |
|---|---|---|---|---|---|---|---|---|---|
| Free | $0 / forever | 5 | 10 | 5,000 | 15 min | 1 | 5 | 10s | 7 days |
| Pro | $12 / month | 50 | 100 | 250,000 | 1 min | 5 | 60 | 30s | 30 days |
| Business | $49 / month | 1,000 | 5,000 | 2,000,000 | 1 min | 25 | 250 | 60s | 30 days |
Active jobs are enabled schedules. Stored jobs include both enabled and disabled schedules. Executions are webhook attempts counted monthly. Concurrency is the number of webhook executions that can run at once for your account. Burst/min is the per-minute execution start cap.
Check plan
/billing
Returns your current plan, usage, and plan limits.
{
"plan": "free",
"stored_jobs_used": 4,
"stored_jobs_limit": 10,
"active_jobs_used": 4,
"active_jobs_limit": 5,
"executions_used": 120,
"executions_limit": 5000,
"usage_period_start": "2026-05-01T00:00:00+00:00",
"min_interval_seconds": 900,
"concurrency_limit": 1,
"burst_per_minute": 5,
"burst_bucket": 5,
"timeout_seconds": 10,
"history_days": 7,
"has_billing": false
}
Upgrade
/billing/upgrade
Returns a Stripe Checkout URL. Open it in your browser to enter payment details. Use the same email address you registered with — this links the payment to your API key.
Request body
| Field | Type | Description |
|---|---|---|
| plan required | string | pro or business |
{
"checkout_url": "https://checkout.stripe.com/..."
}
Downgrade
/billing/downgrade
Downgrades your plan. No browser redirect needed — handled server-side. Downgrades to Free take effect at the end of your current billing period; Business → Pro takes effect immediately with a prorated credit. Active jobs beyond the new plan's limit are paused automatically, keeping the most recently created ones active.
Request body
| Field | Type | Description |
|---|---|---|
| plan required | string | free or pro |
{
"plan": "free",
"effective": "2026-06-10T00:00:00+00:00",
"note": "Change takes effect at end of billing period"
}
Cancel
/billing/subscription
Cancels your subscription at the end of the current billing period. You keep full access until then. After the period ends, your account reverts to the Free plan and active jobs beyond the Free limit are paused automatically.
{
"cancelled": true,
"effective": "2026-06-10T00:00:00+00:00",
"note": "You keep access until the end of your billing period"
}
Payment portal
/billing/portal
Returns a Stripe Billing Portal URL. Open it in your browser to update your payment method, download invoices, or view payment history. Requires an active or past subscription.
{
"url": "https://billing.stripe.com/..."
}
Email hello@croncoco.io — we respond within 24 hours.