Strait of Hormuz Tanker Flow Recovery Index avatar

Strait of Hormuz Tanker Flow Recovery Index

Pricing

from $0.0425 / delivered hormuz recovery report

Go to Apify Store
Strait of Hormuz Tanker Flow Recovery Index

Strait of Hormuz Tanker Flow Recovery Index

Compare aggregate commercial-tanker observations across three fixed Strait of Hormuz zones with seven- and thirty-observation baselines. Get deterministic recovery labels, freshness, confidence, gaps, and a human-review action without exposing raw identities or positions.

Pricing

from $0.0425 / delivered hormuz recovery report

Rating

0.0

(0)

Developer

Tim Zinin

Tim Zinin

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

4 days ago

Last modified

Share

Strait of Hormuz Tanker Flow Recovery: baseline, recovery index, evidence coverage, and review

Strait of Hormuz Tanker Flow Recovery: bounded observations to a reviewable recovery assessment

What this Actor does

This Actor turns repeated commercial-tanker observations in three fixed Strait of Hormuz zones into a small, machine-readable decision report. It compares the current aggregate with seven-observation and thirty-observation baselines and emits deterministic signals:

  • FLOW_COLLAPSE: current flow is at or below 50% of the selected baseline.
  • RECOVERY_STARTED: a prior flow ratio was at or below 0.60 and the current ratio reached at least 0.70.
  • RECOVERY_STALLED: a recovery signal was previously observed but the ratio fell below 0.70.
  • THROUGHPUT_SPIKE: current flow is at least 1.50 times the selected baseline.
  • DATA_STALE: source quality is low or the source is partial.

It is an aggregate monitor, not a vessel search product. It does not return vessel names, MMSI, IMO numbers, coordinates, routes, military information, sanctions conclusions or a geopolitical risk score.

Key features

  • Monitors three fixed commercial-tanker zones: western approach, transit corridor and eastern approach.
  • Produces deterministic flow-collapse, recovery, stalled-recovery and throughput-spike signals.
  • Uses seven-observation and thirty-observation baselines under a same-watch lock.
  • Rejects partial, stale, malformed or empty live samples before paid delivery or state advancement.
  • Stores only a version-2 minimal private snapshot: HMAC-derived identity, fixed zone, movement class and source/observation timestamps. Exact provider speed and navigation status are used only ephemerally while calculating the aggregate and are never returned, logged or persisted.
  • Provides closed schemas for Apify API, Tasks, schedules, MCP clients and automation workflows.

How to run

  1. Run the default demo input to inspect one synthetic aggregate Dataset row. The automatic start event still applies, but demo does not charge result-found.
  2. For live monitoring, select datalastic and provide your Datalastic API key in the secret input field.
  3. Keep the same watchId across scheduled runs so confirmed live reports can build a compatible baseline.
  4. Read the aggregate report from the Dataset and the authoritative delivery/state envelope from OUTPUT.

Input

Example input

{
"schemaVersion": "1.0",
"requestId": "auto",
"watchId": "hormuz-tanker-flow",
"sourceMode": "datalastic",
"datalasticApiKey": "provided as a secret",
"identitySalt": "optional stable 32+ character secret",
"maxVessels": 100,
"maxProviderRequests": 4,
"maxTotalChargeUsd": 0.055
}

watchId must remain stable to build history. At the input boundary, externally supplied requestId and watchId values are replaced by deterministic domain-separated one-way digests before validation, lock naming, output, Dataset, KVS or logging; this keeps repeated scheduled calls stable without retaining a pasted credential. sourceMode=demo writes one synthetic Dataset row after the automatic $0.005 start charge and never charges the $0.05 result-found event. sourceMode=datalastic requires the user's own Datalastic API key. The key is sent only in the provider request header and is never written to output, logs or state. identitySalt is optional; keep the same 32+ character secret while rotating the provider key. A changed identity salt fails closed as incompatible before paid delivery.

Coordinates are not configurable. The Actor uses only the approved western approach, transit corridor and eastern approach zones. Provider usage is capped at exactly four actual attempts/pages: one Datalastic /stat validation attempt plus one bounded page for each fixed zone. maxVessels is a global cap across all three zones; a response that needs more rows or pagination is diagnostic and ineligible for paid delivery.

Output

The Actor writes an authoritative envelope to OUTPUT. A useful live run, including a bootstrap report, writes exactly one report with result-found. Demo writes one free Dataset row after the automatic start charge and does not charge result-found. A budget-blocked run is uncharged; its terminal UNCHARGED intent replays the same result without pricing, provider, Dataset, charge or state effects. A source error is uncharged; an ambiguous delivery may already have charged result-found, is reported as unknown, is not retried, and does not advance state. The delivery block never exposes a provider receipt identifier: it contains only fixed delivery counts and a safe replay-sha256:... identifier derived from a versioned one-way receipt digest.

The public report contains only aggregates:

Example output

{
"schemaVersion": "1.0",
"actor": "strait-of-hormuz-tanker-flow-recovery",
"reportId": "sha256:bb8beb4bfeb750d16a517f0499650a931216ca0a0ba92052750c0e12f7c73019",
"watchId": "hormuz-tanker-flow",
"region": "strait-of-hormuz",
"status": "bootstrap",
"observedAt": "2026-08-08T00:00:00.000Z",
"metrics": {
"tankerCount": 3,
"zoneCounts": { "western_approach": 1, "transit_corridor": 1, "eastern_approach": 1 },
"movement": { "moving": 2, "slow": 0, "stopped": 1, "unknown": 0 },
"transitions": { "entries": null, "exits": null, "crossZoneTransitions": null, "nullReasons": { "entries": "no_prior_observation", "exits": "no_prior_observation", "crossZoneTransitions": "no_prior_observation" } }
},
"baseline": {
"observationCount": 0,
"minimumObservations": 7,
"sevenObservationMean": null,
"thirtyObservationMean": null,
"selectedWindow": null,
"ratio": null,
"percentDelta": null,
"status": "bootstrap",
"previousReportId": null,
"coverage": { "observations": 0, "minimum": 7, "preferred": 30 },
"nullReasons": { "sevenObservationMean": "insufficient_observations", "thirtyObservationMean": "insufficient_observations", "selectedWindow": "insufficient_observations", "ratio": "insufficient_observations", "percentDelta": "insufficient_observations" }
},
"signals": [],
"confidence": "high",
"dataQuality": { "sourceOk": true, "partial": false, "freshnessSeconds": 0, "sourceFreshnessSeconds": 0, "sampleCount": 3, "freshnessKnownCount": 3, "freshnessCoverage": 1, "expectedCount": 3, "score": 100, "confidence": "high", "coverage": { "sample": 3, "expected": 3, "freshness": 3 }, "nullReasons": { "freshnessSeconds": null, "sourceFreshnessSeconds": null, "expectedCount": null }, "limitations": ["Complete paid delivery requires all fixed zones, a non-empty aggregate and 100% timestamp coverage."] },
"sources": [{ "mode": "demo", "provider": "synthetic_fixture", "endpoint": "synthetic_fixture", "calls": 0, "license": "synthetic", "retrievedAt": "2026-08-08T00:00:00.000Z" }],
"limitations": ["Aggregated commercial-tanker observations only.", "No military, sanctions, ownership, route or tactical conclusions.", "A null baseline metric always carries a closed reason in baseline.nullReasons."],
"actions": [{ "actionId": "sha256:801d216247d7d6e0e83d902e41bb1fe3755bf304ca12b2cd6bf341626dcf96ab", "review_required": true, "not_sent": true, "instruction": "Review the evidence and source freshness before making an operational decision." }]
}

The first seven observations are honest bootstrap reports. On the first observation, transition counts are null with no_prior_observation; they become numeric only after a prior delivered snapshot exists. The seven-observation baseline becomes available once seven prior observations exist, so the next run can be compared against it; the thirty-observation baseline is preferred after thirty prior observations. Hashed identities and snapshots are private state only.

Pricing

The Actor uses pay-per-event pricing:

EventPrice
apify-actor-start$0.005
result-found$0.05 per delivered report
Default dataset item$0

Discount tiers are 0%, 5%, 10%, 15%, 18% and 20%. At the base tier, one useful live report costs $0.055 including the $0.005 start event; provider BYOK costs are separate. The Actor checks maxTotalChargeUsd before the provider call and before delivery. An ambiguous delivery may already have charged result-found; its charge and delivery status are reported as unknown and it is never retried automatically.

Data quality

Every report includes provider mode, retrieval time, sample count, timestamp coverage, maximum source freshness and a confidence level. Every source retrievedAt is required to be no later than the report's observedAt, including persisted intent and replay validation. A live sample is eligible only when all three fixed zone responses are complete, every provider row is structurally valid, every accepted tanker has a valid source timestamp, the maximum freshness is at most 10,800 seconds, timestamp coverage is 100%, and the aggregate is nonempty. Valid circle-edge rows outside the Actor's stricter internal aggregate geofences are intentionally excluded and are not treated as malformed. Unknown timestamps, future timestamps beyond 300 seconds of clock skew, stale rows, mixed-zone failures, malformed rows and zero accepted samples produce a diagnostic partial report in OUTPUT; they do not emit result-found and do not advance state.

All public errors use a closed error code and an allowlisted stage:* label. Backend exception prose is never copied to OUTPUT, KVS, or logs, including when a provider error contains an MMSI or an old API key. State and delivery-intent records are recursively validated before every write and replay; state version 1 is incompatible and requires a new monitoring series or explicit migration.

Baselines advance only after a confirmed paid delivery and compatible state save. State includes an exact contract for Actor ID, schema version, fixed-zone version and a non-reversible source-mode plus identity-epoch digest. A same-watch Request Queue lock prevents overlapping updates for the same watchId; backend errors are terminal and are never reported as normal contention. Every nullable baseline decision metric carries a closed baseline.nullReasons entry and its observation coverage. The private intent ledger uses a versioned closed receipt and a receipt-bound intent digest; it rejects poisoned replay records before any source call, charge, Dataset write, state write or public output.

Datalastic is an optional BYOK source. Users are responsible for their provider plan and permitted use of provider data. This Actor publishes derived aggregates, not raw AIS records.

Limitations

  • This is a commercial-tanker aggregate, not a complete maritime picture.
  • A seven-observation baseline is directional; thirty observations are preferred.
  • It does not predict future events. This report is not for navigation and does not provide tactical guidance.
  • It does not identify vessels or infer military activity, sanctions status, ownership or intent.
  • sourceMode=demo is synthetic and must not be used for operational decisions.
  • The Actor does not scrape Panama Canal Authority, PortWatch or other restricted dashboards.

What the Actor gives you

The product answers one deliberately narrow question: how does the current aggregate commercial-tanker observation compare with the same watch's accepted history? The answer is an evidence record with a baseline ratio, deterministic recovery labels, source coverage, confidence, limitations, and a human-review action.

Use it to monitor an aggregate series, create a repeatable review trigger, or attach flow context to a separate commercial analysis. It is especially useful when a team needs to distinguish “we observed more tankers than in the recent accepted baseline” from stronger claims that the Actor cannot support.

It is not a real-time navigation product, an intelligence feed, a sanctions screen, a military tracker, an ownership database, or a prediction of supply, price, safety, or geopolitical events. It intentionally withholds raw identities and positions and never recommends a tactical route.

Analytical model

The live model observes three fixed areas: western approach, transit corridor, and eastern approach. Every accepted identity belongs to one aggregate snapshot. The public report exposes zone totals, movement-class totals, and—after a compatible prior observation—aggregate entries, exits, and cross-zone transitions.

The baseline is observation-based, not calendar-based. Seven accepted prior observations unlock the first comparison window; thirty accepted prior observations unlock the preferred window. If a schedule runs irregularly, the baseline reflects those accepted observation times rather than evenly spaced days. Review observedAt, history coverage, and your Task schedule before interpreting a ratio as a time trend.

FieldInterpretationBoundary
metrics.tankerCountSafe unique commercial-tanker identities in the fixed aggregate zones.Not complete regional traffic or an official transit count.
metrics.zoneCountsAggregate distribution across the three fixed zones.Not individual routes or intended direction.
metrics.movementDeterministic speed-based classes used in the accepted snapshot.Not navigation status, safety, or intent.
metrics.transitionsAggregate changes against one compatible prior delivered snapshot.Null on the first observation; not a voyage history.
baseline.ratioCurrent aggregate divided by the selected accepted-history mean.Not a forecast or causal estimate.
confidenceContract-owned evidence-quality class.Not probability that a market outcome will happen.

Recovery labels

  • FLOW_COLLAPSE means the current aggregate is no more than half of the selected baseline.
  • RECOVERY_STARTED means a prior ratio was no more than 0.60 and the current ratio reached at least 0.70.
  • RECOVERY_STALLED means a prior recovery signal existed but the current ratio fell below 0.70.
  • THROUGHPUT_SPIKE means the current aggregate is at least 1.50 times the selected baseline.
  • DATA_STALE means the evidence contract failed and paid delivery is withheld.

These labels describe transitions within this Actor's accepted series. “Recovery” does not mean that every commercial, operational, environmental, or security condition recovered.

Review workflow

  1. Confirm the platform run and exact build identity.
  2. Read status, dataQuality.sourceOk, dataQuality.partial, freshness, and coverage before any signal.
  3. Check whether the report is still bootstrap and whether the seven- or thirty-observation window is selected.
  4. Preserve every null value with its nullReasons entry.
  5. Compare zone distribution and movement classes with the total ratio.
  6. Inspect sources, limitations, and the explicit review action.
  7. Add independently authorized commercial context; do not infer it from missing fields.
  8. Record the reviewer, the decision, and the evidence identifiers outside the Actor.

The generated actions item always requires review and is marked not_sent: true. The Actor does not alert an external recipient or execute the action. This makes the output suitable for a controlled queue in which another system can request review without pretending the review already happened.

Source completeness and freshness

A live report can be useful only when all three fixed zone calls are complete, all raw rows needed for aggregation are structurally valid, at least one safe tanker is accepted, source timestamp coverage is 100%, no accepted timestamp is more than five minutes in the future, and maximum freshness is no more than 10,800 seconds.

Structurally valid circle-edge rows outside the Actor's stricter internal geofence may be excluded. Provider count and accepted count can therefore differ without implying malformed data. The report exposes coverage so that this distinction is reviewable.

Missing timestamps, partial pages, pagination requirements beyond the one bounded page per zone, malformed rows, mixed success/error zones, empty accepted aggregates, stale evidence, and future timestamps are fail-closed. They produce diagnostic OUTPUT, no useful paid Dataset row, and no baseline advancement.

Billing and settlement

The Dataset is the aggregate report channel. OUTPUT is the authoritative run, delivery, and state channel. A useful live report—including a bootstrap—uses one linked result-found push. Demo uses an ordinary unpriced Dataset push and still purchases the automatic start event.

Terminal factDataset factBilling factBaseline fact
Demo successOne synthetic rowNo result eventNo live baseline advance
Confirmed live resultOne aggregate rowExactly one result eventSave attempted only after confirmation
Source/quality refusalNo useful paid rowResult not attemptedNot advanced
Definitive budget refusalNo useful paid rowConfirmed zero resultNot advanced; refusal is replayable
Ambiguous push or countRow may existSettlement unknownNot advanced
State write failure after deliveryPaid row remains knownOne result remains knownPersistence failed/unknown
Lock release uncertaintyPreserves known rowPreserves known settlementPreserves known save; lock is uncertain

Do not blindly rerun an ambiguous, state-write, or lock-release outcome. Inspect the existing platform run, Dataset, KVS OUTPUT, and charged-event counts. The no-retry rule prevents compounding an unknown result, but a manually created new run is still a new start purchase and can become a new result purchase.

API, Tasks, schedules, and MCP

Demo is the safest integration test:

curl -X POST \
"https://api.apify.com/v2/acts/zinin~strait-of-hormuz-tanker-flow-recovery/runs?token=$APIFY_TOKEN" \
-H "content-type: application/json" \
-d '{
"schemaVersion":"1.0",
"requestId":"auto",
"watchId":"hormuz-tanker-flow",
"sourceMode":"demo",
"maxVessels":100,
"maxProviderRequests":4,
"maxTotalChargeUsd":0.055
}'

For a live Task, change sourceMode to datalastic and store datalasticApiKey in the secret input field. Keep watchId stable for one series. If you use identitySalt, keep it stable across provider-key rotations. A changed identity epoch intentionally fails closed because repeated-observation continuity can no longer be proven.

Schedules should not overlap for the same watch. The lock is a safety net, not a scheduling strategy. Choose an interval that fits your provider plan, source freshness needs, and desired observation-based baseline.

An MCP or automation client should wait for the Apify run to become terminal and then validate OUTPUT, the Dataset report, reportId, source/quality fields, and platform charged-event counts. It should route partial or uncertain outcomes to manual review and must not translate actions into autonomous navigation or operational commands.

Privacy, source rights, and retention

Datalastic mode uses a buyer-owned provider key. You are responsible for a plan and permissions that cover API access, transformation, retention, and downstream use. The Actor reduces exposure by publishing aggregates only and by keeping raw source identity, position, route, provider prose, speed, and navigation status out of public storage.

Private state uses HMAC-derived identity values only for bounded continuity. Cryptographic pseudonyms are a security and minimization control; they are not a universal legal determination that data is anonymous. Do not attempt to reverse, enrich, or join the aggregates to identify vessels, owners, crews, cargo, sanctions exposure, or military activity.

Define a legitimate purpose, authorize users, and set retention for Tasks, named state stores, request ledgers, Datasets, KVS records, webhooks, and exports. Delete obsolete watches and downstream copies. Never place the provider key or identity salt in requestId, watchId, a URL, a log, or a report field.

Production checklist

Before a live schedule:

  • verify demo integration and zero result-event behavior;
  • confirm current tier pricing and a cap that covers start plus one result;
  • verify the provider account and downstream-use rights;
  • choose a stable watch and, when needed, a stable identity salt;
  • document the observation cadence and how it affects the baseline;
  • preserve null/reason pairs and source coverage in downstream storage;
  • prohibit automated retries for ambiguous or post-delivery failures;
  • assign a reviewer for recovery, collapse, spike, stale, and partial states;
  • retain run ID, build ID, report ID, Dataset ID, KVS ID, and event counts;
  • define deletion and state-migration procedures.

Troubleshooting

SymptomLikely causeNext step
bootstrapFewer than seven accepted prior observations.Continue the same compatible watch; do not invent a baseline.
Null transitionsNo compatible prior delivered snapshot.Preserve no_prior_observation; collect the next accepted run.
DATA_STALEMissing/old/future timestamps, partial zone, malformed row, or empty aggregate.Inspect quality coverage and closed errors; do not read zero as recovery.
watch_busyAnother same-watch run owns the lock.Wait for settlement and remove schedule overlap.
request_replay_blockedIntent or state cannot be safely authenticated/reconciled.Investigate the original run and storage before a new request.
Incompatible stateSource mode, fixed zones, schema, or identity epoch differs.Start a reviewed new series or perform an explicit migration.
Budget refusalCap cannot fund the current start plus result price.Review tier and cap; the refused result remains uncharged.

Acceptance criteria

Treat a live output as an accepted report only when the exact candidate/build is known, the platform run is terminal and successful, OUTPUT is present and schema-valid, the Dataset contains the same one report, reportId recomputes, all three zones and timestamp coverage are complete, evidence is fresh, dataQuality.partial is false, the source contains no forbidden raw identity fields, and the platform counters show one start plus exactly one new result-found event. Demo acceptance instead requires one synthetic row, zero result events, and no baseline advance.

ActorWhy use it in the same workflow
Singapore Bunker & Tanker DivergenceCompare Hormuz flow recovery with Singapore bunker demand and tanker pressure.
Panama Canal Queue & Transit ImbalanceAdd a second global shipping bottleneck to the same monitoring dashboard.
Live Price OracleAttach current commodity or freight-price context to a flow signal.
Counterparty Risk RollupAdd structured counterparty context before a human reviews a commercial decision.

FAQ

Why did a live run return no paid Dataset row?

The Actor refuses paid delivery when any zone is partial, a provider error is present, source timestamp coverage is incomplete, the newest accepted observation is older than three hours, rows are malformed, or the aggregate is empty. Check OUTPUT.errors and the diagnostic report's dataQuality fields.

Why is an older baseline rejected as incompatible?

The state contract prevents observations collected under a different Actor schema, zone definition or source mode from being mixed silently. Use a new watchId when intentionally starting a new monitoring series.

Is the Datalastic key stored with vessel identities?

No. The provider key is used only for the Datalastic request. The optional identity salt is used only in memory for HMAC identity derivation and its non-reversible epoch fingerprint; neither secret is returned or persisted. A provider-key rotation with the same identity salt preserves identities. A salt change requires a new watchId or explicit state migration.

What happens if lock release fails after a successful paid report?

The known delivery, billing count and saved baseline remain truthful. OUTPUT.delivery.lockRelease records the separate release uncertainty so the next run can be investigated without rewriting confirmed payment as unknown.

MCP and automation

The closed input/output schemas are designed for MCP clients and scheduled workflows. A machine can call the Actor with a stable watchId, inspect status, signals, dataQuality and baseline, and decide whether human review is required. This Actor never sends external alerts or executes an operational action by itself.