For agents and scripts

Publish a static site through the API.

Choose a workflow based on who should own the site. Both accept one HTML file, a ZIP, or a folder. Only static content is served.

Publish into a user’s account

The user signs in on Flux Drop and creates a publish-only API key in API keys. They give that key to their agent through a secret manager, never in a page or repository. Keys expire after 90 days and can be revoked at any time.

curl -X POST 'https://YOUR-DROP-ORIGIN/api/agent/projects?name=my-site' \
  -H 'Authorization: Bearer drop_YOUR_KEY' \
  -H 'Idempotency-Key: unique-random-value' \
  -H 'Content-Type: text/html' \
  --data-binary @index.html

For a ZIP, use Content-Type: application/zip and --data-binary @site.zip. For a folder, send multipart fields named files with relative filenames and an index.html at the root. The response contains path; prepend this service’s origin to share the URL. The site belongs to the key owner immediately and does not expire.

Send X-Drop-Password: BASE64URL_UTF8_PASSWORD to publish a private self-contained HTML page. Passwords must have at least 12 characters. Never put a password or API key in a URL.

Use the bundled MCP server

The same Docker image includes drop-mcp, a local stdio MCP server. It offers publish_html, publish_file, and publish_folder. It connects to Flux Drop over HTTPS; it does not open another inbound port. Create an API key above, save it in a file readable only by your user, and mount that file read-only. Replace the paths, origin, and UID/GID below with yours.

{
  "mcpServers": {
    "flux-drop": {
      "command": "docker",
      "args": ["run", "--rm", "-i", "--user", "YOUR_UID:YOUR_GID",
        "-v", "/absolute/path/to/drop-key:/run/secrets/drop-api-key:ro",
        "-v", "/absolute/path/to/sites:/workspace:ro",
        "-e", "DROP_MCP_ORIGIN=https://YOUR-DROP-ORIGIN",
        "-e", "DROP_MCP_API_KEY_FILE=/run/secrets/drop-api-key",
        "-e", "DROP_MCP_ROOT=/workspace",
        "--entrypoint", "/usr/local/bin/drop-mcp",
        "alihmahdavi/flux-drop:staging"]
    }
  }
}

Use publish_html for a generated HTML document. For local files, pass paths relative to DROP_MCP_ROOT; the folder tool requires index.html at the folder root and rejects symlinks, dotfiles, and unsupported paths. The API key is read from the file on each publish, so rotating or revoking it does not require rebuilding the image. Keep the key out of tool arguments and source control.

Publish without an API key

Start an anonymous session and keep the returned cookie and CSRF token together. Use a single session across retries. The site expires after 7 days unless the human recipient claims it.

curl -c cookies.txt -X POST 'https://YOUR-DROP-ORIGIN/api/session' \
  -H 'Origin: https://YOUR-DROP-ORIGIN'
# Read csrfToken from that JSON response, then:
curl -b cookies.txt -X POST 'https://YOUR-DROP-ORIGIN/api/projects?name=my-site' \
  -H 'Origin: https://YOUR-DROP-ORIGIN' \
  -H 'X-CSRF-Token: YOUR_CSRF_TOKEN' \
  -H 'Idempotency-Key: unique-random-value' \
  -H 'Content-Type: text/html' --data-binary @index.html

After publishing, use the response’s project.id and project.revision to mint a one-use recipient claim link:

curl -b cookies.txt -X POST 'https://YOUR-DROP-ORIGIN/api/projects/PROJECT_ID/transfer' \
  -H 'Origin: https://YOUR-DROP-ORIGIN' \
  -H 'X-CSRF-Token: YOUR_CSRF_TOKEN' \
  -H 'If-Match: "PROJECT_REVISION"'

Give the returned claimURL to the user privately. They open it in their own browser and sign in with Google. Claiming transfers the site to their account permanently. The link expires in 24 hours, works once, and a newly issued link invalidates the previous one. The original agent loses management access after transfer.

Operational details

Give each publish attempt a random 8–128 character Idempotency-Key. Reuse it only when retrying the same files and name after an uncertain response. Successful responses contain project, path, and claimPath. claimPath is only for claiming within the publishing browser session; it is not a transfer link.

Uploads are limited to 50 MiB and 5,000 files. A busy node can respond 429 with Retry-After; exponential backoff is appropriate. Browser-session authentication requires an exact Origin header and a CSRF token. API-key publishing requires a bearer token and deliberately does not accept browser Origin requests.

No code executes on the server. Uploaded JavaScript runs in a restricted browser sandbox and cannot access Flux Drop’s management cookies or API.