# Panama Canal Queue & Transit Imbalance Monitor (`zinin/panama-canal-queue-transit-imbalance`) Actor

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.

- **URL**: https://apify.com/zinin/panama-canal-queue-transit-imbalance.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** MCP servers, Automation, Travel
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.0425 / delivered panama approach report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Panama Canal Queue & Transit Imbalance Monitor

![Panama Canal Queue Intelligence: aggregate approach pressure, evidence, baseline, and review action](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/8192b1d6e7092f54d1c5e401786e5c0be091e318/commercial115/panama-canal-queue-transit-imbalance/readme-hero.webp)

![Panama Canal Queue Intelligence: bounded signals to a defensible queue decision](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/8192b1d6e7092f54d1c5e401786e5c0be091e318/commercial115/panama-canal-queue-transit-imbalance/readme-workflow.webp)

### 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 derived `replay-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-found` charge and a successful state write.
- Explicit `requestId` and `watchId` values 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.05` result fee.

### How to run

1. Choose `demo` to inspect a synthetic aggregate row, or `datalastic` for live aggregate evidence.
2. For `datalastic`, add your Datalastic API key as the secret `datalasticApiKey` input.
3. Keep `watchId` stable across scheduled runs so accepted observations share one baseline.
4. Set `maxTotalChargeUsd` high enough for the applicable start and result prices.
5. 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

```json
{
  "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.

```json
{"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_BUILDING` requires the current total to be at least 1.25 times the baseline mean and at least three vessels above it.
- `QUEUE_CLEARING` requires the current total to be no more than 0.75 times the baseline mean.
- `SIDE_IMBALANCE` requires at least five observed vessels and an absolute side imbalance of at least 0.40.
- `TRANSIT_FLOW_DROP` requires flow events to be at least 25% and at least three events below the previous observation.
- `DATA_STALE` records 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

1. Confirm `dataQuality.sourceOk === true` and `dataQuality.partial === false`.
2. Confirm `dataQuality.freshnessSeconds` is present and within your business tolerance, not merely within the Actor's 24-hour hard limit.
3. Read `dataQuality.coverage`, `limitations`, and every populated `nullReasons` entry.
4. Compare `metrics.totalQueue` with `baseline.meanQueue` and `baseline.previousQueue`.
5. Inspect the Atlantic/Pacific split before treating a total change as corridor-wide.
6. Treat a bootstrap as a baseline-building observation, not a trend conclusion.
7. 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:

```bash
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 `OUTPUT` record 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 `demo` and 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 `identitySalt` if continuity must survive provider-key rotation;
- choose one stable, non-secret `watchId` per 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](https://apify.com/zinin/strait-of-hormuz-tanker-flow-recovery) | Compare Panama approach pressure with tanker-flow recovery through another constrained maritime corridor. |
| [Singapore Bunker Tanker Divergence](https://apify.com/zinin/singapore-bunker-tanker-divergence) | Add Singapore bunker-demand and tanker-flow context to a wider maritime monitoring workflow. |
| [Live Price Oracle](https://apify.com/zinin/live-price-oracle) | Join transport pressure with current commodity or freight-market price evidence. |
| [Counterparty Risk Rollup](https://apify.com/zinin/counterparty-risk-rollup) | Add a separate buyer-owned counterparty review to downstream logistics decisions. |

Built by zinin.

# Actor input Schema

## `schemaVersion` (type: `string`):

Contract version for this Actor input.

## `requestId` (type: `string`):

Use auto for a trusted-run-derived id or provide an explicit idempotency value. The returned requestId is an irreversible SHA-256-derived identifier.

## `watchId` (type: `string`):

Stable lower-case identity for the queue history. It is irreversibly derived before lock, state, ledger, and output use.

## `sourceMode` (type: `string`):

Demo writes one synthetic row with no $0.05 result-found fee; the $0.005 start charge applies. Datalastic uses your own API key.

## `datalasticApiKey` (type: `string`):

Required only for datalastic mode. Runtime validation requires a printable 8-256 character secret. Never returned in output.

## `identitySalt` (type: `string`):

Optional HMAC salt for datalastic mode. Runtime validation requires a printable 8-256 character secret. Never returned in output.

## `baselineDays` (type: `integer`):

Number of stored observations used for the queue baseline.

## `maxVessels` (type: `integer`):

Maximum bounded provider rows accepted for each fixed approach. The live-safe default of 500 avoids truncating dense approach snapshots.

## `maxProviderRequests` (type: `integer`):

Fixed exact cap: /stat plus the two Panama approach zones.

## `timeoutMs` (type: `integer`):

Timeout for each bounded provider request.

## `maxTotalChargeUsd` (type: `number`):

Buyer-side cap checked before the paid report event.

## Actor input object example

```json
{
  "schemaVersion": "1.0",
  "requestId": "auto",
  "watchId": "panama-canal-main",
  "sourceMode": "demo",
  "baselineDays": 30,
  "maxVessels": 500,
  "maxProviderRequests": 3,
  "timeoutMs": 10000,
  "maxTotalChargeUsd": 0.055
}
```

# Actor output Schema

## `OUTPUT` (type: `string`):

Run status and delivery receipt.

## `REPORTS` (type: `string`):

Contains a paid live aggregate after confirmed result-found delivery, or one uncharged synthetic report in demo mode.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "schemaVersion": "1.0",
    "requestId": "auto",
    "watchId": "panama-canal-main",
    "sourceMode": "demo",
    "baselineDays": 30,
    "maxVessels": 500,
    "maxProviderRequests": 3,
    "timeoutMs": 10000,
    "maxTotalChargeUsd": 0.055
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/panama-canal-queue-transit-imbalance").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "schemaVersion": "1.0",
    "requestId": "auto",
    "watchId": "panama-canal-main",
    "sourceMode": "demo",
    "baselineDays": 30,
    "maxVessels": 500,
    "maxProviderRequests": 3,
    "timeoutMs": 10000,
    "maxTotalChargeUsd": 0.055,
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/panama-canal-queue-transit-imbalance").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "schemaVersion": "1.0",
  "requestId": "auto",
  "watchId": "panama-canal-main",
  "sourceMode": "demo",
  "baselineDays": 30,
  "maxVessels": 500,
  "maxProviderRequests": 3,
  "timeoutMs": 10000,
  "maxTotalChargeUsd": 0.055
}' |
apify call zinin/panama-canal-queue-transit-imbalance --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/panama-canal-queue-transit-imbalance"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/13ahr7oF8U8L5Xouy/builds/UW7wAFw4fD67ZfB0g/openapi.json
