# Container Delay & Free-Time Evidence Monitor (`zinin/container-exception-evidence`) Actor

Turn buyer-authorized container event snapshots into deterministic ETA, milestone, free-time, cost-exposure, confidence, limitation, and human-review evidence. No carrier scraping, reference fetching, legal verdict, automatic claim, or provider key.

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

## Pricing

from $0.0425 / delivered container exception 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

## Container Delay & Free-Time Evidence Monitor

Production charging contract: `container-exception-evidence-production-charging-amendment-r1`. It records the pinned `apify@3.7.2` production receipts and narrowly supersedes the older default-Dataset pricing-shape wording; customer-rights, source and product semantics are unchanged.

Limited-permissions production amendment: `container-exception-evidence-limited-permissions-remediation-r2`. Customer `snapshot` runs use caller-carried continuation state. They do not open a Request Queue, use a named KVS, persist durable intent, or claim cross-run idempotency. The first complete snapshot returns a baseline state; a later snapshot passes that exact state back as `continuationState` and receives the exact next state in `nextContinuationState`.

Turn an authorized customer snapshot of container events into a deterministic evidence report. The Actor compares the supplied timeline with the last healthy baseline and identifies ETA slips, missing or out-of-order milestones, gate/empty-return pairing problems, free-time exposure and customer-assumption cost exposure.

This Actor does **not** scrape carriers, call a provider, resolve a reference, use AIS, accept credentials, determine carrier truth, issue a legal/compliance verdict, or sell raw events. Input remains customer-owned or customer-authorized data and requires the five-field rights attestation.

![Container Exception Evidence: customer snapshot to evidence report](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/f031f479666a80521b9ea0f9a3680f275cbdccf8/commercial115/container-exception-evidence/readme-hero.webp)

![Container Exception Evidence: review and reconciliation workflow](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/f031f479666a80521b9ea0f9a3680f275cbdccf8/commercial115/container-exception-evidence/readme-workflow.webp)

### Machine contract

- Input is a closed `snapshot` object or the exact `synthetic_demo` fixture.
- All calculations are deterministic and use UTC-normalized timestamps, sorted canonical JSON and domain-separated SHA-256 digests.
- Customer BOL and booking values are never returned; only domain-separated digests are exposed.
- Safe `ref:` and HTTPS references are validated but never fetched.
- `REPORTS` is the default Dataset: one immutable pre-push `decisionPayload`, without receipts or post-push facts.
- `OUTPUT` is the default KVS record: the authoritative terminal status, receipt, billing, baseline and replay facts. MCP consumers must read `OUTPUT`.
- The only MCP tool is `container_exception_evidence.run`.
- The executable MCP adapter is exported from `lib/mcp.js` (package export `./mcp`). It returns one text item whose canonical JSON parses byte-for-value to the same `structuredContent` OUTPUT; it never substitutes REPORTS.

### What to upload

Upload one JSON object containing `watchId`, `mode`, `sourceStatus`, `rightsAttestation`, `containers`, `events`, and `tariffAssumptions`; customer snapshots may also include the exact optional `continuationState` returned by a prior complete run. Every snapshot must contain at least one event. For each container, `promisedEta`, `freeTimeEnd`, or at least one matching event supplies its comparison anchor. Tariff values are your own USD/day assumptions; the Actor does not consult terminal calendars or carrier tariffs.

Raw JSON is checked before parsing for the 2,097,152-byte limit and duplicate object keys. Event time must be no later than receipt time, and both must be no later than the Actor-generated decision time. Unsafe references and secret-shaped output-bearing values become non-echoing row errors.

```json
{
  "watchId": "customer-watch-1",
  "mode": "snapshot",
  "sourceStatus": "complete",
  "rightsAttestation": {
    "customerControlsOrIsAuthorizedToUseData": true,
    "noCredentialsOrSecretsSubmitted": true,
    "unfetchedReferencePolicyAccepted": true,
    "attestedAt": "2026-08-09T09:00:00Z",
    "attestorId": "customer-operator-1"
  },
  "containers": [{
    "containerNumber": "MSCU1234566",
    "carrier": "customer-declared-carrier",
    "promisedEta": "2026-08-12T12:00:00Z",
    "freeTimeEnd": "2026-08-15T12:00:00Z",
    "originUnlocode": "NLRTM",
    "destinationUnlocode": "USLAX"
  }],
  "events": [{
    "eventId": "customer-event-1",
    "containerNumber": "MSCU1234566",
    "eventType": "gate_in",
    "eventTime": "2026-08-08T09:00:00Z",
    "receivedAt": "2026-08-08T09:05:00Z",
    "locationUnlocode": "NLRTM",
    "plannedLocationUnlocode": null,
    "plannedTime": null,
    "source": "customer-system",
    "reference": "ref:customer-evidence-1"
  }],
  "tariffAssumptions": { "currency": "USD", "demurragePerDay": 0, "detentionPerDay": 0 }
}
```

### Pricing

Pay per event: USD 0.005 Actor start plus one `container-exception-found` event for a complete report containing one or more new material exception rows. A report with 1, 2 or 1,000 material rows still emits exactly one result event. Baselines, unchanged reports, partial/error reports and the synthetic demo emit zero product events. Tier discounts are Apify's account tiers: FREE, BRONZE, SILVER, GOLD, PLATINUM and DIAMOND. The price is selected by the charging manager, never by row count.

The direct Hub reference price is USD 0.0800. The local product contract caps the worst FREE run at USD 0.0550 and requires p95 whole-run COGS of no more than USD 0.0100 before external release.

### Delivery and recovery

Production reads the authoritative input exactly once from the default KVS client as `getRecord("INPUT", { buffer: true })`. It validates the original Buffer size, JSON media type, fatal UTF-8/ASCII decoding and duplicate keys before schema processing. Parsed `Actor.getInput()` values, alternate input keys and inbound metamorph records are unsupported.

The SDK does not expose an account tier. The Actor infers one tier only from an exact accepted `apify-actor-start`/`container-exception-found` price pair. Pinned `apify@3.7.2` exposes exactly those configured PPE keys; `apify-default-dataset-item` is an implicit zero-priced SDK operation and is not added to the pricing registry. A successful unpriced push returns aggregate `chargedCount=1`, one Dataset item, configured chargeability keys only, default counter delta `+1`, report counter delta `0` and amount delta `0`. A paid named Dataset push confirms one product result only when the pinned SDK returns aggregate `chargedCount=2`, exact +1 report/default counters, one Dataset item and the exact integer micro-USD report-price amount delta. Chargeability is capacity evidence only. Either boolean post-charge limit flag is accepted; `true` means only that future report capacity is exhausted. Extra, missing or malformed configured pricing keys fail closed. `replay.status` is the one closed set `not_replay | confirmed_replay | output_recovered | ambiguous_replay`.

For a customer snapshot, the Actor performs at most one Dataset push: an unpriced decision payload for baseline/unchanged/partial/error, or one `Actor.pushData(decisionPayload, "container-exception-found")` call when a complete snapshot contains a material exception. Application retries are zero. An ambiguous response is terminal with nullable delivery facts and `DELIVERY_EFFECT_UNKNOWN`; it is never pushed again. The only run-scoped KVS record is default `OUTPUT`, read back before a successful exit. `currentRunEffects.stateWrites=0` and `intentWrites=0`; the caller, not the Actor, persists `nextContinuationState`.

Direct Apify reruns are new billable runs. The Actor makes no global cross-run billing-deduplication claim and does not use `OUTPUT` as a replay index. Callers must use `requestDigest` and the exact continuation state to avoid duplicate orchestration. One monotonic 120-second deadline starts before INPUT acquisition and includes OUTPUT Buffer read-back and exit; the paid push receives at most 30 seconds of the remaining budget.

### Limitations and rights

The customer declares control or authorization for the submitted data. DCSA URLs in `contract/source-rights.json` are citation-only semantic references; no DCSA artifact is bundled or fetched. No carrier, terminal or commercial provider adapter exists in V1. This is not legal advice and does not prove tariff, invoice, carrier or compliance truth.

### Related actors

| Actor | Relationship |
| --- | --- |
| [Strait of Hormuz Tanker Flow Recovery](https://apify.com/zinin/strait-of-hormuz-tanker-flow-recovery) | Maritime flow context for separate regional monitoring; this Actor remains container-event-only and does not call it. |
| [Singapore Bunker Tanker Divergence](https://apify.com/zinin/singapore-bunker-tanker-divergence) | Separate Singapore market signal; useful as a workflow input only after the customer maps and authorizes its own events. |
| [Panama Canal Queue Transit Imbalance](https://apify.com/zinin/panama-canal-queue-transit-imbalance) | Separate Panama transit signal; not a carrier truth source for this Actor. |

### Synthetic public Task

The public Task may use the following exact input inline; it is also kept repo-only in `fixtures/public-task-input.json` for tests. The runtime accepts only these values, performs zero provider/reference/continuation-state calls, writes one receipt-free `REPORTS` item and one default KVS `OUTPUT`, and emits zero product events.

```json
{"watchId":"public-synthetic-demo","mode":"synthetic_demo","sourceStatus":"complete","rightsAttestation":{"customerControlsOrIsAuthorizedToUseData":true,"noCredentialsOrSecretsSubmitted":true,"unfetchedReferencePolicyAccepted":true,"attestedAt":"2026-08-09T00:00:00.000Z","attestorId":"public-task-synthetic"},"containers":[{"containerNumber":"MSCU1234566","carrier":"Synthetic Ocean","billOfLading":null,"bookingNumber":null,"promisedEta":"2026-08-12T12:00:00.000Z","freeTimeEnd":"2026-08-15T12:00:00.000Z","originUnlocode":"NLRTM","destinationUnlocode":"USLAX"}],"events":[{"eventId":"demo-gate-in-1","containerNumber":"MSCU1234566","eventType":"gate_in","eventTime":"2026-08-08T09:00:00.000Z","receivedAt":"2026-08-08T09:05:00.000Z","locationUnlocode":"NLRTM","plannedLocationUnlocode":null,"plannedTime":null,"source":"synthetic-fixture","reference":"ref:demo-1"},{"eventId":"demo-eta-1","containerNumber":"MSCU1234566","eventType":"eta_update","eventTime":"2026-08-09T10:00:00.000Z","receivedAt":"2026-08-09T10:01:00.000Z","locationUnlocode":"NLRTM","plannedLocationUnlocode":null,"plannedTime":"2026-08-12T12:00:00.000Z","source":"synthetic-fixture","reference":"ref:demo-2"}],"tariffAssumptions":{"currency":"USD","demurragePerDay":0,"detentionPerDay":0}}
```

The authoritative machine result is the following complete default KVS `OUTPUT` for the inline input above. The timestamps, request identifiers, and SHA-256 values are deterministic for this exact input and generated-at decision time:

```json
{"schemaVersion":"1.1.0","actor":"container-exception-evidence","requestId":"cee_req_c00f36d48fcf6afb14f70cafb8612c13","requestDigest":"sha256:c00f36d48fcf6afb14f70cafb8612c137413baab4f76cebef95ac63645ae4975","reportId":"cee_report_0faa55b5e8a81a852a05985755fdf4f0","decisionPayloadDigest":"sha256:98f2565a695bedd5134d638df03b61c39f109c017157bd51d1b56fe2972acabc","decisionPayloadReference":{"datasetId":"default","reportId":"cee_report_0faa55b5e8a81a852a05985755fdf4f0"},"decisionPayloadReferenceNullReason":null,"status":"complete","resultFound":false,"generatedAt":"2026-08-09T12:00:00.000Z","billing":{"accountTier":"FREE","accountTierSource":"apify_charging_manager","startEvent":{"name":"apify-actor-start","quantity":1,"unitPriceUsd":0.005,"totalPriceUsd":0.005,"priceNullReason":null},"exceptionEvent":null,"exceptionEventNullReason":"SYNTHETIC_DEMO","defaultDatasetEventPriceUsd":0,"defaultDatasetEventPriceNullReason":null,"projectedTotalUsd":0.005,"projectedTotalNullReason":null,"confirmedTotalUsd":0.005,"confirmedTotalNullReason":null,"maxRunSpendUsd":0.055},"deliveryReceipt":{"status":"uncharged","expectedExceptionEvents":0,"confirmedExceptionEvents":0,"confirmedExceptionEventsNullReason":null,"datasetItemsWritten":1,"datasetItemsWrittenNullReason":null,"sdkChargeEvidence":{"aggregateChargedCount":1,"aggregateChargedCountNullReason":null,"eventChargeLimitReached":false,"eventChargeLimitReachedNullReason":null,"chargeableWithinLimitStatus":"default_dataset_only_sufficient"},"receiptDigest":"sha256:fe8dc243f918ee8e4816673b777751bc371322023a9dc4eacb7aac349491ccf0","receiptDigestNullReason":null},"baselineReceipt":{"status":"not_written","initializedContainerCount":0,"initializedContainerCountNullReason":null,"advancedContainerCount":0,"advancedContainerCountNullReason":null,"baselineDigest":null,"baselineDigestNullReason":"NO_BASELINE_WRITE"},"replay":{"status":"not_replay","priorReceiptFacts":null,"priorReceiptFactsNullReason":"NOT_REPLAY"},"currentRunEffects":{"applicationPaidPushInvocations":0,"applicationUnpricedPushInvocations":1,"applicationRetries":0,"datasetItemsWritten":1,"datasetItemsWrittenNullReason":null,"productResultEvents":0,"productResultEventsNullReason":null,"stateWrites":0,"stateWritesNullReason":null,"intentWrites":0,"providerCalls":0,"sdkTransportRetries":null,"sdkTransportRetriesNullReason":"SDK_MANAGED_OPAQUE"},"containers":[{"containerNumber":"MSCU1234566","carrier":"Synthetic Ocean","billOfLadingDigest":null,"bookingNumberDigest":null,"normalizedInputIdentity":"sha256:7395181548a57f76b43eca7276d6a22ede2a85ff9349f789e22223aba5427ad3","observedAt":"2026-08-09T10:01:00.000Z","effectiveAt":null,"generatedAt":"2026-08-09T12:00:00.000Z","status":"synthetic_demo","error":null,"exceptionType":null,"additionalExceptionTypes":[],"severity":"none","materialChange":false,"firstObservedAt":null,"baselineEta":"2026-08-12T12:00:00.000Z","currentEta":"2026-08-12T12:00:00.000Z","delayHours":0,"freeTimeClock":{"status":"active","freeTimeEnd":"2026-08-15T12:00:00.000Z","remainingHours":144,"timezone":"UTC","basis":"customer_supplied","nullReason":null},"costExposure":{"status":"zero","currency":"USD","amount":0,"basis":"customer_supplied_tariff_assumptions","nullReason":null},"evidence":[{"source":"synthetic-fixture","eventId":"demo-gate-in-1","eventType":"gate_in","eventTime":"2026-08-08T09:00:00.000Z","receivedAt":"2026-08-08T09:05:00.000Z","reference":"ref:demo-1","referenceNullReason":null,"eventCoreDigest":"sha256:108a667218e922ba7345e05f04ef6c65cbf5157f7d958ded75a9f9aa46d4b622","digest":"sha256:73082736a674d77b02b201690c78cae31cdedccf10befa92c1e2464478c4c52e"},{"source":"synthetic-fixture","eventId":"demo-eta-1","eventType":"eta_update","eventTime":"2026-08-09T10:00:00.000Z","receivedAt":"2026-08-09T10:01:00.000Z","reference":"ref:demo-2","referenceNullReason":null,"eventCoreDigest":"sha256:ef979b1783236cbe705bb5d85b6957c73a2a3f825580365bd6b30d2d00da3183","digest":"sha256:6471e73b56a811fa1adf607214488e5ccdb569c4b080f238fefe141791367e20"}],"confidence":{"level":"high","score":0.9,"reasons":["COMPLETE_TWO_OR_MORE_SUPPORTING_EVENTS"]},"limitations":["SYNTHETIC_DEMO"],"sourceCompleteness":"complete","freshnessSeconds":7140,"recommendedHumanAction":"none","stateDisposition":"not_written","stateDispositionReason":null,"billingDisposition":"synthetic_demo","acceptedPricingTier":"FREE","nullReasons":{"carrier":null,"billOfLadingDigest":"NOT_SUPPLIED","bookingNumberDigest":"NOT_SUPPLIED","observedAt":null,"effectiveAt":"NO_EXCEPTION","error":"NO_ERROR","exceptionType":"NO_EXCEPTION","firstObservedAt":"NO_EXCEPTION","baselineEta":null,"currentEta":null,"delayHours":null,"freshnessSeconds":null}}],"errors":[],"limitations":["SYNTHETIC_DEMO"],"nextContinuationState":null}
```

Consumers must read `OUTPUT` from KVS rather than reconstructing it from prose; this example is included so a machine client can validate the complete shape without accessing the repo-only fixture.

### What you get

The paid unit is one complete delivered container-exception evidence report, not
one container or one exception row. A report can contain one, two, or up to one
thousand material rows while emitting exactly one
`container-exception-found` event.

For each accepted container, the report can include:

- a normalized observation time and customer-controlled identity digest;
- ETA comparison against the caller-carried healthy baseline;
- missing, duplicated, or out-of-order milestone evidence;
- gate-in, gate-out, empty-return, and free-time pairing observations;
- demurrage or detention exposure calculated only from buyer assumptions;
- source completeness and freshness fields;
- evidence rows with stable digests and unfetched references;
- confidence, limitations, and a recommended human action;
- continuation state for the next complete snapshot;
- a receipt-free Dataset `decisionPayload` for analysis;
- authoritative KVS `OUTPUT` for delivery, billing, current-run effects,
  baseline, continuation, and replay reconciliation.

The Actor is deliberately evidence-first. It does not say that a carrier is at
fault, an invoice is valid, a tariff applies, a shipment breached a contract,
or a customer should dispute a charge. `recommendedHumanAction` is a review
route, not an executed action. No email, webhook, portal message, claim, booking
change, or payment is sent.

Free outcomes remain explicit. The fixed synthetic demo writes one unpriced
report. A healthy baseline, unchanged complete snapshot, partial source,
invalid input, pricing failure, or ambiguous delivery emits no confirmed
product event. The automatic Actor start event is separate and may still apply.

### Who uses it

#### Import and export operations teams

Use the report to organize customer-owned event timelines and highlight
exceptions that need a person to inspect carrier notices, terminal records,
contracts, and operational context.

#### Freight forwarders and NVOCC operations

Use exact customer shipment snapshots to compare ETA and milestone changes
across an approved workflow. The Actor does not establish carrier truth or
replace the forwarder's exception-management process.

#### Finance and accrual teams

Use `costExposure` only as an arithmetic scenario under buyer-supplied USD/day
assumptions. It is not an invoice, accrual policy, accounting conclusion, tariff
quote, payable instruction, or recoverability opinion.

#### Data engineering teams

Use the closed schemas, canonical JSON, domain-separated digests, bounded
payloads, and caller-carried continuation state to test upstream container
event pipelines. Unknown values remain null with reasons rather than being
silently guessed.

#### Governance and assurance reviewers

Use rights attestations, source completeness, evidence digests, limitations,
delivery receipts, and current-run effects to review what the workflow actually
did. Customer shipment facts remain unverified unless your separate process
proves them.

#### Automation builders

Use REPORTS for evidence display and KVS OUTPUT for terminal routing. Only
route material rows into a human work queue. Never trigger a carrier claim,
payment hold, customer representation, legal notice, or booking action directly
from this Actor.

### How to run

Start with `synthetic_demo`. It proves input validation, one unpriced Dataset
write, default-Dataset accounting, KVS OUTPUT, and the no-provider boundary
without using customer shipment information.

For a customer snapshot:

1. export a bounded authorized snapshot from your own system;
2. include at least one container and one event;
3. set `sourceStatus` truthfully to complete or partial;
4. complete all five rights and unfetched-reference attestations;
5. provide buyer-owned tariff assumptions, including zero when no scenario is
   required;
6. on the first complete run, omit `continuationState` and retain the returned
   `nextContinuationState`;
7. on the next comparable run, pass that exact state back without editing it;
8. set a charge cap that covers the current start price and one report price;
9. poll the exact run to terminal, then read KVS OUTPUT before REPORTS;
10. preserve and manually reconcile an ambiguous receipt without retrying.

API pattern:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/zinin~container-exception-evidence/runs?token=YOUR_APIFY_TOKEN' \
  -H 'content-type: application/json' \
  --data-binary @container-snapshot.json
```

The runtime reads the raw default KVS INPUT record exactly once as a Buffer.
Do not depend on alternate Input keys, parsed fallback values, metamorph input,
or a second read. Keep each request below the byte and count limits. If your
system has more rows, partition by a stable watch scope and reconcile each run
separately.

Direct reruns are new Apify runs and can incur a new start or result event. The
Actor does not persist a cross-run idempotency index. Your orchestrator must
bind the request digest and exact continuation state to its own job record.

### Input contract

The authoritative contract is [`contract/input.schema.json`](contract/input.schema.json)
plus raw-byte runtime validation. The Store schema is an Apify-compatible
projection and cannot express every duplicate-key, byte, time, and cross-field
condition.

#### Root fields

- `watchId` is a bounded caller-owned workflow identity;
- `mode` is `snapshot` or the exact fixed `synthetic_demo` branch;
- `sourceStatus` is complete or partial and must reflect the supplied export;
- `rightsAttestation` is mandatory and closed;
- `containers`, `events`, and `tariffAssumptions` are mandatory;
- `continuationState` is optional only for a customer snapshot;
- unknown keys fail closed.

Do not put a bill of lading, booking number, customer name, carrier account,
credential, or other sensitive value in `watchId`. It appears in workflow
metadata even though sensitive shipment references are digested elsewhere.

#### Rights attestation

The caller must affirm control or authorization to process the data, absence of
credentials and secrets, acceptance of the unfetched-reference policy, a
bounded attestation time, and a caller-controlled attestor ID. These are buyer
representations, not independently verified legal facts.

#### Containers

Container number follows the accepted ISO-style shape and must match referenced
events. Carrier text is buyer supplied. BOL and booking identifiers are never
returned as raw values; when accepted they are represented by domain-separated
digests. Origin and destination UN/LOCODE values are syntactically validated but
not checked against a port registry.

At least one comparison anchor is required: promised ETA, free-time end, or a
matching event. Unknown facts must remain null. Do not substitute placeholder
dates or zero values merely to pass validation.

#### Events

Every event has a stable event ID, matching container number, closed event type,
event time, receipt time, source label, and safe `ref:` or HTTPS reference.
References are validated as strings and never fetched. Event time cannot be
after receipt time, and neither can be after the Actor-generated decision time.

The Actor does not verify the sender, signature, source clock, carrier system,
terminal system, EDI semantics, or authenticity of an event. Use a trusted
upstream provenance process when those facts matter.

#### Tariff assumptions

Only USD/day buyer assumptions are accepted in V1. The Actor applies deterministic
arithmetic to the supplied free-time and event timeline. It does not fetch a
tariff, terminal calendar, holiday schedule, invoice, exchange rate, contract,
or carrier rule. Zero means the buyer intentionally supplied a zero scenario;
it does not prove there is no commercial exposure.

#### Continuation state

`nextContinuationState` is the complete caller-carried baseline for the next
comparable snapshot. Preserve the exact value. Editing, merging, reconstructing,
or combining it across watch IDs destroys the accepted comparison boundary.
The Actor does not open a named KVS or RequestQueue for customer state.

### Happy, partial, and failure output

#### Complete material exception

The Actor builds one immutable `decisionPayload`, performs one linked paid push,
reconciles Dataset and product/default event counters plus integer micro-USD
amount, writes KVS OUTPUT, reads it back, and exits. Confirmation requires the
exact pinned receipt lattice; a positive aggregate count alone is insufficient.

#### Complete healthy baseline or unchanged snapshot

A complete snapshot without a new material exception writes one unpriced
decision payload and zero product events. It can return the next continuation
state for the caller to retain. An unchanged result is not evidence that every
external source or real-world fact is unchanged; it is a comparison of the
accepted supplied snapshots.

#### Partial source

Partial input may produce review evidence but cannot safely advance the same
complete-snapshot conclusions. Source completeness remains visible and the
output explains why the result is partial. Do not infer that an absent milestone
or container is truly missing from the upstream system.

#### Invalid or unsafe input

Oversize bytes, invalid media type, duplicate JSON keys, invalid encoding,
unknown fields, secret-shaped output-bearing values, unsafe references, time
inconsistency, and schema failures stop before product delivery. Correct the
source rather than coercing it.

#### Pricing or budget failure

The configured PPE map must contain exactly the start and
`container-exception-found` keys at one accepted tier pair. The implicit default
Dataset event is not configured and remains zero priced. Unknown keys, malformed
prices, insufficient charge capacity, or unreadable amount/counter state fail
closed.

#### Ambiguous delivery

If a push response is lost or receipt facts cannot prove the side effect, OUTPUT
records ambiguity with nullable facts and no automatic retry. Preserve run,
Dataset, KVS, logs, request digest, continuation state, and platform counters.
Never assume ambiguity means free or paid.

#### OUTPUT write failure

OUTPUT is authoritative. If it cannot be written and read back, the run fails
even when a Dataset effect may exist. Use platform evidence to reconcile the
original attempt before starting another run.

### Field dictionary

| Field group | Meaning | Boundary |
|---|---|---|
| `requestId` / `requestDigest` | Current deterministic request binding | A new run is not global idempotency |
| `reportId` | Stable report identity | Not a carrier or shipment identifier |
| `decisionPayloadDigest` | Integrity binding for REPORTS row | A digest is not anonymization |
| `status` | Closed processing terminal | Not a legal/commercial verdict |
| `resultFound` | Confirmed product-result outcome in OUTPUT | Dataset payload itself has no receipt |
| `billing` | Tier, unit, start, projected and confirmed amount facts | Current platform pricing remains authoritative |
| `deliveryReceipt` | Dataset/event/amount confirmation lattice | Ambiguous facts prohibit blind retry |
| `baselineReceipt` | Caller-carried baseline effect | No named persistence is claimed |
| `replay` | Current-run recovery classification | Direct rerun can be newly billable |
| `currentRunEffects` | Pushes, retries, rows, events, state and provider calls | Null means unavailable under a closed reason |
| `containers` | Per-container deterministic evidence rows | Customer source facts remain unverified |
| `evidence` | Accepted supplied timeline facts and digests | References are never fetched |
| `confidence` | Confidence in submitted-evidence processing | Not carrier-truth confidence |
| `limitations` | Explicit scope and data gaps | Review before downstream use |
| `recommendedHumanAction` | Unsent routing suggestion | Never an executed action |
| `sourceCompleteness` | Buyer-declared coverage class | Does not prove upstream completeness |
| `freshnessSeconds` | Submitted event recency | Depends on buyer timestamps |
| `nextContinuationState` | Exact next comparable baseline | Caller must persist unchanged |

#### REPORTS versus OUTPUT

REPORTS stores the immutable payload prepared before the delivery receipt is
known. It cannot contain authoritative post-push billing or recovery facts.
OUTPUT is the terminal receipt and is the only machine surface for result,
delivery, billing, replay, and current-run reconciliation. Do not rebuild OUTPUT
from the Dataset row or README example.

### Evidence and boundaries

The Actor proves deterministic transformations of submitted bytes. It can prove
which rows were accepted, how times were normalized, how exception rules were
applied, which assumptions were used, what digests bind the evidence, what the
runtime attempted, and what the pinned counters/amounts confirm.

It does not prove carrier, terminal, customs, port, customer, vessel, invoice,
tariff, ETA, free-time, contract, negligence, liability, or legal truth. It has
no provider key and makes zero carrier, terminal, DCSA, AIS, portal, reference,
or nested Actor calls.

DCSA references in the source-rights registry are citation-only semantic
context. The runtime does not bundle, fetch, reproduce, or claim conformance to
a DCSA product. Customer fields and local rules remain the operative evidence
contract.

#### Privacy and confidentiality

Container events can reveal customer relationships, routes, schedules, delays,
commercial terms, and operational patterns. Submit only the minimum authorized
fields. Do not submit credentials, access tokens, personal contact data, customs
documents, bills of lading in narrative text, dangerous-goods details, security
instructions, sanctions-sensitive notes, or other unnecessary confidential data.

Digests reduce raw-value exposure but are not anonymization. Apify retains run
Input, REPORTS, OUTPUT, and logs under workspace controls. Establish access,
retention, deletion, correction, export, and incident-response rules before
production use.

### Decision routing

Route by terminal truth first, then evidence:

- confirmed material report: human exception review;
- complete unchanged/baseline result: retain as bounded evidence;
- partial result: repair coverage before operational interpretation;
- invalid input: correct upstream schema or unsafe content;
- pricing/budget failure: review live tier and cap without replaying an
  ambiguous operation;
- ambiguous delivery: freeze automation and reconcile manually;
- OUTPUT failure: use platform run, Dataset, KVS, logs, and counters as the
  recovery surface.

Within a confirmed report, use severity, exception type, confidence,
limitations, freshness, and recommended action to order a human queue. Never
allow one field alone to trigger a material external action.

### Commercial playbooks

#### ETA exception triage

Submit a complete authorized snapshot with promised ETA and recent ETA events.
Review deterministic slips and evidence timestamps, then ask an operator to
check carrier communications and customer commitments.

#### Free-time review

Supply the buyer's accepted free-time end and tariff scenario. Treat calculated
cost as planning exposure only. A person must verify the applicable tariff,
calendar, contract, invoice, and responsibility.

#### Milestone completeness

Use ordered events to identify missing or out-of-order pairs. Partial source
status keeps uncertainty visible. Do not treat a missing supplied event as proof
that the real milestone did not occur.

#### Customer escalation preparation

Use the report to assemble an internal evidence packet. Keep communication,
claims, disputes, and customer representations in a separate approved system
with human authorization.

#### Data-pipeline acceptance

Run the synthetic demo and controlled fixtures to validate byte limits, duplicate
keys, continuation handling, digests, report schemas, billing counters, and
ambiguous recovery before allowing production shipment data.

### Integration recipes

#### Webhook workflow

Wait for one exact run to finish, fetch KVS OUTPUT, validate the schema and
receipt, then store a link to the REPORTS row. Send a minimal internal review
notification rather than copying shipment evidence into email or chat.

#### Warehouse workflow

Store one run/OUTPUT record and explode per-container decisions into child rows.
Keep the exact next continuation state in a restricted state table keyed by
watch ID. Never combine states from different watches or Actor versions.

#### Ticketing workflow

Create a ticket only for confirmed, reviewable material exceptions. Include the
report ID, decision row reference, confidence, limitations, source completeness,
and run link. The ticket system owns assignment and resolution; the Actor owns
only evidence generation.

#### MCP workflow

Call only `container_exception_evidence.run`. Parse the text item and
`structuredContent` as the same canonical OUTPUT. MCP execution does not create
an alternative REPORTS contract and must preserve the same input rights and
human-review boundaries.

### Operating guide

Before production:

- confirm authorization for all container and event data;
- define stable watch ownership and continuation-state storage;
- test the synthetic and controlled snapshot branches;
- document tariff-assumption ownership;
- verify current Apify tier pricing and cap;
- configure access and retention for Input, REPORTS, OUTPUT, and logs;
- assign a human reviewer and correction route.

During a run:

- retain the exact run ID and input digest;
- do not start a second run to poll the first;
- do not edit continuation state;
- allow the 120-second monotonic deadline to govern execution;
- treat REPORTS appearance as evidence preparation, not settlement proof.

After a run:

- check terminal platform status;
- read and validate KVS OUTPUT;
- reconcile result/default counters and confirmed amount;
- inspect completeness, confidence, limitations, and errors;
- persist the next continuation state only from an accepted complete terminal;
- route material evidence to a person;
- apply the approved retention or deletion schedule.

For an incident, preserve the build ID, run ID, Dataset ID, KVS ID, request and
payload digests, counters, amounts, logs, continuation state, and exact input
hash. Do not overwrite the evidence with a retry.

### FAQ

#### Does it scrape carriers or terminals?

No. It processes customer-authorized snapshots and never fetches references.

#### Does it verify carrier truth?

No. It validates and transforms submitted evidence under deterministic rules.

#### Does it calculate an invoice?

No. Cost exposure uses buyer-supplied USD/day assumptions and is a planning
scenario, not a payable or recoverable amount.

#### Why is continuation state caller-carried?

Limited-permissions production deliberately avoids named KVS and RequestQueue
state. The caller owns persistence and passes the exact accepted state forward.

#### Can I rerun safely after an ambiguous push?

Not blindly. A new run can create another start or result event. Reconcile the
original run first.

#### Is one exception row one charge?

No. One complete delivered aggregated report is the result unit whether it has
one, two, or one thousand material rows.

#### Why does the Dataset not contain receipts?

It is written before post-push facts exist. KVS OUTPUT is the authoritative
terminal receipt.

#### Are HTTPS references checked online?

No. Their syntax is validated and the string may be retained, but runtime makes
no request.

#### Does a digest anonymize a BOL or booking value?

No. It avoids returning the raw value but remains linkable evidence and must be
protected under your data policy.

#### What does complete source status mean?

It is a buyer declaration about the submitted snapshot. It is not independent
proof that a carrier or terminal source was complete.

#### Can I automate a dispute or carrier claim?

No. Recommendations are unsent review suggestions. A qualified person must
check evidence, contracts, rights, and context.

#### Is the synthetic demo operational evidence?

No. It is a fixed free contract demonstration only.

### Sources and rights

Runtime uses no external provider. All event, container, ETA, free-time, tariff,
carrier, and reference facts come from the buyer's submitted snapshot. You must
own or be authorized to process, transform, store, and route those facts.

Public accessibility, a portal URL, EDI message, API response, or customer file
does not itself grant downstream commercial rights. Retain your licences,
contracts, customer instructions, source terms, attribution duties, and data
processing records outside the Actor.

The source-rights registry cites public DCSA semantic material as unfetched
reference context. No DCSA page or artifact is bundled or called. No carrier,
terminal, port, marketplace, AIS, customs, billing, or identity provider is
queried. There is no endorsement or official integration claim.

This Actor is not legal advice, a carrier performance rating, a tariff service,
an invoice validator, a customs tool, or an automatic claims system. Its narrow
claim is that it deterministically transforms a customer-authorized bounded
snapshot into evidence, uncertainty, continuation, and current-run receipt
facts for human review.

# Actor input Schema

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

Stable identifier for one customer-owned monitoring series.

## `mode` (type: `string`):

Use snapshot for customer events or synthetic\_demo for the one exact canonical zero-provider public example. The demo accepts only the published fixture values; runtime rejects any changed field, extra row, customer row, or secret before effects.

## `sourceStatus` (type: `string`):

Declare whether this customer-supplied snapshot is complete, partial, or unavailable.

## `rightsAttestation` (type: `object`):

Required customer declaration. Apify Input Schema v1 can serialize false here; the Actor runtime requires all three declarations to be exactly true and rejects otherwise before provider, Dataset, billing, state, lock, intent, or delivery effects. Do not submit credentials, secrets, or data you are not authorized to use.

## `containers` (type: `array`):

At least one and at most 1,000 closed records. Snapshot accepts customer containers; synthetic\_demo accepts exactly one fixed Actor-owned Synthetic Ocean record and rejects substitutions before effects. BOL and booking values are never returned raw.

## `events` (type: `array`):

At least one and at most 50,000 events. Snapshot accepts customer events; synthetic\_demo accepts exactly the two fixed Actor-owned events in the public fixture and rejects substitutions or extra rows before effects. Safe references are validated but never fetched.

## `tariffAssumptions` (type: `object`):

Customer-supplied USD/day assumptions. No terminal calendar or carrier tariff is fetched.

## `continuationState` (type: `object`):

Optional exact nextContinuationState from a previous successful complete run. The Actor does not store this state in a named KVS; pass it back to compare the next customer snapshot.

## Actor input object example

```json
{
  "watchId": "customer-watch-1",
  "mode": "snapshot",
  "sourceStatus": "complete",
  "rightsAttestation": {
    "customerControlsOrIsAuthorizedToUseData": true,
    "noCredentialsOrSecretsSubmitted": true,
    "unfetchedReferencePolicyAccepted": true,
    "attestedAt": "2026-08-09T09:00:00Z",
    "attestorId": "customer-operator-1"
  },
  "containers": [
    {
      "containerNumber": "MSCU1234566",
      "carrier": "customer-declared-carrier",
      "billOfLading": null,
      "bookingNumber": null,
      "promisedEta": "2026-08-12T12:00:00Z",
      "freeTimeEnd": "2026-08-15T12:00:00Z",
      "originUnlocode": "NLRTM",
      "destinationUnlocode": "USLAX"
    }
  ],
  "events": [
    {
      "eventId": "customer-event-1",
      "containerNumber": "MSCU1234566",
      "eventType": "gate_in",
      "eventTime": "2026-08-08T09:00:00Z",
      "receivedAt": "2026-08-08T09:05:00Z",
      "locationUnlocode": "NLRTM",
      "plannedLocationUnlocode": null,
      "plannedTime": null,
      "source": "customer-system",
      "reference": "ref:customer-evidence-1"
    }
  ],
  "tariffAssumptions": {
    "currency": "USD",
    "demurragePerDay": 75,
    "detentionPerDay": 50
  }
}
```

# Actor output Schema

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

KVS record with final delivery, billing, baseline, replay, current-run facts, and the exact caller-carried nextContinuationState when a complete customer snapshot is confirmed.

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

Default Dataset items containing receipt-free pre-push decision evidence.

# 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 = {
    "watchId": "customer-watch-1",
    "mode": "snapshot",
    "sourceStatus": "complete",
    "rightsAttestation": {
        "customerControlsOrIsAuthorizedToUseData": true,
        "noCredentialsOrSecretsSubmitted": true,
        "unfetchedReferencePolicyAccepted": true,
        "attestedAt": "2026-08-09T09:00:00Z",
        "attestorId": "customer-operator-1"
    },
    "containers": [
        {
            "containerNumber": "MSCU1234566",
            "carrier": "customer-declared-carrier",
            "billOfLading": null,
            "bookingNumber": null,
            "promisedEta": "2026-08-12T12:00:00Z",
            "freeTimeEnd": "2026-08-15T12:00:00Z",
            "originUnlocode": "NLRTM",
            "destinationUnlocode": "USLAX"
        }
    ],
    "events": [
        {
            "eventId": "customer-event-1",
            "containerNumber": "MSCU1234566",
            "eventType": "gate_in",
            "eventTime": "2026-08-08T09:00:00Z",
            "receivedAt": "2026-08-08T09:05:00Z",
            "locationUnlocode": "NLRTM",
            "plannedLocationUnlocode": null,
            "plannedTime": null,
            "source": "customer-system",
            "reference": "ref:customer-evidence-1"
        }
    ],
    "tariffAssumptions": {
        "currency": "USD",
        "demurragePerDay": 0,
        "detentionPerDay": 0
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/container-exception-evidence").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 = {
    "watchId": "customer-watch-1",
    "mode": "snapshot",
    "sourceStatus": "complete",
    "rightsAttestation": {
        "customerControlsOrIsAuthorizedToUseData": True,
        "noCredentialsOrSecretsSubmitted": True,
        "unfetchedReferencePolicyAccepted": True,
        "attestedAt": "2026-08-09T09:00:00Z",
        "attestorId": "customer-operator-1",
    },
    "containers": [{
            "containerNumber": "MSCU1234566",
            "carrier": "customer-declared-carrier",
            "billOfLading": None,
            "bookingNumber": None,
            "promisedEta": "2026-08-12T12:00:00Z",
            "freeTimeEnd": "2026-08-15T12:00:00Z",
            "originUnlocode": "NLRTM",
            "destinationUnlocode": "USLAX",
        }],
    "events": [{
            "eventId": "customer-event-1",
            "containerNumber": "MSCU1234566",
            "eventType": "gate_in",
            "eventTime": "2026-08-08T09:00:00Z",
            "receivedAt": "2026-08-08T09:05:00Z",
            "locationUnlocode": "NLRTM",
            "plannedLocationUnlocode": None,
            "plannedTime": None,
            "source": "customer-system",
            "reference": "ref:customer-evidence-1",
        }],
    "tariffAssumptions": {
        "currency": "USD",
        "demurragePerDay": 0,
        "detentionPerDay": 0,
    },
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/container-exception-evidence").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 '{
  "watchId": "customer-watch-1",
  "mode": "snapshot",
  "sourceStatus": "complete",
  "rightsAttestation": {
    "customerControlsOrIsAuthorizedToUseData": true,
    "noCredentialsOrSecretsSubmitted": true,
    "unfetchedReferencePolicyAccepted": true,
    "attestedAt": "2026-08-09T09:00:00Z",
    "attestorId": "customer-operator-1"
  },
  "containers": [
    {
      "containerNumber": "MSCU1234566",
      "carrier": "customer-declared-carrier",
      "billOfLading": null,
      "bookingNumber": null,
      "promisedEta": "2026-08-12T12:00:00Z",
      "freeTimeEnd": "2026-08-15T12:00:00Z",
      "originUnlocode": "NLRTM",
      "destinationUnlocode": "USLAX"
    }
  ],
  "events": [
    {
      "eventId": "customer-event-1",
      "containerNumber": "MSCU1234566",
      "eventType": "gate_in",
      "eventTime": "2026-08-08T09:00:00Z",
      "receivedAt": "2026-08-08T09:05:00Z",
      "locationUnlocode": "NLRTM",
      "plannedLocationUnlocode": null,
      "plannedTime": null,
      "source": "customer-system",
      "reference": "ref:customer-evidence-1"
    }
  ],
  "tariffAssumptions": {
    "currency": "USD",
    "demurragePerDay": 0,
    "detentionPerDay": 0
  }
}' |
apify call zinin/container-exception-evidence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/container-exception-evidence"
        }
    }
}

```

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/0z2O5cKOX6uMZsMvJ/builds/MXOcrPPpHh3pox9aH/openapi.json
