BLS Observation Revision Ledger avatar

BLS Observation Revision Ledger

Pricing

from $3.00 / 1,000 series checkeds

Go to Apify Store
BLS Observation Revision Ledger

BLS Observation Revision Ledger

Track exact revisions to official U.S. BLS time-series observations and footnotes. Establish a persistent baseline, detect value and footnote changes, and emit deterministic before-and-after evidence with hashes and attribution.

Pricing

from $3.00 / 1,000 series checkeds

Rating

0.0

(0)

Developer

Flintglade

Flintglade

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Categories

Share

BLS Observation Revision Ledger remembers an exact official BLS Public Data API v1 query and emits one deterministic before/after report when a previously captured observation value or footnote changes.

This is not another BLS data scraper. It does not calculate growth, forecast, interpret economic conditions, or provide investment, employment, policy, or economic advice.

Each successfully retrieved series produces exactly one dataset row and one paid event:

OutcomePPE eventPrice
First baseline or no material changeseries-checked$0.003
One complete report containing every bounded change for the seriesseries-revision-report$0.020

Apify automatically charges the synthetic apify-actor-start event at $0.00005. This Actor never charges that event in code. The pricing definition intentionally omits apify-default-dataset-item, so a row is not double-charged.

A failed, malformed, partial, rejected, or spend-limit-skipped series produces no dataset row, no paid event, and no baseline change. The Actor stops before the next series when its event cannot fit within the run's maximum total charge.

First-run and revision semantics

The first successful run for a watchId establishes a baseline. It returns status: "baseline-established", an empty changes array, and makes no revision claim.

Later runs use the exact observation key (seriesId, year, period):

  • added: the key exists only in the current response;
  • removed: the key exists only in the prior baseline;
  • value: the exact trimmed source value changed;
  • footnote: the canonical exact-text footnote set changed;
  • value-and-footnote: both changed, represented by one change rather than duplicate records.

Every observation, change, series, query, and result has a deterministic SHA-256 hash. Retrieval timestamps are excluded from observation, series, query, and result hashes. Source observations and footnotes are projected onto an allowlist; values remain strings and are never coerced to floating point.

The query signature covers the normalized sorted series IDs, exact year window, and schema version. Reusing a watchId with a different signature fails before a BLS request unless resetBaseline is true. A reset is itself committed only after a paid result row is written successfully.

Input

{
"seriesIds": ["CUUR0000SA0"],
"startYear": 2024,
"endYear": 2025,
"watchId": "bls-cpi-baseline",
"resetBaseline": false,
"requestTimeoutSeconds": 20,
"maxRetries": 3
}
  • seriesIds: 1–25 unique official IDs. IDs are trimmed, sorted, and must contain only uppercase ASCII letters, digits, hyphen, or underscore, up to 64 characters.
  • startYear, endYear: four-digit integers forming an inclusive window of at most ten years.
  • watchId: 1–64 ASCII letters, digits, hyphen, or underscore. It scopes one persistent atomic baseline.
  • resetBaseline: explicitly replace a watch, including when its exact query changes.
  • requestTimeoutSeconds: 5–30, default 20.
  • maxRetries: 0–4, default 3.

Unknown keys are rejected. The Actor does not accept a URL, API key, token, proxy, header, cookie, webhook, account, file, credential, or code.

Source and bounds

The only network origin is an HTTPS POST to:

https://api.bls.gov/publicAPI/v1/timeseries/data/

The body contains only the documented seriesid, startyear, and endyear fields. The Actor makes one bounded batch request, except for retries of network failures, HTTP 408, 429, or 5xx responses. Request starts are at least one second apart; Retry-After is honored up to 30 seconds; each attempt has a timeout; and the response body is capped at 8 MiB.

A BLS-success status and exactly one unambiguous, complete series object are required. A missing, duplicate, empty, or malformed series is isolated as partial while complete peer series may proceed. Logs contain stable codes and bounded counts, never raw payloads.

BLS v1 supports at most 25 series and ten years and can lag a published release by one day. It returns observations and footnotes, not full series metadata.

Output

Each paid row includes:

  • schema version, watch ID, series ID, and exact year window;
  • baseline, unchanged, or revised status;
  • prior/current series hashes and observation count;
  • the complete ordered change set for a revised series;
  • the one charged event name;
  • official source name and endpoint, UTC retrieval timestamp and date;
  • BLS attribution, required derived-analysis disclaimer, and non-affiliation notice;
  • a deterministic recordHash that excludes retrieval/run metadata.

No raw response, HTTP header, IP address, host/user name, environment value, local path, credential, token, or contact data is stored in a result.

Persistent-state safety

The named Apify key-value store flintglade-bls-revision-ledger persists across Actor runs. One record per watchId holds the complete query signature and all committed series snapshots. A run stages one complete candidate watch in memory and replaces that record exactly once. The order is deliberate:

  1. validate and canonicalize the bounded source batch;
  2. build each complete series result against the prior committed watch;
  3. verify event capacity and write each admitted row with its one PPE event;
  4. stage admitted snapshots while retaining prior snapshots for partial, rejected, or spend-limit-skipped series;
  5. atomically replace the watch record once after the output loop finishes cleanly.

If output or charging is interrupted, the previous complete watch remains. A clean spend stop commits only admitted series and keeps skipped series unchanged. If final persistence fails after paid rows, the previous complete watch remains; the run fails with a stable code rather than pretending the new state was committed.

Do not overlap runs that use the same watchId. Apify key-value records provide atomic replacement but not a cross-run compare-and-swap lock.

Local verification

Requirements: Node.js 24+, pnpm 11.7.0, and Docker for the container gate.

pnpm install --frozen-lockfile
pnpm gate:offline
pnpm smoke:live
pnpm smoke:local
docker build --tag bls-observation-revision-ledger:rc .
pnpm smoke:docker
  • gate:offline runs formatting, lint, type checking, 58+ unit/integration assertions, schema checks, compilation, the deterministic two-run fixture, and a production dependency audit.
  • smoke:live makes two bounded requests for one known series against the fixed official endpoint and prints only hashes, counts, statuses, and event names.
  • smoke:local runs the compiled Actor twice with a temporary local Apify store and verifies baseline-established then unchanged without retaining raw responses.
  • smoke:docker performs the same live two-run check through the previously built image. Set BLS_LEDGER_IMAGE when the tag is not bls-observation-revision-ledger:rc.

The live commands use the public BLS service and may fail when that external service is unavailable. They never deploy or publish the Actor.

Attribution, terms, and limitations

Source: U.S. Bureau of Labor Statistics Public Data API. Every result states its UTC retrieval date.

BLS.gov cannot vouch for the data or analyses derived from these data after the data have been retrieved from BLS.gov.

This unofficial derived-data monitor is not affiliated with or endorsed by the U.S. Bureau of Labor Statistics. It does not use a BLS logo and must not be presented as an official BLS product. Source text is preserved; the ledger must not be used to falsely represent modified content as BLS content.

Primary policies:

Release status

This repository is a release candidate. Public Store publication remains blocked until the reviewed commit is reconciled byte-for-byte with the deployed build and a logged-out Store check confirms Limited permissions, hidden source files, Standby off, publisher identity, support address, event prices, platform usage included, and no default dataset-item event.

Support: support@flintglade.com