Platform
Hosting & deploysPush to a branch, get a live linkDatabaseReal Postgres, one per appSign-inEmail and Google, users includedFile storageUploads, photos and documentsPaymentsCheckout and plans, same projectAI gatewayEvery model, with a hard spend cap
Solutions
Moving an app overFrom Lovable, Bolt, Replit or v0Your first real appNever shipped anything beforeSide project → businessWhen people start paying youPricing$20/month plus prepaid credits
Resources
DocsGuides written for people who are newFor AI agentsClaude Code, Cursor, MCP, JSON CLIChangelogWhat shipped, most recent firstComponentsPaste-ready UI for sign-in and moreSupportA person answers, not a queue botRefer a friendBoth of you get credits Start for $20
Open in ChatGPT Open in Claude Last updated 2026-09-24

Webhooks and deploy hooks

Signed outbound webhooks with retries and replay, and inbound hook URLs that trigger a deploy.

"Webhooks" covers two different things here, and they face opposite directions:

  • Project webhooks — Camplax calls your HTTPS endpoint when something happens in the project.
  • Deploy hooksyou call a secret Camplax URL to trigger a deploy.

Project webhooks (outbound)

Create an endpoint in the console, or with POST /v1/projects/<slug>/webhooks:

{ "url": "https://your-app.example.com/hooks/camplax", "events": ["order.paid", "deploy.*"], "maxAttempts": 6 }

The URL must be https, and private or loopback hosts are refused. The response includes the endpoint's secretwhsec_…, shown once. Store it; you need it to verify deliveries. An empty events list means every event; a trailing * subscribes to a family.

The events a project can emit:

EventFires when
user.created, user.deletedAn account is added or removed
order.created, order.paid, order.refundedA payment moves — see Payments
db.row.created, db.row.updated, db.row.deletedA watched table changes
deploy.succeeded, deploy.failedA deploy finishes either way
email.receivedMail lands in one of the project's mailbox inboxes
webhook.testThe test button or POST /test

email.received is opt-in only: catch-all endpoints (events: []) never receive it — a project endpoint must name email.received or email.* explicitly. Its payload is { inbox, thread, message } — the message carries from/fromName, to, subject, capped text/html (plus a truncated flag), attachments metadata, senderAuthenticated (aligned-DKIM verdict), rfcMessageId, and rawKey pointing at the stored .eml. An inbox's own webhookUrl rides this same pipeline and signing scheme, signed with the inbox's whsec_… secret — but that endpoint is managed through the mailbox routes only, and never appears in your project webhook list.

Verifying a delivery

Deliveries are POSTs with a JSON body { "event", "data", "sentAt" } and a signature header:

Camplax-Signature: t=1736…,v1=9c86…
User-Agent: Camplax-Webhooks/1.0

The scheme is Stripe's: v1 is the hex HMAC-SHA256 of <t>.<raw body> keyed with your endpoint secret. The timestamp is inside the signed string, so a captured delivery cannot be replayed with a fresh t — anything more than five minutes old fails anyway. While a secret is being rotated the header can carry several v1 digests; accepting any one that verifies keeps you up through the overlap.

const [t, v1] = header.split(",").map((p) => p.split("=")[1]);
const expected = hmacSha256Hex(secret, `${t}.${rawBody}`);
// compare expected to each v1, then check t is within 5 minutes

Retries, dead-letters, replay

Your endpoint gets 10 seconds per attempt; only the status code matters — the response body is never read. Failures back off roughly 10s, 40s, 3m, 11m, 43m with jitter (up to maxAttempts, 1–10, default 6), and a minute-by-minute sweep picks up whatever fell due. After the last attempt the delivery is dead-lettered, not lost — it sits in the delivery log with its error.

GET /v1/projects/<slug>/webhooks/:id/deliveries shows the last 100 attempts per endpoint. POST /deliveries/:id/replay resets a delivery to pending with a fresh attempt budget. POST /test fires a webhook.test event — the one endpoint call a webhooks:send API key may make; everything else here is console-session only. POST /:id/rotate-secret mints a new whsec_…, shown once.

Deploy hooks (inbound)

A deploy hook is a secret URL that queues a deploy — for CI systems, other hosts' build pipelines, or a button anywhere:

POST https://camplax.dev/v1/hooks/cxhook_…

Create one in the console or with POST /v1/projects/<slug>/deploys/hooks (GET lists, DELETE removes). The cxhook_… token is shown once and only its hash is stored. Each hook is bound to a branch: matching the project's default branch queues a production deploy, any other branch a preview. The answer is 202 with the deployId, or 409 while a production deploy is already running — the URL is the secret, so anyone holding it can deploy.

If the caller can sign, send X-Hub-Signature-256: sha256=<hex> — an HMAC-SHA256 of the raw body keyed with the hook token itself (X-Camplax-Signature works too). With no header the token alone is the check.

The platform's own inbound hooks

For completeness — these exist so external providers can reach Camplax, and are not yours to call: POST /v1/webhooks/github (GitHub events, signature-checked), POST /v1/webhooks/stripe and /stripe/connect (billing and connected-account events), and POST /v1/webhooks/resend (email delivery events — see Email). Each verifies its provider's signature; the signature is the auth.

© 2026 Camplax $20 / month · credits stop at zero
Ask about Camplax