Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/HNU-himematsu/HNU-TimeLetter/llms.txt

Use this file to discover all available pages before exploring further.

The sync jobs API manages the full lifecycle of Feishu data sync tasks. Each job pulls records from Feishu Bitable and writes them to JSON output files under src/data/. The frontend reads those files through the public runtime API (/api/content, /api/contributors, /api/creation-board) at request time — no build or server restart is needed after a sync completes.
All sync jobs execute asynchronously. A 202 Accepted response means the job has been queued successfully — it does not mean the sync has finished. Poll GET /api/admin/sync/jobs/:jobId or stream GET /api/admin/sync/jobs/:jobId/logs to track progress.

Enum reference

SyncJobKind

ValueDescription
sync-dataPull records from Feishu Bitable and write JSON output files to src/data/.

SyncJobStatus

ValueDescription
queuedJob has been created and is waiting to run.
runningJob is actively executing.
successAll tables synced successfully.
partial_successSome tables failed, but output files were still written.
failedJob failed; output files were not updated.
canceledJob was canceled before completion.

SyncStepStatus

ValueDescription
pendingStep is waiting to be executed.
runningStep is currently executing.
successStep completed without issues.
success_with_warningsStep completed but some records had non-fatal issues.
skippedStep was skipped due to missing dependencies or an earlier termination.
failedStep failed.

DependencyMode

ValueDescription
read_local(Default) Sync only the selected tables; read dependency data from local output files.
run_dependenciesAutomatically run dependency tables before the selected tables.
strictFail immediately if a dependency is missing — no local read, no automatic run.

GET /api/admin/sync/jobs

Returns a paginated list of sync job records, sorted by createdAt descending (most recent first). Authentication: admin_auth cookie required.

Query parameters

limit
number
default:"20"
Maximum number of records to return. Accepted range: 1100.

Response fields

items
SyncJobRecord[]
required
Array of sync job records sorted newest-first.

curl example

curl -X GET "https://himematsu.cn/api/admin/sync/jobs?limit=10" \
  --cookie "admin_auth=<YOUR_SESSION_COOKIE>"

POST /api/admin/sync/jobs

Creates a new sync job and immediately queues it for background execution. The response is returned as soon as the job is queued — before any Feishu API calls are made. Authentication: admin_auth cookie required.

Request body

kind
SyncJobKind
Job type. Defaults to the value from the scheduler configuration. Currently the only accepted value is "sync-data".
tables
SyncTableKey[]
Which tables to sync in this job. Defaults to config.defaultTables when omitted. Cannot be an empty array.
dependencyMode
DependencyMode
default:"read_local"
Controls how tables that other selected tables depend on are handled. See the DependencyMode enum above.
includeAssets
boolean
default:"true"
When true, attachment files are downloaded and their OSS URLs are back-filled into the output JSON.
continueOnTableError
boolean
default:"false"
When true, a failure in one table step does not abort the remaining steps.
triggeredBy
string
default:"admin-ui"
A free-form label identifying the caller. Stored in the job record for auditing.
note
string
Optional human-readable note stored with the job record (e.g. "手动刷新首页内容").

Responses

202 Accepted — Job was queued successfully.
{
  "jobId": "sync_20260430100000_ab12cd",
  "status": "queued",
  "kind": "sync-data",
  "tables": ["locations", "stories"],
  "effectiveTables": ["locations", "stories"],
  "createdAt": "2026-04-30T10:00:00.000Z"
}
409 Conflict — Another sync job is already running. Wait for it to finish before creating a new one.
{
  "message": "已有同步任务正在执行",
  "currentJobId": "sync_20260430095900_xy99zz"
}
400 Bad Request — One or more table keys are not valid SyncTableKey values.
{ "message": "不支持的同步表: unknown_table" }

curl example

curl -X POST https://himematsu.cn/api/admin/sync/jobs \
  --cookie "admin_auth=<YOUR_SESSION_COOKIE>" \
  -H "Content-Type: application/json" \
  -d '{
    "tables": ["locations", "stories"],
    "dependencyMode": "read_local",
    "includeAssets": true,
    "note": "手动刷新首页内容"
  }'

GET /api/admin/sync/jobs/:jobId

Returns the full SyncJobRecord for a single job, including the expanded steps array with per-table results. Authentication: admin_auth cookie required.

Path parameters

jobId
string
required
The job identifier returned when the job was created. Format: sync_{YYYYMMDDHHmmss}_{random6} (e.g. sync_20260430100000_ab12cd).

Response fields

The top-level object matches the SyncJobRecord shape described under GET /api/admin/sync/jobs. The steps array is always fully expanded here.
steps
SyncJobStep[]
required
One entry per table included in the job.

Example response

{
  "jobId": "sync_20260430100000_ab12cd",
  "kind": "sync-data",
  "status": "success",
  "tables": ["locations", "stories"],
  "effectiveTables": ["locations", "stories"],
  "dependencyMode": "read_local",
  "includeAssets": true,
  "continueOnTableError": false,
  "triggeredBy": "admin-ui",
  "note": "",
  "createdAt": "2026-04-30T10:00:00.000Z",
  "startedAt": "2026-04-30T10:00:00.200Z",
  "syncedAt": "2026-04-30T10:01:30.000Z",
  "finishedAt": "2026-04-30T10:01:30.000Z",
  "durationMs": 90000,
  "steps": [
    {
      "step": "locations",
      "status": "success",
      "startedAt": "2026-04-30T10:00:00.500Z",
      "finishedAt": "2026-04-30T10:00:45.000Z",
      "summary": {
        "totalRecords": 5,
        "successRecords": 5,
        "skippedRecords": 0,
        "failedRecords": 0,
        "filesWritten": ["src/config/locations.json"]
      },
      "warnings": [],
      "errors": []
    },
    {
      "step": "stories",
      "status": "success_with_warnings",
      "startedAt": "2026-04-30T10:00:45.000Z",
      "finishedAt": "2026-04-30T10:01:30.000Z",
      "summary": {
        "totalRecords": 7,
        "successRecords": 6,
        "skippedRecords": 0,
        "failedRecords": 1,
        "filesWritten": ["src/data/content.json"]
      },
      "warnings": ["记录 recXXX 缺少主图,已跳过图片处理"],
      "errors": []
    }
  ],
  "summary": {
    "totalRecords": 12,
    "successRecords": 11,
    "skippedRecords": 0,
    "failedRecords": 1,
    "locationCount": 5,
    "storyCount": 6,
    "filesWritten": [
      "src/config/locations.json",
      "src/data/content.json"
    ]
  },
  "warnings": ["记录 recXXX 缺少主图,已跳过图片处理"],
  "errors": []
}
404 Not Found — No job exists with the given ID.
{ "message": "Not found" }

curl example

curl -X GET https://himematsu.cn/api/admin/sync/jobs/sync_20260430100000_ab12cd \
  --cookie "admin_auth=<YOUR_SESSION_COOKIE>"

GET /api/admin/sync/jobs/:jobId/logs

Returns the tail of the raw execution log for a job. Up to the last 200 lines are returned. For a job that is still running, polling this endpoint lets you observe progress in real time. Authentication: admin_auth cookie required.

Path parameters

jobId
string
required
The job identifier. Format: sync_{YYYYMMDDHHmmss}_{random6}.

Response fields

lines
string[]
required
The last up-to-200 log lines for the job. Each line includes a timestamp and step prefix, e.g. "[2026-04-30T10:00:01.000Z] [locations] 获取飞书 token 成功". Empty array when no log file exists yet.
total
number
required
Total number of lines in the full log file. Useful for detecting whether lines were truncated. 0 when no log file exists.

Example responses

With log data:
{
  "lines": [
    "[2026-04-30T10:00:00.500Z] [locations] 开始同步...",
    "[2026-04-30T10:00:01.000Z] [locations] 获取飞书 token 成功",
    "[2026-04-30T10:00:45.000Z] [locations] 完成,写入 src/config/locations.json"
  ],
  "total": 156
}
No log file yet (job still queued):
{ "lines": [], "total": 0 }
404 Not Found — No job exists with the given ID.
{ "message": "Not found" }

curl example

curl -X GET https://himematsu.cn/api/admin/sync/jobs/sync_20260430100000_ab12cd/logs \
  --cookie "admin_auth=<YOUR_SESSION_COOKIE>"

Build docs developers (and LLMs) love