File Journal & Audit Log
Section titled “File Journal & Audit Log”The file journal records every mutation event for files inside a container: writes, deletes, moves, copies, permission changes, and directory operations. Use these endpoints to query the audit trail, retrieve storage and writer-health statistics, or force pending entries to be durably flushed to disk. All endpoints are scoped to a single container and require the journal feature to be enabled.
Journal queries
Section titled “Journal queries”GET /api/v1/journal
Section titled “GET /api/v1/journal”Query file mutation journal entries with optional filters. Supports cursor-based pagination via after_id. A page can hold fewer entries than limit, or none, while has_more is true: keep paging with next_after_id until has_more is false.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
path | query | string | No | Filter entries by path prefix |
op | query | string | No | Filter by operation type(s), comma-separated (e.g. write,delete) |
since | query | string | No | Filter entries since timestamp (RFC3339 or Unix ms) |
limit | query | integer | No | Max entries to return (default 100) |
after_id | query | integer | No | Cursor: return entries with id > after_id (default 0) |
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-example-1.containers.hoody.com/api/v1/journal?path=src/&op=write,delete&limit=50&after_id=0" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.journal.list({ path: 'src/', op: 'write,delete', limit: 50 });{ "count": 2, "entries": [ { "id": 18421, "ts": 1717686400000, "op": "write", "path": "src/index.ts", "before": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "after": "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7", "blob": true, "blob_before": true, "blob_after": true, "size_before": 0, "size_after": 412, "seq": 7 }, { "id": 18422, "ts": 1717686405000, "op": "delete", "path": "src/legacy.ts", "before": "9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7", "after": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "blob": true, "blob_before": true, "blob_after": true, "size_before": 1024, "size_after": 0, "seq": 3 } ], "has_more": true, "next_after_id": 18422}{ "success": false, "error": "Journal queries are not allowed on this deployment (it was started without --allow-journal)", "code": "JOURNAL_NOT_ALLOWED"}The deployment was started without the --allow-journal flag, so journal queries are disabled.
The journal feature is not enabled on this container.
Too many concurrent journal queries are in flight. Retry after a short delay.
{ "success": false, "error": "Storage check timed out; retry", "code": "STORAGE_CHECK_TIMEOUT"}The journal read could not check the paths it reads in time, so it returned nothing. Retry after the number of seconds given in the Retry-After response header.
| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_PARAMETER | Invalid request | A query parameter, a header or the request body is not one this operation accepts, or a copy or a move names a destination inside the directory it copies or moves; the message names what was refused | Correct the request |
The op field accepts the following values: create, write, append, delete, touch, moved_from, moved_to, copied_from, copied_to, dir_moved_from, dir_moved_to, dir_copied_from, dir_copied_to, dir_deleted, mkdir, chmod, chown, gap.
Journal statistics
Section titled “Journal statistics”GET /api/v1/journal/stats
Section titled “GET /api/v1/journal/stats”Returns storage statistics for the journal system, including entry counts, blob storage usage, writer health, and pruning information.
This endpoint takes no parameters.
curl -X GET "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-example-1.containers.hoody.com/api/v1/journal/stats" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.journal.getStats();{ "total_entries": 18422, "total_blobs": 15840, "total_blob_bytes": 67108864, "total_storage_bytes": 67121152, "writer_healthy": true, "entries_skipped_total": 3, "parse_failures": 0, "skipped_overflow": 0, "newest_entry_ts": 1717686405000, "pruned_before_date": "2024-05-01"}{ "success": false, "error": "Journal queries are not allowed on this deployment (it was started without --allow-journal)", "code": "JOURNAL_NOT_ALLOWED"}The deployment was started without the --allow-journal flag, so journal queries are disabled.
The journal feature is not enabled on this container.
Too many concurrent journal queries are in flight. Retry after a short delay.
| Field | Type | Description |
|---|---|---|
total_entries | integer | Total number of journal entries across all day files |
total_blobs | integer | Total number of content blobs stored |
total_blob_bytes | integer | Total bytes used by content blobs |
total_storage_bytes | integer | Total bytes used by journal (entries + blobs) |
writer_healthy | boolean | Whether the background JSONL writer task is healthy |
entries_skipped_total | integer | Number of paths with entries that were dropped (writer outage) |
parse_failures | integer | Count of corrupted or malformed JSONL lines encountered during scans |
skipped_overflow | integer | Count of dropped paths that exceeded the tracking cap; a non-zero value means completeness detection is degraded |
newest_entry_ts | integer | Unix ms timestamp of the most recent entry, or null if there are none |
pruned_before_date | string | ISO date (YYYY-MM-DD) before which all day files have been pruned, or null if no pruning has occurred |
Flush journal
Section titled “Flush journal”POST /api/v1/journal/flush
Section titled “POST /api/v1/journal/flush”Force all pending journal entries to be written and fsynced to disk. Returns 200 with flushed: true if all entries were durably persisted, or 503 with flushed: false if the flush failed or entries were lost.
This endpoint takes no parameters.
curl -X POST "https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-example-1.containers.hoody.com/api/v1/journal/flush" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://67e89abc123def456789abcd-890abcdef12345678901cdef-files-1.node-example-1.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.files.journal.flush();{ "flushed": true}{ "success": false, "error": "Journal queries are not allowed on this deployment (it was started without --allow-journal)", "code": "JOURNAL_NOT_ALLOWED"}The deployment was started without the --allow-journal flag, so journal queries are disabled.
The journal feature is not enabled on this container.
{ "flushed": false}The flush was not durable. Pending entries may have been lost or the underlying write failed. Investigate disk health and the writer task before retrying.