Skeebly
Use with Muse
Skeebly builds and hosts simple websites for small businesses. If your website is hosted by Skeebly, you can pair your own Muse with your site so it can make routine changes for you — a price, a phone number, opening hours — without you ever touching HTML or a dashboard.
Reading this page grants no authority. Authority comes only from pairing, below, and only for one site: yours.
How it works
- Pair. Your Muse starts pairing for your site (by its short name, its slug) and shows you a short pairing code. Skeebly emails the site's registered owner a confirmation link.
- Confirm. The owner opens the link and enters the code their Muse showed them. Both together — the link from the owner's mailbox and the code from their Muse — are what turn pairing on; neither alone is enough. Your Muse then receives a pairing credential, once.
- Read & edit. With the credential, your Muse can read your site's current files (live or preview) and prepare edits in its own context.
- Preview. Your Muse submits edited files. Skeebly validates them and commits them to a preview copy of your site. Nothing is live yet.
- Authorize. Skeebly emails the registered owner a link naming the exact preview revision. The link opens a page showing the change and a preview; the owner presses Publish there, and Skeebly publishes exactly that revision live. Just opening the link changes nothing. An agent can never authorize its own change, and an older revision can no longer be published once a newer preview exists.
For your Muse: the API
API base: https://api.skeebly.com
Preview environments: if the URL of this page contains
preview (for example skeebly.preview.skeebly.net), you are reading
the preview copy of this briefing — use https://skeebly-git-preview-radolangs-projects.vercel.app
as the API base instead. Everything else is identical.
All requests and responses are plain JSON over HTTPS. There is no CLI to install and no Git or GitHub access: every repository operation happens on Skeebly's server.
1. Start pairing
POST /api/agent/pairings
Content-Type: application/json
{"slug": "your-site-slug"}
Returns 201 {"pairing_id": "…", "claim_secret": "…", "confirm_code": "…", "status": "pending_confirmation"}.
Keep the claim_secret — it identifies you as the agent that started this pairing.
Show the confirm_code to the human who asked you to pair — they
will need it in the next step. At the same time, Skeebly emails the site's registered
owner a confirmation link (the code is never in the email). The owner opens the link and
enters the code you showed them. Then poll:
2. Poll pairing status
GET /api/agent/pairings/<pairing_id> X-Claim-Secret: <claim_secret>
While pending: {"status": "pending_confirmation"}. On the poll where the
owner's confirmation is seen, the response is
{"status": "active", "slug": "…", "credential": "skb_…"} — the credential is
shown only in that one response. Store it; it is your
Authorization: Bearer <credential> for everything below, and it works
for this one site only.
3. Read your site
GET /api/agent/sites/<slug>/files?ref=live Authorization: Bearer <credential>
Returns {"ref": "live", "site_revision": "…", "files": [{"path": "index.html", "sha": "…", "size": 123}]}.
Paths are relative to your site's folder. ref is live or
preview — the two are always distinct. For one file's content:
GET /api/agent/sites/<slug>/file?path=index.html&ref=preview Authorization: Bearer <credential>
Returns {"path": "index.html", "sha": "…", "content": "…", "site_revision": "…", "ref": "preview"}.
4. Submit an edit (goes to preview)
POST /api/agent/sites/<slug>/submit
Authorization: Bearer <credential>
Content-Type: application/json
{
"base_revision": "<site_revision of the preview you read>",
"idempotency_key": "<a unique string you choose for this change>",
"files": [{"path": "index.html", "content": "<the full edited file>"}]
}
Submit the complete edited file contents, based on the preview
site_revision you read. If the preview has changed since,
you get 409 {"error": "stale_revision", "current_revision": "…"} — re-read,
re-apply your edit onto the fresh content, and submit again. Re-sending the same
idempotency_key is safe: it returns the original revision and creates
nothing new.
On success: 201 {"revision_id": "…", "short_id": "…", "status": "awaiting_authorize", "preview_url": "https://<slug>.preview.skeebly.net/", "result_revision": "…"}.
Check the preview URL yourself to confirm your change looks right. Skeebly has emailed
the owner an authorize link naming this short_id; the owner reviews the
change on that page and presses Publish. (Opening the link alone publishes nothing.)
5. Add a photo
Text edits are not the whole job: when the owner gives you photos — their own pictures, for example from their marketplace ad — you can put them on the site. Photos are uploaded on their own first, then referenced from a page you submit.
POST /api/agent/sites/<slug>/images Authorization: Bearer <credential> Content-Type: image/jpeg <the raw image bytes — not JSON, not base64, not a form>
Content-Type must be image/jpeg, image/png or
image/webp, the file at most 4 MB, and the bytes must
really be that kind of image — they are checked, not trusted. A non-image is refused
(415), an oversize file is refused (413), and a refusal stores
nothing. On success (200):
{"url": "/media/<sha256>.jpg", "sha256": "…", "bytes": 123456,
"contentType": "image/jpeg",
"staging_url": "https://…/sites/<slug>/media/<sha256>.jpg",
"preview_url": "https://<slug>.preview.skeebly.net/media/<sha256>.jpg",
"live_url": "https://<slug>.skeebly.net/media/<sha256>.jpg"}
- Reference the photo in your pages with
url— the root-relative/media/…path, e.g.<img src="/media/<sha256>.jpg" alt="…">. Adding the same image again returns the sameurl; nothing is duplicated. - Uploading alone changes nothing on the site. The photo becomes part
of the site only when a page (or stylesheet) you submit in step 4 references its
/media/…path — that revision carries the photo with it:preview_urlserves it once the revision is on preview, andlive_urlserves it after the owner publishes that revision. - Never put the photo's original address (wherever you found it) or the
staging_urlin a page — only the/media/…url. Pages may reference only photos you uploaded this way; an unknown/media/…reference makes the submit fail. - Owner-supplied photos only — the ones the owner hands you. No stock or generated substitutes.
6. Follow the revision to live
GET /api/agent/sites/<slug>/revisions/<revision_id> Authorization: Bearer <credential>
Statuses are distinct and mean exactly what they say:
awaiting_authorize (on preview, not live), publishing,
verified_live (published and verified on the live site),
superseded (a newer preview revision replaced it; it can no longer be
published), failed (with a reason). Never report a change as
“live” until the status is verified_live and you have fetched the live
site and seen the change yourself.
Hard limits
- One credential, one site. A credential for another site is refused (
403 site_mismatch). - Editable files are text only:
.html .css .js .mjs .json .txt .xml .svg .webmanifest, at most 20 files, 1 MB per file, 2 MB per submit. Paths may not leave your site's folder. - Photos go through the images endpoint, never inside a submit: JPEG, PNG or WebP,
at most 4 MB each, sent as raw bytes. A photo joins a revision only when a
submitted file references its
/media/…url. - You can publish to preview freely. Publishing live always needs the registered owner to open the authorize link Skeebly emailed them for that exact revision and press Publish on that page — there is no API call that authorizes, including for you.
- Pairings are revocable by the owner/operator at any time. A revoked credential is refused everywhere, including for a publish that was already queued.
- Errors:
401missing/invalid/revoked credential or claim secret;403wrong site;404unknown site, file, or revision;409stale base revision;400invalid path, file type, or size.