Get the board refresh status
const url = 'http://127.0.0.1:8765/api/sources/update';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url http://127.0.0.1:8765/api/sources/updateState of the last or running sources update. update is the running or last update’s snapshot (null when none ever ran): trigger is manual or auto (a background check), failures counts boards that did not answer by code, backoff names the providers the update left alone after a 429 (null: none; skipped and code rate_limited there: boards left for the next update), stores counts what the update wrote to the tag store and the text index (stores.tags.titles_backfilled: stored titles this update gave their first rules tag, a level, in its one-time catch-up; it is not the number of titles with a function), catch_up is that one-time work, done after boards settle and never before the first request: tags {companies_done, companies_total, pending} and text_index and search_index (each deferred until the boards are done, building, or null). index says whether a search can read the stored postings. background is the background refresh and the two stores: auto_refresh {enabled, source: default|setting|environment|settings_unreadable, active: a refresh thread runs in this server}; state is disabled, inactive, needs_first_update (run Update sources once: the background refresh never fills an empty index), running, waiting or due; in_progress and trigger describe the live update, last_update the last finished one; next_tick_at is null unless a check is scheduled; interval_seconds is null unless the checks run at a fixed interval (see refresh.schedule); tags counts stored titles and those still lacking a function; text.unchecked counts postings with no stored text, which a text search cannot match. snapshot is the downloaded metadata snapshot (titles, locations, links, title tags and board validators; never descriptions): enabled and setting_source (default|setting|environment|settings_unreadable) say whether it may be downloaded, as_of when the one in use was built (null: none imported), kind full or delta, last_result imported, up_to_date, skipped, refused or failed, last_reason why nothing was imported (offline, not_published, local_fresher, checked_recently, digest_mismatch, …), counts what the last import wrote. tags counts the stored titles (titles: every one has a level from the rules) by function, four numbers that add up to titles: tagged_by_rules and tagged_by_model have a function, model_other are titles a model looked at and could not place, awaiting_model have no function and no model has looked. Of those, awaiting_model_queued are the ones a model will tag under the settings in effect (the demand set; all of them with the backfill on) and awaiting_model_not_queued the ones it will not, for not_queued_reason (backfill_off, model_off, refresh_off, no_refresh_thread; null when none). tagging.state is what the model queue does now: running, idle, waiting_for_update (a manual update is live; the queue does not wait for a background check), failing (detail is the last error, retry_after the next try), off, paused (automatic updates are off) or inactive (no refresh thread); setting is the tagging setting in effect, models the model each lane asks (demand: titles the active profiles can reach; backfill: the rest; null when none is configured), queue the model queue of this server (null when it runs no refresh thread): its last drain and, per lane, calls, failures, last_error and retry_after (when a failed lane tries again). text_index counts postings a keyword search can check (postings_with_text) and cannot (unchecked). refresh is the strip’s line: enabled, state and trigger as in background, last_updated_at with last_updated_minutes_ago (null before the first update and while one runs), next_tick_at with next_tick_in_minutes (null unless a check is scheduled), and schedule: when the background checks run, kind times with the weekdays and weekends lists of local HH:MM times (the settings file’s sources.check_times, else eight on a weekday and two on a weekend day) or interval with interval_seconds; source default, setting or settings_unreadable; checks_today how many times today’s list holds. Reading this makes no request.
Responses
Section titled “Responses”Success.
object
Example
{ "background": { "auto_refresh": { "active": true, "enabled": true, "source": "default" }, "in_progress": false, "interval_seconds": null, "last_update": { "finished_at": "2026-10-01T12:00:00.000Z", "started_at": "2026-10-01T11:50:00.000Z", "status": "succeeded", "trigger": "manual", "update_id": "sources_update_1" }, "message": null, "next_tick_at": "2026-10-01T13:00:00.000Z", "state": "waiting", "tags": { "available": true, "lacking_function": 800, "titles": 5200, "with_function": 4400 }, "text": { "available": true, "postings": 9000, "unchecked": 2900, "with_text": 6100 }, "trigger": "manual" }, "index": { "companies_indexed": 120, "last_checked_at": "2026-10-01T12:00:00.000Z", "message": null, "needs_update": false, "stale_after_hours": 24, "status": "ready" }, "refresh": { "enabled": true, "in_progress": false, "last_updated_at": "2026-10-01T12:00:00.000Z", "last_updated_minutes_ago": 12, "next_tick_at": "2026-10-01T13:00:00.000Z", "next_tick_in_minutes": 48, "schedule": { "checks_today": 8, "interval_seconds": null, "kind": "times", "source": "default", "weekdays": [ "03:00", "07:00", "09:00", "11:00", "13:00", "15:00", "17:00", "19:00" ], "weekends": [ "09:00", "18:00" ] }, "state": "waiting", "trigger": "manual" }, "running": false, "schema_version": "scout-sources-update-status:1", "snapshot": { "as_of": "2026-10-01T06:00:00Z", "counts": { "boards": 120, "boards_kept_local": 0, "boards_removed": 0, "postings": 9000, "postings_removed": 0, "tags": 5200 }, "enabled": true, "imported_at": "2026-10-01T11:49:00.000Z", "kind": "full", "last_attempt_at": "2026-10-01T11:49:00.000Z", "last_message": "Imported the snapshot as of 2026-10-01T06:00:00Z.", "last_reason": null, "last_result": "imported", "manifest_url": "https://github.com/karthik446/gigai/releases/download/scout-snapshot/manifest.json", "setting_source": "default", "source": "https://github.com/karthik446/gigai/releases/download/scout-snapshot/manifest.json" }, "tags": { "available": true, "awaiting_model": 150, "awaiting_model_not_queued": 50, "awaiting_model_queued": 100, "model_other": 50, "models": { "backfill": "ollama_local", "demand": "ollama_local:llama3.1" }, "not_queued_reason": "backfill_off", "queue": { "backfill": { "batches": 0, "calls": 0, "consecutive_failures": 0, "failures": 0, "last_error": null, "last_error_at": null, "model": null, "rejected": 0, "retry_after": null, "tagged": 0 }, "batch_size": 50, "batches_per_tick": 4, "demand": { "batches": 12, "calls": 12, "consecutive_failures": 0, "failures": 0, "last_error": null, "last_error_at": null, "model": "ollama_local:llama3.1", "rejected": 0, "retry_after": null, "tagged": 600 }, "last_drain": { "batches": 4, "calls": 4, "rejected": 0, "state": "drained", "tagged": 200 }, "last_drain_at": "2026-10-01T12:01:00Z", "parked": 0, "prompt_version": "tag-v2", "setting": { "backfill_enabled": false, "model_enabled": true, "source": "default", "tag_backfill_model": "configured" }, "state": "drained" }, "setting": { "backfill_enabled": false, "model_enabled": true, "source": "default", "tag_backfill_model": "configured" }, "tagged_by_model": 600, "tagged_by_rules": 4400, "tagging": { "detail": null, "model": null, "retry_after": null, "state": "running" }, "titles": 5200 }, "text_index": { "available": true, "postings_with_text": 6100, "unchecked": 2900 }, "update": null}Forbidden / forbidden_origin: loopback peer and Host 127.0.0.1:<port> or localhost:<port> only (Origin too on writes).
object
object
Examplegenerated
{ "error": { "allowed_keys": [ "example" ], "code": "example", "message": "example" }}