Panama Canal Queue & Transit Imbalance Monitor
Pricing
from $0.0425 / delivered panama approach report
Panama Canal Queue & Transit Imbalance Monitor
Compare aggregate commercial-vessel pressure across two fixed Panama Canal approach zones. Get side imbalance, movement, observed dwell, baseline change, freshness, confidence, gaps, and a human review action without exposing raw vessel identities or claiming official Canal queues.
Pricing
from $0.0425 / delivered panama approach report
Rating
0.0
(0)
Developer
Tim Zinin
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share


What this Actor does
This Actor converts bounded commercial AIS observations from the fixed Atlantic and Pacific Panama Canal approach zones into one aggregate queue-pressure report. It compares accepted observations with the same watch's private history and reports side imbalance, observed movement, repeated-observation dwell, flow changes, freshness, and data quality.
This is not a Panama Canal Authority feed and not for navigation. It does not claim official Canal queues, booking slots, transit appointments, or official wait times.
Key features
- Fixed Panama approach zones with no user-supplied coordinates or URLs.
- Aggregate-only output with no MMSI, IMO, vessel names, coordinates, routes, or raw AIS rows.
- Conservative 24-hour source freshness limit derived from safe snapshot timestamps.
- Fail-closed handling for partial, mixed-zone, malformed, timestamp-unknown, stale, or empty live sources.
- Stateful queue and dwell comparisons protected by a same-watch lock.
- Per-watch/request intent ledger: a confirmed replay does not call the provider, push a Dataset row, or charge again; prepared and ambiguous replays fail closed.
- A definitive budget stop is stored as an uncharged intent before delivery preparation; its replay has no provider, Dataset, charge, or state-write effects.
- Delivery receipts are closed internal records with no persisted
deliveryId; replay output exposes only a derivedreplay-sha256:<64 hex>marker bound to the report and request. - Overlapping Atlantic/Pacific identities are counted once; prior side wins, otherwise Atlantic wins deterministically.
- Baseline advancement only after exactly one confirmed
result-foundcharge and a successful state write. - Explicit
requestIdandwatchIdvalues are domain-separated SHA-256-derived identifiers before any lock, state, ledger, or output action. Returned request IDs are irreversible and cannot be used to recover the supplied input. - Synthetic demo Dataset row for Store and prefill inspection without the
$0.05result fee.
How to run
- Choose
demoto inspect a synthetic aggregate row, ordatalasticfor live aggregate evidence. - For
datalastic, add your Datalastic API key as the secretdatalasticApiKeyinput. - Keep
watchIdstable across scheduled runs so accepted observations share one baseline. - Set
maxTotalChargeUsdhigh enough for the applicable start and result prices. - Run the Actor and inspect
OUTPUT; a useful live report appears in the Dataset only after confirmed delivery.
The live source budget is fixed at maxProviderRequests: 3: one Datalastic /stat validation and one request for each Panama approach zone. Datalastic provider costs are separate from Actor pricing.
Input
| Field | Required | Description |
|---|---|---|
schemaVersion | Yes | Must be 1.0. |
requestId | Yes | Canonical lowercase idempotency value, or auto; the returned requestId is an irreversible derived identifier. |
watchId | Yes | Stable lowercase identity for one private baseline; it is irreversibly derived before lock/state/ledger use. |
sourceMode | Yes | demo or datalastic. |
datalasticApiKey | Live only | Secret buyer-owned provider key: present and non-empty, printable, 8-256 characters. Never returned or persisted. |
identitySalt | No | Optional live secret HMAC salt: if present, non-empty, printable, 8-256 characters. In demo mode even an empty or null secret property is rejected. |
baselineDays | No | Accepted historical observations used for comparison, from 7 to 365. |
maxVessels | No | Maximum safe rows accepted per fixed zone, from 1 to 500; defaults to 500 so dense live approaches are not truncated. |
maxProviderRequests | No | Fixed at exactly 3. |
timeoutMs | No | Per-request timeout from 1,000 to 30,000 ms. |
maxTotalChargeUsd | No | Buyer-side total Actor charge cap. Default is $0.055. |
Example input
{"schemaVersion": "1.0","requestId": "auto","watchId": "panama-canal-main","sourceMode": "datalastic","datalasticApiKey": "provided as a secret","baselineDays": 30,"maxVessels": 500,"maxProviderRequests": 3,"timeoutMs": 10000,"maxTotalChargeUsd": 0.055}
Output
OUTPUT is the authoritative run envelope. A live Dataset row is written only when the source is complete, every accepted snapshot has a usable source timestamp, the oldest accepted observation is no more than 24 hours old, at least one safe sample exists, and delivery is confirmed by an exact result-found counter increase of one.
A partial or insufficient source produces a partial report in OUTPUT with DATA_STALE, resultFound: false, no paid Dataset row, and no baseline advancement. A provider timestamp more than five minutes ahead of the Actor clock is rejected as future_source_timestamp. A first useful live observation is an honest bootstrap report; repeated runs are required before observed dwell is available.
Example output
This live bootstrap envelope is generated by scripts/generate_examples.mjs from the same report and output serializers used by the Actor; examples/live-output.json is the checked-in source fixture.
{"schemaVersion":"1.0","actor":"panama-canal-queue-transit-imbalance","requestId":"request-4fc91e78a0e5eae429d753795627b50a7a32c1c226b22457c1a695a9","status":"bootstrap","resultFound":true,"billedResultCount":1,"datasetWriteCount":1,"report":{"schemaVersion":"1.0","reportId":"sha256:e32ed254150a2014910f86feb43733fa54ad573adb3a5a972d57f052a159ab47","region":"panama_canal_approaches","status":"bootstrap","observedAt":"2026-08-08T00:00:00.000Z","metrics":{"atlantic":{"queueCount":6,"moving":4,"slow":0,"stopped":2,"unknown":0,"new":6,"departed":0},"pacific":{"queueCount":4,"moving":3,"slow":0,"stopped":1,"unknown":0,"new":4,"departed":0},"totalQueue":10,"sideImbalance":0.2,"crossSideTransitions":0,"observedDwell":{"samples":0,"meanSeconds":null,"minSeconds":null,"maxSeconds":null},"flowEvents":0,"crossZoneDeduplicated":0},"baseline":{"sampleCount":0,"meanQueue":null,"previousQueue":null,"queueRatio":null,"queuePercentDelta":null,"dwellAvailable":false},"nullReasons":{"metrics.sideImbalance":null,"metrics.observedDwell.meanSeconds":"unavailable_dwell","metrics.observedDwell.minSeconds":"unavailable_dwell","metrics.observedDwell.maxSeconds":"unavailable_dwell","baseline.meanQueue":"insufficient_history","baseline.previousQueue":"insufficient_history","baseline.queueRatio":"insufficient_history","baseline.queuePercentDelta":"insufficient_history","dataQuality.freshnessSeconds":null},"signals":[],"dataQuality":{"sourceOk":true,"partial":false,"freshnessSeconds":900,"sampleCount":10,"score":100,"confidence":"high","coverage":{"zonesExpected":2,"zonesComplete":2,"acceptedSamples":10},"limitations":["DWELL_UNAVAILABLE","INSUFFICIENT_HISTORY"]},"sources":[{"provider":"Datalastic","mode":"datalastic","retrievedAt":"2026-08-07T23:45:00.000Z","attribution":"Aggregate derived data; no raw AIS, official slots, official queue, or official Canal wait is returned."}],"billing":{"resultEvent":"result-found","baseResultPriceUsd":0.05,"tier":"FREE","resultPriceUsd":0.05}},"delivery":{"state":"confirmed_paid_result","confirmed":true,"attemptedPushCount":1,"chargedCount":1,"event":"result-found","tier":"FREE","resultPriceUsd":0.05},"baseline":{"advanced":true,"state":"advanced","sampleCount":1},"errors":[]}
Pricing
The Actor uses pay-per-event pricing. The default Dataset item event is unpriced. A synthetic demo writes one ordinary Dataset row after the start charge but does not emit result-found.
| Tier | Start event | Useful live result | Base total before BYOK provider costs |
|---|---|---|---|
| FREE | $0.005 | $0.05 | $0.055 |
| BRONZE | $0.00475 | $0.0475 | $0.05225 |
| SILVER | $0.0045 | $0.045 | $0.0495 |
| GOLD | $0.00425 | $0.0425 | $0.04675 |
| PLATINUM | $0.0041 | $0.041 | $0.0451 |
| DIAMOND | $0.004 | $0.04 | $0.044 |
At base tier, demo costs the $0.005 start event. A useful live run costs $0.055 before buyer-owned Datalastic usage. Partial, stale, malformed, timestamp-unknown, and empty live sources do not emit the $0.05 result event.
Data quality
Freshness is derived from sourceObservedAt and freshnessSeconds retained only in safe internal snapshots. The report uses the oldest accepted source observation as its conservative aggregate timestamp. Missing timestamps produce freshnessSeconds: null; observations older than 86,400 seconds or more than five minutes in the future are stale/invalid. Every nullable decision metric has a closed entry in nullReasons; dataQuality.coverage and dataQuality.limitations explain source and history coverage.
Motion classes use the canonical provider thresholds: stopped is <= 0.5 knots, slow is > 0.5 and < 3 knots, and moving is >= 3 knots. IDs returned by the Actor are fixed-format one-way derivatives, not the original request or watch strings.
Any provider error, mixed complete/error zone result, provider truncation, malformed zone payload or raw row, missing source timestamp, stale sample, or zero safe sample marks the report partial with DATA_STALE. Such a run cannot call paid delivery and cannot update canonical state. Raw provider counts need not equal Actor-owned geofence counts because valid circle-edge rows may be excluded.
Limitations
- Commercial AIS coverage and timestamps can be delayed, incomplete, or absent.
- An observed approach count is not an official Canal queue or official wait-time statistic.
- Observed dwell requires the same salted identity across repeated accepted runs.
- The Actor does not identify vessels, reconstruct routes, infer ownership or intent, classify sanctions exposure, or provide tactical alerts.
- A state save failure after confirmed paid delivery is reported as
state_write_failed; the paid row remains confirmed while baseline advancement is false and persistence is unknown. - A confirmed paid result and state write remain truthful if later lock release becomes uncertain; the run is separately terminal as
lock_release_unknown.
What the Actor gives you
The product is designed for a narrow commercial question: did the aggregate pressure observed in the two fixed Panama Canal approaches change enough to deserve review? It returns evidence for that question, not a substitute for an official schedule or a navigation system.
Use the report when you need to:
- compare Atlantic-side and Pacific-side observed pressure using the same deterministic geofences;
- distinguish a first observation from a history-backed change;
- inspect whether a queue increase is broad, side-specific, or accompanied by reduced observed flow;
- retain a compact evidence record without retaining raw vessel identities or coordinates;
- drive a human review queue with explicit freshness, coverage, null reasons, and limitations;
- run the same bounded watch repeatedly without silently charging a confirmed request twice.
Do not use it to claim an official Canal queue, predict an individual transit, route a vessel, infer cargo or ownership, estimate a booked slot, or make an autonomous operational decision. The Actor deliberately does not contain the evidence required for those conclusions.
How to read the decision evidence
The output separates observation, comparison, and actionability. Start with status and dataQuality, then read the metrics and signals.
| Evidence | What it means | What it does not mean |
|---|---|---|
metrics.totalQueue | Unique safe identities observed inside the two fixed approach zones. | Official queue size or ships with confirmed Canal reservations. |
metrics.sideImbalance | Absolute side-count difference divided by the total observed count. | Direction of a booked transit or a forecast of lock availability. |
metrics.observedDwell | Repeated-observation duration for the same salted identity across accepted runs. | Official waiting time, anchorage duration, or berth time. |
metrics.flowEvents | Deterministic aggregate movement events between compatible observations. | A complete transit ledger or voyage reconstruction. |
baseline.meanQueue | Mean of accepted stored queue observations in the configured window. | A climatological or Panama Canal Authority baseline. |
dataQuality.score | Contract-owned score for completeness, freshness, and usable coverage. | Probability that a commercial conclusion is correct. |
bootstrap is a useful first live observation with insufficient prior history. complete or no_change means the source and comparison contract was satisfied; it does not mean that no uncertainty remains. partial means the Actor withheld paid delivery because a source, freshness, timestamp, coverage, or structural requirement failed.
Signal thresholds
Signals are deterministic review labels, not model predictions:
QUEUE_BUILDINGrequires the current total to be at least 1.25 times the baseline mean and at least three vessels above it.QUEUE_CLEARINGrequires the current total to be no more than 0.75 times the baseline mean.SIDE_IMBALANCErequires at least five observed vessels and an absolute side imbalance of at least 0.40.TRANSIT_FLOW_DROPrequires flow events to be at least 25% and at least three events below the previous observation.DATA_STALErecords a source-quality failure and prevents a useful paid result.
The absence of a signal means only that its exact threshold was not met. It is not proof of normal Canal conditions.
Recommended review workflow
- Confirm
dataQuality.sourceOk === trueanddataQuality.partial === false. - Confirm
dataQuality.freshnessSecondsis present and within your business tolerance, not merely within the Actor's 24-hour hard limit. - Read
dataQuality.coverage,limitations, and every populatednullReasonsentry. - Compare
metrics.totalQueuewithbaseline.meanQueueandbaseline.previousQueue. - Inspect the Atlantic/Pacific split before treating a total change as corridor-wide.
- Treat a bootstrap as a baseline-building observation, not a trend conclusion.
- Record your independent context and decision outside the Actor. The Actor does not send, approve, or execute an action.
A useful downstream record normally stores the reportId, derived requestId, observedAt, signal list, confidence/quality fields, the human reviewer, and the review outcome. Keep the raw provider key out of downstream systems.
Automation, API, and MCP
The Actor can be called from the Apify API, a Task, a Schedule, an MCP client, or an automation platform. For scheduled monitoring, keep the same watchId and use a new requestId or auto for each intended observation. Reusing a confirmed request returns its proven result without another provider call or paid delivery; it does not create a new observation.
Example API request:
curl -X POST \"https://api.apify.com/v2/acts/zinin~panama-canal-queue-transit-imbalance/runs?token=$APIFY_TOKEN" \-H "content-type: application/json" \-d '{"schemaVersion":"1.0","requestId":"auto","watchId":"panama-canal-main","sourceMode":"demo","baselineDays":30,"maxVessels":500,"maxProviderRequests":3,"timeoutMs":10000,"maxTotalChargeUsd":0.055}'
For live mode, send datalasticApiKey through the secret Actor input field or your protected Task configuration. Do not place it in a URL, requestId, watchId, webhook payload, log message, or Dataset row.
After the run reaches a terminal platform state, read:
- the default KVS
OUTPUTrecord for the authoritative run and delivery state; - the default Dataset for a synthetic demo row or a confirmed useful live report;
- platform charged-event counts for settlement reconciliation.
Never automate a blind rerun after delivery_unknown, state_write_failed, or lock_release_unknown. Inspect the existing run, Dataset, OUTPUT, and platform event counts first. A new run always incurs a new automatic start event and may represent a new paid observation.
Delivery and replay states
The Actor distinguishes facts that are often incorrectly collapsed into one “failed” flag.
| State | Dataset may contain the report | result-found status | Safe automatic retry |
|---|---|---|---|
| Demo success | Yes, synthetic row | Not emitted | A new run is a new start purchase. |
| Confirmed live result | Yes | Exactly one confirmed event | No; reuse the same request only for reconciliation. |
| Definitive budget refusal | No | Confirmed zero | Same request returns the recorded refusal without new effects. |
| Source/quality refusal | No paid row | Not attempted | Fix the cause before creating a new request. |
| Ambiguous push or charge | Possibly | Unknown | No. Reconcile manually. |
| State write failure after paid delivery | Yes | Confirmed one | No. Billing is known; baseline persistence is not. |
| Lock release uncertainty | Yes when delivery was confirmed | Preserves the known result | No until the watch lock is investigated. |
replaySafe is therefore contextual rather than a promise that a fresh run is free. The durable request ledger prevents a confirmed request from being paid twice; a different run or request represents a separate purchase.
Data rights, privacy, and retention
Live mode is BYOK. You are responsible for holding a Datalastic plan and permissions that cover your use, transformation, retention, and downstream distribution. This Actor is designed to reduce exposure by returning derived aggregates and by excluding raw AIS rows, vessel names, MMSI, IMO, callsigns, coordinates, routes, and provider response text.
Private state retains only bounded salted identity derivatives and the minimum observation history needed for the configured baseline. A hash or HMAC is a pseudonymous technical control, not a declaration that source data is legally anonymous in every jurisdiction. Select a legitimate business purpose, limit access, set an appropriate retention period for Actor storages and exports, and delete Tasks, KVS records, Datasets, or downstream copies when they are no longer needed.
Do not use the Actor to identify or track a vessel, person, beneficial owner, crew, cargo, sanctions status, or military activity. Do not combine the aggregates with other data to reverse-engineer identities. Provider and public-data terms remain applicable even when the Actor exposes only aggregates.
Operational checklist
Before enabling a schedule:
- run
demoand verify your Dataset/KVS integration without a result fee; - confirm the expected tier prices and a cap that covers start plus one result;
- provide a stable
identitySaltif continuity must survive provider-key rotation; - choose one stable, non-secret
watchIdper analytical series; - ensure schedules cannot overlap for the same watch;
- decide who reviews partial, ambiguous, state-write, and lock-release outcomes;
- verify storage retention and provider-rights requirements;
- test that downstream code reads null reasons rather than coercing null to zero.
For every production run, retain the platform run ID, exact build ID, reportId, Dataset ID, KVS ID, and charged-event counts. Those identifiers make later reconciliation possible without exposing raw source data.
Troubleshooting
| Symptom | Likely reason | Next step |
|---|---|---|
bootstrap with null baseline fields | The watch has too little accepted history. | Keep the same watch and collect later accepted observations. |
DATA_STALE | Missing, future, old, malformed, partial, or empty source evidence. | Inspect quality and error codes; do not treat zero as a clean queue. |
watch_busy | Another run owns the same-watch lock. | Let that run settle; do not create parallel retries. |
request_replay_blocked | The intent is prepared, ambiguous, incompatible, or malformed. | Reconcile the original run and storage before any new request. |
| Budget refusal | Cap cannot cover the current start plus result contract. | Check your tier and cap; the refused request remains uncharged for the result. |
| State incompatibility | Schema, zone definition, source mode, or identity epoch changed. | Start a new watch or perform an explicit reviewed migration. |
Acceptance criteria for a useful live run
A downstream system should call the run useful only when the platform run is terminal, OUTPUT identifies a confirmed useful result, the Dataset contains exactly the expected report, the report passes its closed schema, reportId recomputes, dataQuality.partial is false, both fixed zones are complete, timestamps are eligible, and platform event counts reconcile to exactly one new result-found unit. Anything weaker is diagnostic evidence, not a completed decision report.
FAQ
Why did a live run return partial without a paid result?
At least one fail-closed quality condition was present: provider error, mixed-zone response, malformed payload, missing timestamp, data older than 24 hours, or zero safe samples. Inspect errors, report.signals, and report.dataQuality.
Does zero observed vessels mean the Canal queue is empty?
No. Zero safe samples is insufficient evidence and is never reported as a clean complete source.
Is this official Panama Canal wait or slot data?
No. The Actor publishes aggregate commercial AIS observations only and makes no official wait, slot, appointment, or navigation claim.
What happens if lock release is uncertain after delivery?
Known billing and saved-baseline facts remain unchanged. The run is marked lock_release_unknown so another same-watch run cannot assume the lock was released safely.
Related Actors
| Actor | Workflow reason |
|---|---|
| Strait of Hormuz Tanker Flow Recovery | Compare Panama approach pressure with tanker-flow recovery through another constrained maritime corridor. |
| Singapore Bunker Tanker Divergence | Add Singapore bunker-demand and tanker-flow context to a wider maritime monitoring workflow. |
| Live Price Oracle | Join transport pressure with current commodity or freight-market price evidence. |
| Counterparty Risk Rollup | Add a separate buyer-owned counterparty review to downstream logistics decisions. |
Built by zinin.