FEMA Public Assistance Funding & Obligation Monitor
Under maintenancePricing
Pay per usage
FEMA Public Assistance Funding & Obligation Monitor
Under maintenanceMonitor official OpenFEMA Public Assistance funded projects for disaster recovery funding changes. Get decision-ready obligation increases, deobligations, mitigation, process-step, and status events instead of raw FEMA API rows.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Blake Panter
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Track FEMA Public Assistance disaster recovery funding without rebuilding OpenFEMA snapshots yourself. This Actor monitors the official OpenFEMA Public Assistance Funded Projects Details feed and turns funded-project updates into decision-ready events for obligation increases, deobligations, mitigation amounts, process steps, and project status.
Run it on a schedule to compare each project with its previous normalized snapshot and emit only the configured changes. This is a funding-monitoring product—not an open-bid feed—and it preserves FEMA's Public Assistance terminology rather than labeling every obligation a grant.
Built for
- Disaster recovery consultants tracking funded projects and obligation changes
- State, local, tribal, and territorial emergency management teams overseeing Public Assistance recovery
- Infrastructure, resilience, and government affairs teams monitoring disaster recovery funding
- Analysts and data teams that need structured OpenFEMA change events for alerts, reporting, or downstream workflows
Why this instead of a raw FEMA scraper
- Change detection across runs: see what changed instead of repeatedly receiving the same OpenFEMA rows.
- Decision-ready funding signals: get typed obligation increases, deobligations, mitigation changes, process-step changes, and status changes with previous, current, and delta values.
- Traceable, automation-ready output: every event includes project and geography context, official-source evidence, detection time, and a stable
dedupeKey. - Reliable recurring delivery: persistent state and a retryable pending outbox protect unpaid change events when a run is interrupted.
Signals
initial-obligation— first observation in the selected baseline (opt in withincludeInitial)obligation-increase— current total obligated increaseddeobligation— current total obligated decreasedmitigation-change— mitigation amount changedprocess-step-change— FEMA project processing step changedstatus-change— project status changedunchanged— no configured signal type met its emission criteria; changes excluded by a non-emptysignalTypesallowlist count as unchanged (opt in withemitUnchanged)
Every result includes project identity and geography, previous/current/delta monetary values, old/new status and process fields, an evidence description, official source URL, detection time, and a stable dedupeKey. Results are charged as the PPE event fema-project-funding-change.
Example input
{"states": ["LA", "NC"],"disasterNumbers": [],"damageCategoryCodes": ["E"],"minimumTotalObligated": 100000,"minimumAbsoluteChange": 1000,"signalTypes": ["obligation-increase", "deobligation", "status-change"],"includeInitial": false,"emitUnchanged": false,"maxSourceRecords": 5000,"maxItems": 100,"pageSize": 500,"requestTimeoutSecs": 30,"baselineStoreName": "fema-pa-obligation-monitor-baseline"}
Stateful behavior
The Actor opens the deliberately named KV store and saves one legal key such as project-552422 per normalized project. Each record contains the current snapshot plus a per-signal pending outbox and bounded acknowledgement history. The pending outbox is capped at 256 signals per project. Whenever a project already has pending signals, the Actor emits and acknowledges all of that older work before staging the newly fetched observation, even when the outbox has spare capacity. If a failed push, maxItems, or a PPE charge limit interrupts that drain, the newly fetched snapshot remains unstaged and retryable; the Actor neither evicts pending work nor advances the snapshot. One observation can atomically stage at most four signals, and the internal outbox capacity is never allowed below that batch size, preventing capacity deadlock. The Actor persists a newly accepted snapshot and all of its payable signals before any dataset/PPE emission, then acknowledges each signal after its push succeeds. Delivery is at least once, not exactly once: if the dataset/PPE push succeeds but acknowledgement persistence fails, that event can be delivered and charged again on retry. Consumers should make processing idempotent by deduplicating on the stable dedupeKey. Unpaid signals remain pending for a later run; signals whose acknowledgements were durably saved are not pushed again. Use the same store name for recurring runs; use a fresh name to intentionally re-baseline. Existing snapshot-only records are migrated when next observed.
Project/geography/category and minimumTotalObligated filters are applied before baseline comparison and charging. minimumAbsoluteChange is measured against the immediately previous stored observation; sub-threshold changes are stored and do not accumulate across runs. maxItems is checked before another project is persisted, and both maxItems and PPE charge limits stop output without discarding already-pending signals. maxSourceRecords bounds source retrieval.
Coverage and caveats
- Source:
GET https://www.fema.gov/api/open/v2/PublicAssistanceFundedProjectsDetails, using documented$top/$skippagination and deterministicgmProjectId ascordering. - Every response body is streamed with a strict 10 MiB UTF-8 byte cap, even when
Content-Lengthis absent or incorrect. Each page has a monotonic wall-time deadline through UTF-8 decoding and JSON parsing: async body reads are aborted, while synchronous decode/parse cannot be preempted but the page is rejected if either stage returns after the deadline. - This monitors records observed within the bounded source window. Narrow filters are useful, but filtering is local and does not expand the source window.
- A project absent from a later bounded response is not emitted as resolved, closed, or deobligated. Only explicit fields in a returned record produce signals.
- Null or blank monetary fields remain
null, never synthetic zeroes. A null-to-number transition is not classified as a monetary increase because there is no numeric prior amount. detectedAtis the Actor observation time; FEMA'slastRefreshand obligation dates are included separately.- FEMA may revise, delay, or correct source data. Verify consequential decisions against the linked official record.
- Multiple simultaneous changes can emit multiple events for one project, each with its own signal type and dedupe key.
Local development
bun installbun testbun run typechecknpx --yes apify-cli validate-schemaapify actor:run
For a first smoke run, set includeInitial: true, a fresh baselineStoreName, and small maxSourceRecords/maxItems. Repeat with the same baseline and includeInitial: false to verify unchanged suppression.