Edit
Read and change a project's files.
How Editing Works
Any file in a project can be changed: pages, data, manifest.json, styles, images, and more. Each update becomes a new deployment on staging, so you can check it before you promote it.
To start from nothing, publish a build, or send an update that includes an index.html. For a documentation site from Markdown, the Docs Template builds one in a single request.
Read Files
List the files of the live deployment, so you can see what to change.
curl "https://api.manifestx.dev/v1/projects/proj_…/files?env=staging" \
-H "Authorization: Bearer $MANIFEST_ACCOUNT_KEY"
| Field | Type | Required | Notes |
|---|---|---|---|
env |
string | no | staging (default) or production. |
limit |
number | no | Files per page, 1 to 1,000. Defaults to 1,000. |
cursor |
string | no | The next_cursor from the previous page. |
{
"env": "staging",
"deployment_id": "dep_…",
"files": [
{ "path": "_redirects", "size": 64, "content_type": "application/octet-stream", "etag": "9b2e…" },
{ "path": "_redirects.json", "size": 210, "content_type": "application/json; charset=utf-8", "etag": "41c7…", "compiled_from": "_redirects" },
{ "path": "articles/intro.md", "size": 1834, "content_type": "text/markdown; charset=utf-8", "etag": "e3b0…" },
{ "path": "index.html", "size": 2210, "content_type": "text/html; charset=utf-8", "etag": "5d41…" }
],
"next_cursor": null,
"request_id": "…"
}
- Paths match what a file update takes, sorted by path.
etagchanges when a file's content does. Treat it as opaque: the same content can carry a differentetagif published another way.compiled_frommarks a file Manifest compiles. Edit the source file instead.- Left out:
precache.jsonandmanifest.utilities.css, which Manifest writes on every publish. - Nothing live yet:
deployment_idisnullandfilesis empty. - More pages: send
next_cursorascursor. A cursor keeps reading the same deployment, even if a new one goes live meanwhile.
Read One File
Fetch one file's content from the deployment live on env (staging by default).
curl "https://api.manifestx.dev/v1/projects/proj_…/files/articles/intro.md" \
-H "Authorization: Bearer $MANIFEST_ACCOUNT_KEY"
The answer is the file itself, not JSON, with these headers:
| Header | Value |
|---|---|
Content-Type |
The file's type, such as text/markdown; charset=utf-8 or image/png. |
ETag |
The file's etag from the list, in quotes. |
x-manifest-deployment |
The deployment the file came from. Send it as base with your update. |
HTML comes back as stored, without the tags Manifest adds when serving. Send If-None-Match with the ETag to get 304 Not Modified when nothing changed. Encode special characters in the path the way a browser would, such as a space as %20.
Update Files
When only a few files change, send just those. Manifest keeps everything else that is live on staging and publishes the result as a new staging deployment.
curl -X PATCH https://api.manifestx.dev/v1/projects/proj_…/files \
-H "Authorization: Bearer $MANIFEST_ACCOUNT_KEY" \
-H "Idempotency-Key: edit-intro-0042" \
-H "Content-Type: application/json" \
-d '{
"base": "dep_…",
"files": [
{ "path": "articles/intro.md", "content": "# Introduction\n\nUpdated text." },
{ "path": "media/logo.png", "content_base64": "iVBORw0KGgo…" },
{ "path": "articles/old.md", "delete": true }
]
}'
| Field | Type | Required | Notes |
|---|---|---|---|
files |
array | yes | 1 to 1,000 changes, one per path. |
base |
string | no | The deployment your changes start from. If staging has moved on since, nothing changes and the answer is 409 base_mismatch. |
env |
string | no | Only staging. Promote to reach production. |
Each change has a path from the project root (inside output_dir, if the build has one) and exactly one of these:
| Field | Type | Notes |
|---|---|---|
content |
string | The new file as UTF-8 text, for Markdown, JSON, HTML, CSS, and other text files. |
content_base64 |
string | The new file as standard base64, for images and other binary files. |
delete |
boolean | true removes the file. |
A path that doesn't exist yet adds a file. The answer is 201 Created, and the new version is live on the staging URL straight away:
{
"deployment": { "id": "dep_…", "env": "staging", "status": "ready", "files": 43, "bytes": 320544, "base": "dep_…" },
"changes": { "updated": 2, "deleted": 1 },
"url": "https://acme-docs-staging.manifestx.ai",
"request_id": "…"
}
Avoid Overwriting Others
Send the last deployment.id you saw as base, so two editors can't overwrite each other.
- Read the files and note the
deployment_id. - Send your update with that id as
base. - On
409 base_mismatch, read the files again, reapply your change, and send it with the newlive_deployment_id.
Without base, changes apply to whatever is live on staging. Either way, an update is refused with the same 409 if another publish lands while it runs, and you can send it again.
Good to Know
- Limits. A request can be up to 12 MB, with each file up to 8 MB after decoding. Publish larger files in a zip.
- First publish. If nothing is live on staging yet, the files become the project's first version and must include
index.html. No update can removeindex.html. - Refused paths.
.envfiles,.git,node_modules,.claude,precache.json, andmanifest.utilities.cssare refused. - Redirects and headers. Manifest compiles
_redirectsand_headersinto.jsonfiles. Update the source file, not the compiled one. - HTML read back is fine. The analytics and badge tags Manifest adds when serving a page are removed before the file is stored.
- Prerendered builds. On
renderoutput, the answer carries aprerendered_sitenotice: pages built from the changed files aren't rebuilt, so publish a new build to refresh them. - It counts as a publish. Each update counts toward a Free project's daily publish limit. It's also a new deployment, so frequent updates push older versions out of rollback reach.
- A rare warning. If a follow-up step doesn't finish, the answer is still
201with awarning. Don't resend it: the step completes on the next publish.
Article does not exist
There is no documentation at this path.