LemonadeHost help Main site Pricing Status

For developers

The HTTP API

Five endpoints. A bearer token, a zip, and no SDK to adopt.

The base URL is your instance — https://app.lemonadehost.com. Every request carries the token:

Authorization: Bearer lm_…

Endpoints

MethodPathDoes
GET/api/deploy/whoamiWhich site this token reaches, and whether it is serving.
POST/api/deploy/{siteId}Publish a zip. Replaces the whole site.
GET/api/deploy/{siteId}/deploymentsRecent publishes and their outcomes.
GET/api/deploy/{siteId}/filesThe live files, as text.
POST/api/deploy/{siteId}/restorePut a previous release back.

Check the token first

curl -s https://app.lemonadehost.com/api/deploy/whoami \
  -H "Authorization: Bearer $LEMONADE_TOKEN"
{
  "ok": true,
  "site": "st_…",
  "name": "My site",
  "subdomain": "mysite",
  "url": "https://mysite.lemonhosted.com",
  "serving": true
}

serving is the useful one: it is false when the site would accept files but not show them — unpaid, or held for review. A CI job can find that out without opening a support thread.

Publish

curl -X POST https://app.lemonadehost.com/api/deploy/st_… \
  -H "Authorization: Bearer $LEMONADE_TOKEN" \
  -H "Content-Type: application/zip" \
  --data-binary @site.zip

Put index.html at the ROOT of the zip. Nothing refuses an archive without one — the publish succeeds and the site's home address then serves a 404, which is a worse way to find out. A single wrapper folder is the usual cause, and only the GitHub door strips one; this endpoint publishes the archive exactly as sent.

Limits

LimitDefault
Compressed upload256 MB
Any single file25 MB
Files per site20,000
Total extracted1 GB
Restore window7 days

Status codes

CodeMeans
401Missing, malformed or revoked token.
404No such site — or not this token's site. The two are deliberately indistinguishable.
409A deploy is already running, or the site is managed by the editor.
413Too large. See the table above.
429Rate limited. Retry-After says how long.
400Empty body, or the upload was interrupted.
404 rather than 403, deliberately. A token pointed at somebody else's site gets the same answer as one pointed at a site that does not exist. Neither confirms the site is real.

Every refusal, with the fix, is on when a publish is refused.

Reading files back

GET /api/deploy/{siteId}/files returns the live text files as JSON. Binary files are listed but not returned, the total is capped, and the response says when it truncated — so an assistant can tell the difference between "that is the whole site" and "that is as much as fitted".

Read before you replace. A publish replaces everything, so an edit is: read the files, change the one you meant, send the whole set back.

Last checked against the product on 2026-09-04. Something wrong or missing? Tell us.