# ASN & Carton Packing Reconciliation (`wheresprada/asn-packing-reconciliation`) Actor

Compare current purchase orders, ASN notices and actual packing exports by shipment, carton and PO line. Flag quantity and missing-carton differences, preserve incomplete records, and avoid unsupported unit conversions.

- **URL**: https://apify.com/wheresprada/asn-packing-reconciliation.md
- **Developed by:** [Mahruf Hossain](https://apify.com/wheresprada) (community)
- **Categories:** Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.39 / completed asn carton review

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ASN & Carton Packing Reconciliation

Check whether an advance shipping notice describes the cartons your warehouse says it packed. ASN & Carton Packing Reconciliation compares three structured exports: current purchase order lines, declared ASN carton lines and actual packing carton lines. It highlights quantity differences, missing carton records, unsupported units and cumulative packing above the current order.

This is a focused review for suppliers and logistics teams that already use an EDI or warehouse system. It does not translate X12, generate labels, transmit an ASN or certify retailer compliance. The benefit is an independent comparison of what was ordered, what was declared and what was recorded as packed.

### Key features

- Compare ASN and packing quantities at shipment, carton and PO-line level.
- Prevent differences in separate cartons from cancelling into a misleading matching shipment total.
- Aggregate packing across split shipments against the current order quantity.
- Use exact decimal arithmetic with up to three fractional places.
- Keep unsupported SKU or unit mappings unresolved rather than inventing conversions.
- Ignore exact duplicate stable records while rejecting conflicting IDs or PO revisions.
- Preserve incomplete export scope explicitly, without declaring missing notices to be shipping defects.

### Who is it for?

Retail suppliers preparing shipment notices, 3PL teams reviewing warehouse exports and EDI coordinators investigating mismatches are the intended users. You need authorized structured data from your current systems and a consistent mapping between their order, line, shipment and carton identifiers.

An operations owner should review findings before changing a shipment or notice. Exported packing data does not independently establish what physically left a warehouse. A recorded ASN difference is not proof that a retailer will issue a chargeback, and this tool does not calculate or recover chargebacks.

### Real-world uses

Review a shipment before transmitting its final notice. Investigate why a shipment total matches while individual cartons disagree. Check cumulative fulfillment when one PO is split across several shipments. Find an ASN line that references an unknown current PO line. Identify units that require an explicit mapping before anyone compares case quantities with individual pieces.

### Quick start

Run the supplied example without credentials. Its invented order is for ten units, its ASN declares ten and its packing record says nine. The review returns a signed ASN-minus-packed difference of `1.000` and leaves one ordered unit open. That open quantity is not itself classified as a defect.

For production, export the agreed current PO revision and the relevant shipment history. Normalize identifiers deliberately. If one system uses a carton SSCC and another an internal box ID, establish their mapping outside this Actor. Do not mark coverage complete until you have checked the export scope.

### Input example

```json
{
  "coverageComplete": true,
  "orderLines": [{"poId":"PO-DEMO","lineId":"1","sku":"SKU-DEMO","uom":"EA","quantity":"10"}],
  "asnLines": [{"id":"ASN1","shipmentId":"SHIP1","cartonId":"BOX1","poId":"PO-DEMO","lineId":"1","sku":"SKU-DEMO","uom":"EA","quantity":"10"}],
  "packedLines": [{"id":"PACK1","shipmentId":"SHIP1","cartonId":"BOX1","poId":"PO-DEMO","lineId":"1","sku":"SKU-DEMO","uom":"EA","quantity":"9"}]
}
```

#### Input parameters

| Parameter | Required | Meaning |
|---|---|---|
| `coverageComplete` | Yes | Confirms the current PO and relevant ASN/packing scope is complete |
| `orderLines` | Yes | 1–2,000 current lines with PO ID, line ID, SKU, unit and quantity |
| `asnLines` | Yes | 0–5,000 declared carton lines with stable record and shipment IDs |
| `packedLines` | Yes | 0–5,000 actual packing-export lines with the same mapped identifiers |

Quantities are nonnegative decimal strings with no more than three fractional digits. Numbers, negative credits and scientific notation are rejected. Identifiers permit ASCII letters, digits and `_.:-`, up to 80 characters. The entire input must fit within 2 MB.

Empty ASN or packing arrays are allowed, but must be supplied. Current PO lines cannot be empty. Conflicting versions of the same PO line fail; select the agreed revision first. Carton IDs are customer-mapped keys, not verified GS1 registrations. No barcode check-digit or retailer registration claim is made.

### Output and verified example

The full report is stored as one default dataset item and the `OUTPUT` key-value record. The packaged example produces one carton comparison and one finding:

```json
{
  "shipmentId": "SHIP-DEMO",
  "cartonId": "BOX-DEMO",
  "poId": "PO-DEMO",
  "lineId": "1",
  "sku": "SKU-DEMO",
  "uom": "EA",
  "asn": "10.000",
  "packed": "9.000",
  "signedAsnMinusPacked": "1.000",
  "state": "ASN_PACKED_QUANTITY_DIFFERENCE"
}
```

Additional fields record the number of contributing ASN and packing records. `orderReview` shows ordered, ASN and packed totals per PO line, plus remaining ordered quantity. `findings` contains supported differences; `unresolved` identifies records that could not be compared safely. `summary` includes ignored exact duplicates and unresolved-record counts. `checkedAt` is processing time, not shipment time.

### How comparisons work

First, the Actor validates current PO lines and detects conflicting revisions. It then validates each shipment record and matches it to its PO line. SKU and unit must match exactly. It aggregates declared and packed quantities within each shipment/carton/PO-line key, then compares those ledgers. Finally it compares cumulative packing with the current ordered quantity.

A partial fill is labeled `OPEN_QUANTITY_NOT_A_DEFECT`: it may be a legitimate backorder or planned split. An observed overfill is flagged only when the relevant scope is complete. With incomplete scope, comparisons stay unresolved. A SKU or unit mismatch also makes the affected order line unresolved; no automatic substitution or case-to-piece conversion occurs.

Stable IDs are scoped by shipment and record kind. Exact duplicate exports are ignored with a count. Different IDs are retained as separate records, even when quantities look similar. This avoids deleting legitimate repeated lines merely because they resemble duplicates.

### Pricing

Each completed review costs **$0.39**, including explicit unresolved results. Invalid input that cannot produce a review has no completed-review event. The charge is per bounded report, not per difference or carton.

Ten completed reviews cost $3.90 in Actor events; 100 cost $39; 1,000 cost $390. Apify platform usage and plan-specific terms can apply separately. Check the live pricing display and set a suitable run spending limit. Scheduled reruns are new reports and are charged again; the Actor does not maintain a permanent cross-run duplicate ledger.

### API integration and scheduling

```javascript
import { ApifyClient } from 'apify-client';
import fs from 'node:fs';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const input = JSON.parse(fs.readFileSync('shipment-review.json', 'utf8'));
const run = await client.actor('wheresprada/asn-packing-reconciliation').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].findings);
```

Schedule your existing exports, then pass a fresh bounded input after the exports finish. Static Apify task input does not fetch current WMS records automatically. Preserve original authorized references for investigation and inspect coverage before forwarding findings to operations. This Actor performs no shipping or accounting writes.

### Limits and accuracy

The runtime budget is 128 MB and 30 seconds. Input beyond the documented line or byte limits fails rather than being silently truncated. Split large reviews by a deliberate scope, remembering that cumulative overfill cannot be established across omitted shipments.

No X12 or EDIFACT parser, label generator, transport connector, quantity conversion or customer-specific compliance engine is included. The review uses the quantities and revisions you supply. It cannot establish actual physical contents, approved substitutions, cancellations not reflected in the current PO, or retailer acceptance. Do not use it as the sole authorization to ship.

### Privacy and security

Provide only records you are authorized to process. Customer addresses, contact details, credentials and item descriptions are unnecessary. Stable pseudonyms can be used if consistent across exports. Input and output remain in Apify storage under your permissions and retention settings. There are no carrier, retailer or warehouse requests from the Actor. Restrict dataset sharing and remove old operational records according to your policy.

### Troubleshooting and FAQ

**Why is a line unresolved?** Check its current PO reference, SKU, unit and confirmed export coverage.

**Why are two cartons reported when the shipment total matches?** Different carton allocations are intentionally compared separately. An incorrect carton should not disappear inside a correct overall total.

**Can I upload raw 856 files?** No. Supply structured lines exported or mapped by your authorized EDI system.

**Does an open quantity mean a missed shipment?** No. It may be a planned partial fill, so the Actor labels it without declaring a defect.

**Can it convert CASE to EA?** No. Apply a verified pack-size mapping upstream and preserve its evidence.

**Why did a repeated record fail?** The same scoped ID had conflicting content. Resolve the source inconsistency instead of assigning invented replacement IDs.

### Support

Use the Actor's Apify Store issue section. Include the run ID, expected comparison and a minimal redacted example with stable identifiers. Do not include retailer credentials or private customer data. Supply the input units and revision context when reporting a quantity issue so the behavior can be reproduced accurately.

# Actor input Schema

## `coverageComplete` (type: `boolean`):

Only true when current PO revisions and relevant ASN/packing history are complete. Otherwise missing/mismatch conclusions stay unresolved.

## `orderLines` (type: `array`):

1-2000: poId,lineId,sku,uom,quantity. Decimal quantity strings up to 3 places. Supply only the agreed current PO revision.

## `asnLines` (type: `array`):

0-5000: id,shipmentId,cartonId,poId,lineId,sku,uom,quantity. Stable mapped carton keys; no GS1 registration claim.

## `packedLines` (type: `array`):

0-5000 actual packing records using the same fields and stable carton mapping as ASN. Empty allowed, must be present. No guessing unit conversions.

## Actor input object example

```json
{
  "coverageComplete": true,
  "orderLines": [
    {
      "poId": "PO-DEMO",
      "lineId": "1",
      "sku": "SKU-DEMO",
      "uom": "EA",
      "quantity": "10"
    }
  ],
  "asnLines": [
    {
      "id": "ROW-DEMO",
      "shipmentId": "SHIP-DEMO",
      "cartonId": "BOX-DEMO",
      "poId": "PO-DEMO",
      "lineId": "1",
      "sku": "SKU-DEMO",
      "uom": "EA",
      "quantity": "10"
    }
  ],
  "packedLines": [
    {
      "id": "ROW-DEMO",
      "shipmentId": "SHIP-DEMO",
      "cartonId": "BOX-DEMO",
      "poId": "PO-DEMO",
      "lineId": "1",
      "sku": "SKU-DEMO",
      "uom": "EA",
      "quantity": "9"
    }
  ]
}
```

# Actor output Schema

## `report` (type: `string`):

No description

## `reports` (type: `string`):

No description

# 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 = {
    "coverageComplete": true,
    "orderLines": [
        {
            "poId": "PO-DEMO",
            "lineId": "1",
            "sku": "SKU-DEMO",
            "uom": "EA",
            "quantity": "10"
        }
    ],
    "asnLines": [
        {
            "id": "ROW-DEMO",
            "shipmentId": "SHIP-DEMO",
            "cartonId": "BOX-DEMO",
            "poId": "PO-DEMO",
            "lineId": "1",
            "sku": "SKU-DEMO",
            "uom": "EA",
            "quantity": "10"
        }
    ],
    "packedLines": [
        {
            "id": "ROW-DEMO",
            "shipmentId": "SHIP-DEMO",
            "cartonId": "BOX-DEMO",
            "poId": "PO-DEMO",
            "lineId": "1",
            "sku": "SKU-DEMO",
            "uom": "EA",
            "quantity": "9"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wheresprada/asn-packing-reconciliation").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 = {
    "coverageComplete": True,
    "orderLines": [{
            "poId": "PO-DEMO",
            "lineId": "1",
            "sku": "SKU-DEMO",
            "uom": "EA",
            "quantity": "10",
        }],
    "asnLines": [{
            "id": "ROW-DEMO",
            "shipmentId": "SHIP-DEMO",
            "cartonId": "BOX-DEMO",
            "poId": "PO-DEMO",
            "lineId": "1",
            "sku": "SKU-DEMO",
            "uom": "EA",
            "quantity": "10",
        }],
    "packedLines": [{
            "id": "ROW-DEMO",
            "shipmentId": "SHIP-DEMO",
            "cartonId": "BOX-DEMO",
            "poId": "PO-DEMO",
            "lineId": "1",
            "sku": "SKU-DEMO",
            "uom": "EA",
            "quantity": "9",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("wheresprada/asn-packing-reconciliation").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 '{
  "coverageComplete": true,
  "orderLines": [
    {
      "poId": "PO-DEMO",
      "lineId": "1",
      "sku": "SKU-DEMO",
      "uom": "EA",
      "quantity": "10"
    }
  ],
  "asnLines": [
    {
      "id": "ROW-DEMO",
      "shipmentId": "SHIP-DEMO",
      "cartonId": "BOX-DEMO",
      "poId": "PO-DEMO",
      "lineId": "1",
      "sku": "SKU-DEMO",
      "uom": "EA",
      "quantity": "10"
    }
  ],
  "packedLines": [
    {
      "id": "ROW-DEMO",
      "shipmentId": "SHIP-DEMO",
      "cartonId": "BOX-DEMO",
      "poId": "PO-DEMO",
      "lineId": "1",
      "sku": "SKU-DEMO",
      "uom": "EA",
      "quantity": "9"
    }
  ]
}' |
apify call wheresprada/asn-packing-reconciliation --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wheresprada/asn-packing-reconciliation"
        }
    }
}
```

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/OoYpTgdv2i1s7ZLGz/builds/BMhTIFOXE7WMKttTu/openapi.json
