Platform
Hosting & deploysPush to a branch, get a live linkDatabaseReal Postgres, one per appSign-inEmail and Google, users includedFile storageUploads, photos and documentsAI gatewayEvery model, with a hard spend cap
Resources
DocsGuides written for people who are newFor AI agentsClaude Code, Cursor, MCP, JSON CLICompareCamplax beside the stack it replacesPricingFrom $25/month plus prepaid creditsSupportA person answers, not a queue botPoliciesTerms, privacy and how we handle data Get started
Open in ChatGPT Open in Claude Last updated 2026-10-19

Uptime monitoring

Every live project gets a Production monitor — plus custom HTTP checks, heartbeats, incidents confirmed from three regions, alerts, and a public status page people can subscribe to.

You do not set up monitoring on Camplax — it is already running. The moment a project goes live, a monitor named Production starts checking https://<slug>.camplax.app/ every 15 minutes. Custom monitors add paths and custom domains on top, up to 5 monitors per project.

What a monitor checks

Each monitor is an HTTPS request against one of your project's hosts — the <slug>.camplax.app URL or any custom domain with an active certificate:

SettingDefaultLimits
name—1–80 characters
path/a path on the monitor's host
methodGETGET or HEAD
expectedStatusMin – expectedStatusMax200–299any range inside 100–599
assertionnonecontains or not_contains text (≤200 chars); needs GET
timeoutMs100001,000–10,000 ms
followRedirectsonup to 3 redirects, and only to your own project hosts
enabledonpause a monitor instead of deleting it

Two deliberate constraints: checks only ever target your hosts (a monitor cannot be aimed at an arbitrary URL), and a custom domain is re-checked before every check — it must still be active on your project and must not resolve to a private address, or the check fails with a domain error instead of following your DNS somewhere else. Response bodies are read only up to 256 KB, just enough to run the assertion.

The automatic Production monitor is special: it cannot be deleted (pause it instead) and it cannot be repointed — it must keep watching the project's production URL. New monitors get a 5-minute warm-up so deploy noise does not open incidents.

Heartbeats — for jobs that run on their own

An HTTP check asks "does the app answer?". A heartbeat asks the opposite: "did my nightly backup, queue worker or sync job run?". Your job pings Camplax when it finishes, and silence is the outage — no ping within the period plus a grace window opens an incident, with the same alerts and status page as any other monitor.

Add one under Uptime → Monitors → Add heartbeat (or POST /v1/projects/:slug/uptime/heartbeats) with a key, how often the job runs (periodSeconds, 1 minute to 7 days) and a grace (graceSeconds, default 5 minutes). Then ping it from the app with the project token Camplax already put in its environment — there is no ping URL secret to copy:

await fetch("https://camplax.dev/v1/heartbeats/nightly-backup", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.CAMPLAX_PROJECT_TOKEN}` },
});

Post to /v1/heartbeats/<key>/fail (optionally with { "message": "…" }) when the job ran and failed — that opens the incident at once instead of waiting out the silence. The next successful ping resolves it. Heartbeats count toward the 5 monitors per project, and pings less than 10 seconds apart are accepted but not recorded (a job that pings per request costs nothing extra). The token's heartbeat:send scope is added to every app token on its next deploy — an app deployed before heartbeats existed gets 403 until you redeploy it once.

A preview environment's token pings too, inside its own namespace: asking for nightly-backup resolves the monitor named preview-nightly-backup. The same code works on a preview whose owner added a preview- heartbeat — and a preview can never keep a production monitor green, since nothing it sends reaches a key outside preview-.

Incidents and alerts

A failed check does not immediately page you. Twenty seconds later the same check runs again from three regions — eastern North America, western Europe and Asia-Pacific — and an incident opens only when at least two of the three fail. One colo's bad minute is not an outage. Recovery works the same way: two of three must pass before the incident resolves, and a 1–1 split (a region did not answer) confirms nothing either way. The incident records where it failed ("Failed from 3 of 3 locations").

Honest limits: every region reaches your app through Cloudflare's edge and the cell's tunnel, so this separates "one location had a problem" from "the app is down" — it is not an independent ISP-level view. If fewer than two regions answer, the check also runs where the confirmation was scheduled, so an outage is never missed for want of probes. The regional re-checks only happen after a check has already failed, so they cost nothing on a healthy app.

When an incident opens or resolves, emails go to the project's alert recipients — any owner or member seat with a verified email. Each person gets each alert at most once: a send that was refused is retried, but one that timed out is not, since it may already have arrived. The project owner is added by default; edit the list under Uptime → Alerts. The same list receives error alerts.

SSL expiry warnings ride the same rail: once a day the platform reads the certificate on each active custom domain and emails when expiry is 30, 14, 7 or 1 day out.

To post outages to a team channel as well, add a Slack, Discord or webhook destination under Settings → Alerts — each channel picks which events it hears (down, recovered, deploy failed, new error, analytics alert, log pattern). A webhook channel receives JSON signed with Camplax's own key, so there is no secret to store — check it with Camplax's public key. Anyone who would rather not get the email can switch it off for themselves under Account → Notifications; everyone else keeps receiving it.

The status page

Each project can publish a status page without any code. Enable it under Uptime → Status page, give it a title, and pick which monitors are public:

  • Page: https://camplax.dev/status/<slug> — status banner, per-monitor 90-day uptime, recent incidents.
  • JSON: https://camplax.dev/v1/status/<slug> — the same data for a status badge in your own UI.
  • Embeds: a badge or card for your own site:
<script src="https://camplax.dev/status.js" data-project="<slug>" data-layout="badge" async></script>

The public page only ever shows what you selected — monitor names, up/down status and incident summaries like "Service disruption", never internal error text.

Status page subscribers

A status page is how your users hear about an outage without watching it. Every enabled page has three ways in:

  • Email. A form at the bottom of the page, behind a Turnstile check. The address gets a confirmation email and nothing else until someone clicks Confirm on the page it links to (double opt-in; the button is a POST, so mail scanners that open every link cannot subscribe anybody). Because that mail goes to an address nobody has verified, it carries only Camplax's fixed wording and the page's address — never the page title — and it is rationed: at most two per unconfirmed address, ten minutes apart, and at most three a day to one address across every Camplax status page. Each later email has an unsubscribe link and a one-click List-Unsubscribe header; every mail is logged in the project's email sends, counts toward the plan's monthly sent mail, goes out at the project's send rate (10 a second), and skips addresses that bounced or complained. A page holds up to 1,000 confirmed subscribers and 100 unconfirmed ones at a time; unconfirmed addresses are forgotten after 7 days. Variants of one mailbox (ann+news@, and Gmail's dotted and googlemail.com forms) count as one subscriber and share that daily budget. The form gives the same answer whatever happens to the address — known, new, or turned away because the page is at its limits — and the console shows how many sign-ups were turned away. Confirmation emails go out under a Camplax-owned sending reputation, never your project's, so a stranger typing bad addresses cannot hurt your own mail.
  • RSS and Atom. https://camplax.dev/status/<slug>/feed.rss and …/feed.atom — the last 20 posts, linked from the page.
  • Webhooks. Project owners add up to 10 URLs under Uptime → Status page (POST /v1/projects/:slug/status-page/subscribers/webhooks). Anyone can subscribe by email; only an owner can make Camplax post somewhere. Each post is JSON — { id, type: "status.incident_opened", projectId, page, title, body, createdAt } — signed with Camplax's own key under the status purpose, with a Camplax-Delivery id to dedupe on. Verify it like any Camplax webhook with verifyCamplaxWebhook(req, raw, { purpose: "status" }); there is no secret to store.

Subscribers hear about incidents on monitors the page shows (opened and resolved, in the same plain words as the page) and about scheduled maintenance. Announce a window under Uptime → Status page → Schedule maintenance (POST /v1/projects/:slug/status-page/maintenance with title, body, startsAt, endsAt, up to 7 days long and 90 days ahead): subscribers get the announcement (or not — notify: false), the page shows it as upcoming, then "Scheduled maintenance in progress" while it runs, and posts again when it starts and ends. End it early or cancel it with PATCH …/maintenance/:id { "action": "complete" | "cancel" }.

Sending is cheap by design: one job sends 50 subscribers and moves a cursor, so a thousand subscribers are twenty small jobs. A subscriber whose mail was refused is retried on its own (1, 4, 16, 64 minutes) and given up after five tries — but one whose send timed out is not sent again, because the mail may already have arrived, so nobody gets the same post twice; a webhook that fails ten times in a row is skipped until an owner re-adds it. Turning the page off stops all sending, and unsubscribe links keep working.

The API surface

All of the above is also scriptable — every console route takes a session, and none is reachable with a project API key. The one exception is the heartbeat ping, which is only reachable with the app token.

EndpointWhat it does
GET /v1/projects/:slug/uptimeMonitors, recent incidents, domains, recipients, status-page config
POST /v1/projects/:slug/uptime/monitorsCreate a monitor (409 monitor_limit past 5)
PATCH /v1/projects/:slug/uptime/monitors/:idEdit a monitor
DELETE /v1/projects/:slug/uptime/monitors/:idDelete (the automatic monitor refuses)
POST /v1/projects/:slug/uptime/monitors/:id/testRun one check right now
GET /v1/projects/:slug/uptime/monitors/:id/series?range=24h|7d|30d|90dLatency/uptime series for charts
GET /v1/projects/:slug/uptime/incidentsIncident history (resolved entries age out after a year)
PATCH /v1/projects/:slug/uptime/recipientsChoose who gets alert email (owner only)
PATCH /v1/projects/:slug/uptime/status-pageEnable, title and select public monitors (owner only)
POST /v1/projects/:slug/uptime/heartbeatsCreate a heartbeat monitor { name, key, periodSeconds, graceSeconds? }
PATCH /v1/projects/:slug/uptime/heartbeats/:idChange its name, period, grace or pause it
POST /v1/heartbeats/:key · /:key/failThe app's ping — CAMPLAX_PROJECT_TOKEN, scope heartbeat:send
GET /v1/projects/:slug/status-page/subscribersSubscribers, counts and feed URLs
POST /v1/projects/:slug/status-page/subscribers/webhooksAdd a webhook subscriber (owner only)
DELETE /v1/projects/:slug/status-page/subscribers/:idRemove a subscriber (owner only)
GET · POST /v1/projects/:slug/status-page/maintenanceList or schedule maintenance
PATCH /v1/projects/:slug/status-page/maintenance/:id{ action: "complete" | "cancel" }
GET /v1/projects/:slug/status-page/postsWhat was sent to subscribers
GET /v1/status/:slugPublic JSON for the status page — no sign-in (includes maintenance and subscribe links)
POST /status/:slug/subscribe · GET /status/:slug/feed.rss · /feed.atomPublic subscribe form and feeds
Camplax

Hosting, database, sign-in and storage in one project. One login, one bill.

Platform
More
Legal
Company
© 2026 Camplax From $25 / month · credits stop at zero