Deploy a serverless API from your AI agent, without a Cloudflare account

Your agent writes a JavaScript, TypeScript or Hono API and chorus.host, web hosting for AI agents, runs it on Cloudflare's network at https://your-api.worker.chorus.host. You need a free chorus.host account, not a Cloudflare account.

Updated 1 October 2026 · For agents: /workers.md

NeedsA free chorus.host account. You read one 6-digit code from your email; it works in a headless agent session with no browser login.
Doesn't needA Cloudflare account, a browser OAuth step, or a credit card.
URL lifetimeUntil you delete it.

Can an agent deploy a serverless function with no account at all?

Checked 1 October 2026 against Cloudflare's claim-deployments docs and Netlify's AI quickstart.

chorus.host WorkersCloudflare npx wrangler@latest deploy --temporaryNetlify netlify deploy --allow-anonymousYour own Cloudflare account
Before the first deployA 6-digit email code, onceNothing (Wrangler 4.102.0 or later; you accept Cloudflare's terms and a proof-of-work runs automatically)NothingSign up, then wrangler login or an API token
URL lifetime with no human stepUntil deleted60 minutes unless a person claims it1 hour unless claimedUntil deleted
Server codeYes, JavaScript modules; the CLI bundles TypeScript, npm packages and HonoYesNo: Netlify says "sites or apps that use serverless functions or edge functions will require an account"Yes
StorageNone built inKV, D1 (1 database, 100 MB), Durable Objects, Queuesn/aAll of it
Static files on the same originNo; pair it with a site at <name>.chorus.hostStatic Assets, 1,000 files of up to 5 MiBStatic onlyYes
SecretsYes, and they stay set across redeploys and rollbacksNot in Cloudflare's list of supported resourcesn/aYes
Cron triggersNot yetNot in the listn/aYes

Vercel's agent skill also has a no-auth fallback that returns a preview URL and a claim URL; how long an unclaimed deploy lasts isn't documented. here.now hosts static files only and its docs say not to use it for backend code: see chorus.host vs here.now.

Deploy a plain JavaScript Worker

1. Write the Worker

Save this as worker.js. It answers GET /api/hello with JSON that any web page can fetch.

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname === "/api/hello") {
      return Response.json(
        { message: "hello from chorus.host", time: new Date().toISOString() },
        { headers: { "Access-Control-Allow-Origin": "*" } },
      );
    }
    return new Response("Not found", { status: 404 });
  },
};

2. Get an API key

Signing up and signing in are the same step. With the CLI:

curl -fsSL https://chorus.host/install.sh -o install-beacon.sh && sh install-beacon.sh
beacon login --email you@example.com
beacon login --email you@example.com --code 123456

The first login emails you a 6-digit code; the second saves your key to ~/.config/beacon/config.json. Without the CLI, see sign in from a headless agent.

3. Deploy

From the folder that holds worker.js:

beacon deploy --slug my-api --pretty

Or with two HTTP calls, one to create the Worker and one to upload the code:

curl -sS https://chorus.host/v1/workers \
  -H "Authorization: Bearer $BEACON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"my-api"}'
curl -sS https://chorus.host/v1/workers/my-api/deploy \
  -H "Authorization: Bearer $BEACON_API_KEY" \
  -F 'metadata={"entryPoint":"worker.js","compatibilityDate":"2026-09-01"}' \
  -F "file=@worker.js"

Then try it:

curl -sS https://my-api.worker.chorus.host/api/hello

Redeploy the same way after every change. The URL stays the same.

Deploy a Hono app

curl -fsSL https://chorus.host/install.sh -o install-beacon.sh && sh install-beacon.sh
beacon init my-api --template hono
cd my-api && npm install && npm i -D esbuild
beacon login --email you@example.com              # then: --code 123456
beacon deploy --pretty

The template's index.ts is a normal Hono app. To let a web page on another host call it, add CORS:

import { Hono } from 'hono'
import { cors } from 'hono/cors'

const app = new Hono()
app.use('/api/*', cors())
app.get('/api/hello', (c) => c.json({ message: 'Hello from chorus.host!' }))

export default app

beacon deploy bundles index.ts and its npm imports with esbuild and serves it at https://my-api.worker.chorus.host. Secrets are c.env.NAME. Claude Code, Codex and Cursor can run these commands as they are.

Sign in from a headless agent

No browser window, OAuth redirect or token page. The agent sends a code to the user's email, asks the user for it, and gets an API key:

curl -sS https://chorus.host/v1/auth/send-otp \
  -H "Content-Type: application/json" -d '{"email":"you@example.com"}'
# the user reads the 6-digit code from the email (valid for 10 minutes)
curl -sS https://chorus.host/v1/auth/verify-otp \
  -H "Content-Type: application/json" -d '{"email":"you@example.com","code":"123456"}'
# {"apiKey":"chk_...","account":{...}}

Keep the key in BEACON_API_KEY (the CLI also reads ~/.config/beacon/config.json). Five wrong tries cancel a code.

Secrets

printf '%s' "sk-your-token" | beacon secret set UPSTREAM_TOKEN - --slug my-api
curl -sS -X PUT https://chorus.host/v1/workers/my-api/secrets/UPSTREAM_TOKEN \
  -H "Authorization: Bearer $BEACON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value":"sk-your-token"}'

Your code reads it as env.UPSTREAM_TOKEN. Set secrets after the first deploy; they stay set across redeploys and rollbacks. Names use capital letters, digits and underscores. chorus.host stores only the names; the values are kept by Cloudflare and can't be read back.

Watch the logs

beacon logs my-api

This streams one JSON line per request, including anything your code passes to console.log. Over HTTP, GET /v1/workers/my-api/logs/tail returns a WebSocket URL to read the same stream from.

Give a static site an API

Option A: two hosts. Publish the site to my-app.chorus.host and the Worker to my-app-api.worker.chorus.host (a site and a Worker can't share a name). The page calls the API with fetch, and the Worker sends Access-Control-Allow-Origin, as the example in step 1 does:

const res = await fetch("https://my-app-api.worker.chorus.host/api/hello");
const data = await res.json();

beacon init my-app --template fullstack scaffolds both halves: a React frontend in frontend/ for my-app.chorus.host and a Hono API in backend/ for my-app-api.worker.chorus.host.

Option B: one origin, no CORS. For a small page, let the Worker serve the HTML too:

const page = `<!doctype html>
<title>Counter</title>
<p id="out">Loading…</p>
<script>
  fetch("/api/hello").then((r) => r.json()).then((d) => (out.textContent = d.message));
</script>`;

export default {
  async fetch(request) {
    const { pathname } = new URL(request.url);
    if (pathname.startsWith("/api/")) {
      return Response.json({ message: "hello from the same origin" });
    }
    return new Response(page, { headers: { "Content-Type": "text/html; charset=utf-8" } });
  },
};

Roll back

curl -sS -X POST https://chorus.host/v1/workers/my-api/rollback \
  -H "Authorization: Bearer $BEACON_API_KEY"

This puts the previous deploy back. To pick an older one, send {"deploymentId":"..."} with an id from GET /v1/workers/my-api/deployments.

Free tier and limits

Free, with no credit card. These are the limits today:

LimitValue
Code per deploy3 MB total, up to 100 files
LanguageJavaScript ES modules. For npm imports or TypeScript, the CLI bundles with esbuild or runs your npm run build.
Secret values5 KB each
New Workers10 per hour
Deploys and rollbacks20 per hour
Log sessions5 per hour
Scheduled (cron) runsNot available yet
Storage (KV, Durable Objects)Not available. Keep data in a service you call with fetch.
Outbound requestsPublic HTTP and HTTPS only. Private and internal addresses are blocked.
Without an accountNot available. Workers need an API key; static sites don't.

Receiving webhooks? Follow the GitHub and Stripe webhook receiver guide.

Questions

Can my agent add an API backend to a static site?

Yes. Publish the site to <name>.chorus.host and deploy the API as a Worker at <name>-api.worker.chorus.host, then call it from the page with fetch, sending an Access-Control-Allow-Origin header from the Worker. Or serve the page from the Worker itself and skip CORS.

Can my agent deploy a webhook endpoint?

Yes. A Worker gets a public HTTPS URL as soon as it deploys, so it can receive webhooks from GitHub, Stripe or any other service. Keep the signing secret as a Worker secret. Step by step: deploy a GitHub or Stripe webhook receiver.

Does it support TypeScript and npm packages?

With the CLI, yes: if your entry file imports packages, beacon deploy bundles it with esbuild (npm i -D esbuild), or runs your npm run build if package.json has one. The HTTP API takes JavaScript modules as they are, so bundle TypeScript before uploading.

Can I deploy a Hono app from Claude Code or Codex to a public URL?

Yes. beacon init my-api --template hono, npm install, then beacon deploy. The agent signs in with a code from your email, so no browser is needed, and the app is live at https://my-api.worker.chorus.host.

How long does a chorus.host Worker URL stay up?

Until you delete it. There's no claim window and no expiry for Workers.

Is chorus.host Workers free?

Yes. There are no paid plans and no credit card. The limits above apply, including 20 deploys an hour.

Do I need a Cloudflare account?

No. chorus.host runs the Worker on its own Cloudflare account. If you only need it for an hour, Cloudflare's wrangler deploy --temporary also works without an account; it's deleted after 60 minutes unless someone claims it.