Documentation

Build with Mello

Everything you need to go from idea to endpoint: APIs, databases, realtime rooms, cron jobs and websites.

melloagent.md
Early preview. Mello is in early preview. Mello is available for early testing. Deployments and routing may take a little time to become available.
01 Getting started

Your first API, step by step.

  1. Create an account and verify your email.
  2. In your dashboard, create an API with a name such as hello-mello. Names are unique within your account and can repeat across accounts. Mello adds a random suffix to the endpoint.
  3. Create a key for that API and copy it immediately. It is shown only once.
  4. Write a single-file JavaScript or TypeScript Worker, review it, and deploy your API.
  5. Use the displayed endpoint and your key to send a request.
02 Your first worker

Start with a hello.

Save this as index.js. Mello passes requests to the default exported Worker’s fetch handler. In this example, the path inside the Worker is /hello; Mello removes your route prefix (the API name plus its random suffix) first.

index.js JAVASCRIPT
export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (request.method === 'GET' && url.pathname === '/hello') {
      return Response.json({ message: 'Hello from Mello!' });
    }

    return Response.json({ error: 'Not found' }, { status: 404 });
  },
};

The dashboard accepts one JavaScript or TypeScript ES module up to 10 MB. Mello compiles TypeScript syntax into JavaScript during deployment; this removes type annotations but does not type-check your project. Have more than one file, or npm packages? Use project bundling and Mello bundles them for you. Store sensitive values as variables in the dashboard, not in your source file.

03 Deploy

Give it a home.

Choose your API in the dashboard. Drag a .js, .mjs, or .ts file onto the upload area, or use the file picker. The file is loaded into the editor so you can inspect and edit it before selecting Deploy API. Uploading a file alone does not deploy it. You can request cancellation before publishing begins; once resource changes start, the deployment cannot safely be cancelled.

New deployments attempt to save an encrypted source snapshot for comparison in Deployment history. You can remove a snapshot there without changing the running deployment. Earlier versions do not have snapshots, and very large source comparisons may be limited. Mello keeps the previous deployment active until the replacement is ready. Use Deployment history to restore an available earlier version. A failed or interrupted deployment may require operator review. You can also paste a public raw.githubusercontent.com link to a bundled JavaScript file and deploy it manually. Private repositories and automatic deploys on push are not connected yet.

Static website hosting

Bring a built website to Mello.

Use Dashboard → Websites to create a site, then choose or drop its output folder. Mello serves the files as a static website with a shareable URL. The folder must have an index.html at its top level.

HTML, CSS, JavaScript, images, and the output of TypeScript frameworks are supported. For TypeScript, build your project on your computer or in your own CI first, then upload the generated output such as dist or out. Mello does not run a build command or a server process for these sites; backend routes and server-side rendering are not included.

The starter limits each site to 20 MB and 1,000 files, with a maximum file size of 1.8 MB. Each account can create up to two sites, subject to available platform capacity. Use relative asset paths in your site, and keep API credentials out of browser JavaScript. For a private API call, use a backend you control.

04 Send a request

Make your first request.

Replace the placeholders below with the endpoint shown in your dashboard and your API key. Append the path your Worker handles; the example above responds at /hello.

Terminal CURL
curl https://YOUR-GATEWAY/api/hello-mello-a1b2c3d4e5f6/hello \
  -H "X-API-Key: YOUR_MELLO_KEY"

A successful call to the example returns { "message": "Hello from Mello!" }. You can also call it from a server:

server.js JAVASCRIPT
// Run on your server, not in browser code.
const response = await fetch(
  'https://YOUR-GATEWAY/api/hello-mello-a1b2c3d4e5f6/hello',
  { headers: { 'X-API-Key': process.env.MELLO_API_KEY } }
);
if (!response.ok) throw new Error(`Mello returned ${response.status}`);
console.log(await response.json());

The key authenticates the caller to Mello and is removed before the request reaches your Worker. Other Authorization headers are also removed by the current gateway.

Build with mello

Bring your project to life.

Call your API from a trusted server. These examples share the same request helper; set MELLO_ENDPOINT to the API URL shown in your dashboard and MELLO_API_KEY to its key. Keep both on your server and adapt the paths and response fields to your API.

mello-client.js SERVER-SIDE JAVASCRIPT
export async function callMello(path) {
  const response = await fetch(process.env.MELLO_ENDPOINT + path, {
    headers: { 'X-API-Key': process.env.MELLO_API_KEY },
  });
  if (!response.ok) throw new Error('Mello request failed: ' + response.status);
  return response.json();
}

Discord bot

Choose the Discord bot API template when deploying, or use your own API. In your bot server, use the helper above to call /greeting and reply to a command. This assumes an existing Discord bot. The bot server holds the Mello key; do not put it in your bot’s client code or repository. Mello’s gateway requires its API key, so a Discord webhook cannot call this endpoint directly.

discord-command.js JAVASCRIPT
import { callMello } from './mello-client.js';
// Inside an existing Discord interaction handler:
const data = await callMello('/greeting?name=' + encodeURIComponent(interaction.user.username));
await interaction.reply({ content: data.message, ephemeral: true });

Telegram bot

The Telegram webhook starter verifies the x-telegram-bot-api-secret-token header against the TELEGRAM_WEBHOOK_SECRET variable before accepting an update. Configure the same secret in your Telegram webhook settings and deploy after saving it. The starter acknowledges valid updates; add your own handling to send replies.

Telegram cannot attach a Mello API key to its webhook requests. Run a trusted proxy that accepts Telegram requests, forwards the original body and secret-token header, and adds your Mello API key before forwarding to your Mello endpoint. Protect the key on the proxy server. The starter will reject missing or incorrect secret-token headers.

For outgoing replies from your own bot server:

telegram-reply.js JAVASCRIPT
import { callMello } from './mello-client.js';
// Inside your verified Telegram update handler:
const data = await callMello('/hello');
await fetch('https://api.telegram.org/bot' + process.env.TELEGRAM_BOT_TOKEN + '/sendMessage', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ chat_id: update.message.chat.id, text: data.message }),
});

Website or game backend

Call Mello from your own backend, then return only the data the visitor or game client is allowed to see. Never put a Mello key in browser or game client code.

server-route.js JAVASCRIPT
import { callMello } from './mello-client.js';
// Example Next.js route handler, running on your server:
export async function GET() {
  const data = await callMello('/hello');
  return Response.json({ message: data.message });
}

Other ideas

Use the same server-side helper for mobile apps, automation jobs, community tools, or a webhook processor. Authenticate requests to your own backend before returning private data.

Work from your terminal

Meet the Mello CLI.

Download the CLI and use Node.js 22 or newer to list APIs, create a project, or deploy a single bundled JavaScript module. Your Mello email must be verified.

Terminal SHELL
curl -fsS -o mello.mjs https://www.itsmello.cloud/mello.mjs
node mello.mjs list
node mello.mjs create my-api
node mello.mjs deploy my-api ./index.js
node mello.mjs deploy my-api ./my-project   # bundles a folder first

The CLI asks for your email and password in the terminal for each command. It hides the password and does not save your password or session. Review downloaded scripts before running them.

For automation, the CLI can read a short-lived account ID token from MELLO_ID_TOKEN. These tokens expire; Mello does not yet offer long-lived CI credentials or automatic token renewal. Do not commit tokens to a repository.

Download the CLI
Bigger projects

Bundle a whole project.

Split your API across files and use npm packages. In the dashboard, open Deploy and choose Bundle a project folder, or run node mello.mjs deploy my-api ./my-project. Mello finds your entry file (main in package.json, or src/index.ts), bundles your files and the packages in dependencies, and loads the result into the editor for you to review.

Project FILES
my-project/
  package.json      # { "dependencies": { "hono": "^4.6.0" } }
  src/index.ts      # export default app
  src/routes.ts
  • Packages come from npm via the esm.sh CDN. Pin versions in package.json for repeatable builds.
  • node_modules, .git and build folders are skipped. Source must be under 3.5 MB and the bundle under 10 MB.
  • Node.js built-ins like fs and child_process aren’t available. Use Web APIs such as fetch, crypto.subtle and Response.
  • Your entry file needs a default export with a fetch(request, env) handler, like a Hono app.
Realtime

Realtime rooms.

Every API has WebSocket rooms. Connect to /_rooms/<room> on your API with a key, pass it as the mello-key. subprotocol from a browser, and any message you send goes to everyone else in that room. Room names use letters, numbers, - and _.

chat.js JAVASCRIPT
// Browser: join the "lobby" room
const socket = new WebSocket(
  'wss://api.itsmello.cloud/api/YOUR_ROUTE_ID/_rooms/lobby?name=Ana',
  ['mello-key.' + MELLO_KEY]
);
socket.onmessage = (e) => console.log(JSON.parse(e.data));
socket.onopen = () => socket.send(JSON.stringify({ text: 'hi!' }));

Mello sends JSON events: welcome (with who is already there), join, leave and message. Messages can be up to 16 KB, and each API can hold 200 connections. Your server can push to a room with a POST to the same path. For a website, add its address under Network first. Dashboard → Realtime shows who is online.

Plus

Custom API domains.

Serve an API from your own domain, like api.example.com. Open Dashboard → Network → Custom domain, enter the domain, then add a CNAME record pointing to api.itsmello.cloud at your DNS provider. Mello issues the certificate, and the status changes to Working when it is ready, usually within a few minutes.

On your own domain there is no /api/<route-id> prefix: https://api.example.com/hello reaches your /hello route. Requests still need your API key.

Work locally

Run your API with mello dev.

Test changes on your own machine before deploying. mello dev starts a local server, loads variables from .dev.vars or .env, enforces Mello’s 120 requests per minute and 3 MB body limits, and reloads when you save. No sign-in needed.

Terminal SHELL
node mello.mjs dev ./index.js
# → http://localhost:8787, reloads on save

# .dev.vars (next to your file)
API_TOKEN="local-test-value"

It runs on Node.js, so it’s close to Mello’s runtime but not identical. Always try the deployed version in the Playground before sharing it.

Build with confidence

Use Mello with CI.

Run your tests and bundle your project in your existing CI pipeline, then upload the resulting single JavaScript module in the dashboard. The Mello CLI can deploy with a short-lived account ID token, but automatic deployments on push and long-lived CI credentials are not yet available.

Example CI steps SHELL
npm ci
npm test
npm run build
# Upload your bundled .js or .mjs in Mello’s dashboard.

Configure your build command to output one ES module without external imports. Store credentials in your CI provider’s secret manager, and never commit keys or paste them into the module.

Keep data around

Persistent storage.

Each active API has its own simple JSON key-value store. Create an API key, save it as STORAGE_API_KEY in Variables & secrets, and deploy your code. Use the route ID from your dashboard endpoint (the part after /api/) as projectId. It includes your API name and its random suffix.

index.js JAVASCRIPT
export default {
  async fetch(request, env) {
    const response = await fetch('https://www.itsmello.cloud/api/storage', {
      method: 'POST',
      headers: { 'content-type': 'application/json', 'x-api-key': env.STORAGE_API_KEY },
      body: JSON.stringify({ projectId: 'YOUR_API_ROUTE_ID', action: 'put', key: 'greeting', value: { message: 'hello' } }),
    });
    if (!response.ok) return Response.json({ error: 'Storage unavailable' }, { status: 502 });
    return Response.json(await response.json());
  },
};

Send get, put, or delete as the action. A get returns found and, if present, value. Keys start with a letter or digit and may contain letters, digits, periods, underscores and hyphens, up to 100 characters. On Free, each API can hold 1,000 keys with values up to 64 KB (25 MB in total), and make 300 storage requests per minute and 50,000 per UTC day. Mello Plus raises that to 10,000 keys, 256 KB values, 250 MB in total, 600 requests per minute and 500,000 per day. Backups hold up to 10 MB on Free and 50 MB on Plus.

The storage key can also call that API, so keep it private. Store secrets in Variables & secrets rather than in this store. Data remains until deleted; full API deletion and cleanup are not yet available.

Files for your API

Store small files and images.

Use the file endpoint from trusted server code with an API key for an active project. Files are private and returned as base64; Mello does not create public file URLs.

store-file.mjs JAVASCRIPT
import { readFile } from 'node:fs/promises';
const dataBase64 = (await readFile('./avatar.png')).toString('base64');
const response = await fetch('https://www.itsmello.cloud/api/files', {
  method: 'POST',
  headers: { 'content-type': 'application/json', 'x-api-key': process.env.MELLO_API_KEY },
  body: JSON.stringify({ projectId: 'YOUR_API_ROUTE_ID', action: 'put', key: 'images/avatar.png', name: 'avatar.png', contentType: 'image/png', dataBase64 }),
});
if (!response.ok) throw new Error('File upload failed: ' + response.status);
console.log(await response.json());

Send list, put, get, or delete. A file can be up to 2 MB; each API can store up to 25 MB across 500 files. Use a stable key such as images/avatar.png to replace a file. File contents are stored in chunks and survive code deployments. Keep the API key on a server; do not expose it in browser code.

Network & access

Choose who can reach your API.

On the API detail page, open Network & access. Add exact HTTPS website origins to allow browser calls and choose the request methods. Mello answers browser preflight requests and adds the matching response headers.

CORS settings CONFIGURATION
// Dashboard → choose an API → Network & access
// Add https://app.example.com to Allowed website origins.
// Mello handles the browser preflight and adds CORS headers to the response.
// Keep the API key on your server; CORS is not authentication.

CORS controls which browsers may read a response; it does not authenticate requests. Keep keys on trusted servers. You can also allow IPv4 addresses or CIDR ranges. An empty allowlist leaves the API reachable from any network.

WebSocket connections

The gateway forwards WebSocket upgrades to your API. Browser clients can pass the API key as a mello-key.<API_KEY> subprotocol; Mello strips it before forwarding the upgrade, leaving your application subprotocols.

client.mjs JAVASCRIPT
const socket = new WebSocket(
  'wss://api.itsmello.cloud/api/hello-mello-a1b2c3d4e5f6/chat',
  ['mello-key.' + process.env.MELLO_API_KEY, 'chat.v1']
);
socket.addEventListener('message', event => console.log(event.data));
Private configuration

Variables & secrets.

On the Deploy page, choose an API and add a variable name and value. Values are encrypted in storage, shown only when entered, and supplied to the next deployment. Names must start with a capital letter, contain only capital letters, numbers and underscores, and cannot start with MELLO_. Each API can have up to 10 values of 4 KB each.

index.js JAVASCRIPT
export default {
  async fetch(request, env) {
    const token = env.API_TOKEN;
    // Use token in a server-to-server request.
    return Response.json({ configured: Boolean(token) });
  },
};

Adding, changing or removing a value does not alter an existing deployment; deploy again to apply the change. Restoring a previous version also restores the values that version had. If a credential is exposed, rotate it with its provider and redeploy; changing it in Mello alone does not invalidate the old credential.

Your code can read its own values. Keep them out of responses and logs, and only deploy code you trust.

05 Security

Take care of your keys.

Keys grant access to one API. Store them in server-side environment variables or a secret manager; never commit them to a repository, paste them into frontend code, or share them in screenshots. If one is exposed, revoke it in the dashboard and create a replacement. Revoked keys cannot be used again.

06 Limits

Limits and usage.

The current control-plane design allows five APIs per account, ten active keys per API, ten deployment attempts per API per UTC day, and 60 admitted requests per API per minute. Shared platform limits also apply. These limits may change before launch.

The dashboard counts admitted requests, including calls that subsequently fail in your Worker. Mello automatically allows 10,000 admitted requests per API per UTC day and displays a warning at 8,000. Once the daily allowance is reached, requests receive HTTP 429 until midnight UTC. Shared platform limits can apply sooner. It does not currently measure response time or provide billing information.

07 Troubleshooting

Something not quite right?

401

The key is missing, invalid, revoked, or belongs to a different API. Create a new key if you no longer have the original.

404

Check the endpoint URL shown on your API page and whether it has an active deployment. A 404 can also come from your own Worker when its path does not match.

429

The API has reached its request or deployment limit. Wait for the limit to reset before trying again.

502 / 503

The Worker or Mello’s control plane is unavailable. Check status and try again; the status page provides point-in-time service checks.

If a file won’t load, check that it is one non-empty UTF-8 .js, .mjs, or .ts file no larger than 10 MB. If sign-in succeeds but the dashboard asks you to verify your email, follow the email link and sign in again.

Ready to make your first API?

It takes about a minute.

Open your dashboard