Runlog docs

Start building

A plan buys a weekly allowance, sized for steady work.

Start

Source changes

For a file whose content moved. The single-file surgical update is deliberately open on every plan — a new version re-ingests only its delta, unchanged regions cost nothing, and every reference to the file survives because the file id never changes. Reingest re-runs derivation without re-uploading a byte.

PUT/v1/projects/{projectId}/files/{fileId}/contentAPI key

Replace a file's content

Flip an existing file onto a replacement chunk you have already uploaded, and re-derive only what changed.

The edit lane is a diff, not a rewrite. The server compares the old content-addressed derivations against the new ones and re-ingests only the differing parts; unchanged regions are untouched, and derivations that no longer have a source retire.

Upload the replacement bytes through `chunks/missing` first, exactly as for a new file. This endpoint moves the pointer; it never carries bytes.

The `fileId` does not change. Everything that cites the file — retrieval results, plan proposals, folder placement — keeps citing it.

Path parameters

FieldTypeRequiredDescription
projectIdstringrequiredThe owning project.
fileIdstringrequiredThe file to edit.

Body

FieldTypeRequiredDescription
chunkIdstringrequiredThe replacement content's chunk id. Its bytes must already be stored.
fileSizeintegeroptionalNew total size in bytes.
Request · curl
curl -X PUT "https://runlog-7613480744.us-central1.run.app/v1/projects/p7Kd2mQx/files/4mHqZ1nR8vTbC0sWyLpAeGkJ3dXfU6iO2rN/content" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx" \
  -H "Content-Type: application/json" \
  -d '{
  "chunkId": "Yt4RcVbNm2QaZsXdCfVgBhNjMkLoPiUyTrE",
  "fileSize": 42190
}'
Response · 200
{
  "chunkIds": [
    "Yt4RcVbNm2QaZsXdCfVgBhNjMkLoPiUyTrE"
  ],
  "chunking": "",
  "createdAt": "2026-08-07T18:22:10Z",
  "ext": "swift",
  "fileId": "4mHqZ1nR8vTbC0sWyLpAeGkJ3dXfU6iO2rN",
  "fileSize": 42190,
  "fileType": "code",
  "filepath": "Sources/Net",
  "name": "Router.swift",
  "projectId": "p7Kd2mQx",
  "status": "queued",
  "updatedAt": "2026-08-07T18:22:10Z"
}

Errors

StatuserrorWhen
400chunk is not storedYou named a chunk whose bytes never landed. Run `chunks/missing` and PUT the body first.
400file is not editableThe file's family has no content-edit lane (a media container, for instance).
404file not foundNo such file in this project.
403editor access requiredYou can read the project but not write to it.
404project not foundThe project does not exist, or you have no access to it. Projects are non-enumerable, so a denied read is indistinguishable from a missing one.
401invalid API keyThe `Authorization` header is missing, malformed, or names a revoked key.
400name the target project via the X-Project-Id header or projectId queryNo project was named and the key is not bound to one.
429rate limit exceededYou passed 60 requests/minute on this key. `Retry-After` carries the seconds to wait.
500internal errorThe relay failed to serve the request. Retry with backoff; the cause is logged server-side against your request.
POST/v1/projects/{projectId}/files/reingestAPI key

Reingest files

Re-run the derivation pass over named files without re-uploading their bytes.

Bytes are already content-addressed and stored, so this costs no upload. The whole set lands in one enqueue — one queue write and one wake for N files, never a wake per file.

An id that no longer resolves is dropped rather than failing the batch.

Path parameters

FieldTypeRequiredDescription
projectIdstringrequiredThe owning project.

Body

FieldTypeRequiredDescription
fileIdsstring[]requiredFiles to re-derive. A single-element array is the single-file reingest.
Request · curl
curl -X POST "https://runlog-7613480744.us-central1.run.app/v1/projects/p7Kd2mQx/files/reingest" \
  -H "Authorization: Bearer $RUNLOG_API_KEY" \
  -H "X-Project-Id: p7Kd2mQx" \
  -H "Content-Type: application/json" \
  -d '{
  "fileIds": [
    "4mHqZ1nR8vTbC0sWyLpAeGkJ3dXfU6iO2rN"
  ]
}'
Response · 200
{
  "enqueued": 1,
  "skipped": 0
}

Errors

StatuserrorWhen
400fileIds are requiredThe batch was empty.
403editor access requiredYou can read the project but not write to it.
404project not foundThe project does not exist, or you have no access to it. Projects are non-enumerable, so a denied read is indistinguishable from a missing one.
401invalid API keyThe `Authorization` header is missing, malformed, or names a revoked key.
400name the target project via the X-Project-Id header or projectId queryNo project was named and the key is not bound to one.
429rate limit exceededYou passed 60 requests/minute on this key. `Retry-After` carries the seconds to wait.
500internal errorThe relay failed to serve the request. Retry with backoff; the cause is logged server-side against your request.