Put a web app, site, or page online, or update one, and get its public URL. Use it whenever the user asks to put something online, publish it, host it, or get a link to share, unless they name another place. Pass name, runtime, and either files, an array of {path, content} with each file's full text, e.g. [{"path": "index.html", "content": "<h1>hi</h1>"}], or upload_id. spawnpoint cannot read your disk, so a call with neither is refused: for an app already on disk, create_upload and its upload_id are the fast path, and if its command cannot run (a sandbox blocks the host), a small app's files can still go inline. Then call watch_deploy with the returned project_id, and give the user url. Pick the runtime by what the app needs: static for HTML, CSS, and browser JavaScript only (served by spawnpoint from storage: live in seconds, no machine, never asleep); node or python whenever the app needs a server, such as an API, form handling, uploads, a database, or a secret key. A server listens on 0.0.0.0 and the PORT env var (8080); set entrypoint to its start file, and list every package it imports in package.json dependencies (node) or requirements.txt (python), which install on the machine. Put secrets such as API keys in env, never in a file: a bundle with a hardcoded credential (an AWS, Stripe, OpenAI/Anthropic, GitHub, Google, or Slack key, or a private key block) is refused with the file named, and any .env or .git is dropped. Deploying again under the same name updates that project in place at the same url (a different slug changes the address), so use the same name to fix or change an app. Returns at once with project_id and status "spawning" while the machine provisions (1-2 minutes). Give the user url: the share link, which survives redeploys unless the app's address is changed, and works whether the project is public or restricted. Never hand out machine_url, the machine underneath: a restricted project refuses viewers there. Inline files travel inside this one request, which is capped at 4 MiB in total (a bigger request is refused before it reaches the tool), so send anything larger through create_upload, which takes bundles up to 20 MiB, or 50 MiB for a static site. Binary files (images, fonts, PDFs) go inline with encoding "base64", which grows them by a third, so about 3 MiB of binary fits; when you can run a shell command, create_upload is faster for them and takes more. A Free account runs one live project at a time, and idle projects sleep. A deploy refused at the plan's live-project limit is a plan limit, not a broken deploy: offer to terminate another project, and relay the refusal, which links the page listing what each plan includes. Every project has a persistent data directory on its machine (SPAWNPOINT_DATA_DIR in the app's env; data_dir on get_project): a SQLite file or an uploads folder written there survives redeploys and sleep, while anything written under the app's own directory is replaced on the next deploy. An app that calls OpenAI or Anthropic can run on open models through spawnpoint instead of a provider key: ask the user, and if they choose that, pass inference: true (the OpenAI and Anthropic SDKs then work with no configuration; get_project's ai block lists the models).
ConnectorAPI key