Import a container spreadsheet
A customer or partner sends you a spreadsheet of containers. Conterminal reads that file, guesses which column is which, and stages the rows for your operations list. Forwarder and importer workspaces create managed tracking; carrier workspaces link strong delivery-order matches or create document-optional native operations records.
9 minute read · Updated August 2, 2026
Auto-apply depends on your workspace type.
Forwarder and importer tracker imports still auto-confirm clean rows. Carrier imports do not: every parsed row stays staged until you select rows or choose Confirm all valid containers. A carrier row needs only a valid container number; ETA, terminal, customer, and delivery-order document details can be added later or never supplied.
Before you start
Forwarder and importer workspaces reach Import tracker from the operations list. Carrier workspaces open + Add Documents in Document Review and choose Spreadsheet. If the page bounces you back to operations, your active workspace is not eligible — see why a page shows Access Denied.
The hard limits
| Limit | Value | What happens when you cross it |
|---|---|---|
| File types | .xlsx, .xls, .csv | The upload is refused with “Upload an Excel (.xlsx, .xls) or CSV (.csv) tracker.” A PDF tracker cannot go through this screen at all. |
| File size | 25 MB | Checked before the file is stored: “Tracker upload is larger than 25 MB. Split it into smaller files and try again.” |
| Rows per tracker | 50,000 | Counted across all sheets after upload, so this one fails during parsing, not at the upload form. The import ends as Import failed. |
| Rows per re-extract | 2,000 pending | A column-mapping change refuses to run while more than 2,000 rows are still pending review. Nothing is written. |
| Rows shown at once | 200 | The grid pages in 200 rows at a time behind a Load more rows button. |
What each workspace requires
The parser recognizes the same columns in every workspace, but the hard apply gate differs:
- Carrier import
- A valid 11-character container number is the only required field. ETA, pickup terminal, customer, and document data are optional.
- Forwarder / importer identifier
- A container number, master bill of lading, or booking number. A row with none of the three is an Error and cannot be approved.
- Forwarder / importer details
- A normalizable ETA and pickup terminal are required for managed tracking. Missing values remain review exceptions until repaired.
- One worksheet, plain headers
- The upload form's own guidance: one worksheet per tracker is best, and pivot tables work poorly. Every sheet with data is processed, and each gets its own column mapping.
Uploading
- Open the spreadsheet importer. Forwarder and importer workspaces see Import tracker and Tracker file. Carrier workspaces see Import operations records and Container spreadsheet. Both accept .xlsx, .xls, or .csv up to 25 MB.
- Choose the file. There is no drag-and-drop zone and no multi-file select — one file per upload.
- Upload. Select Upload tracker or Upload spreadsheet, depending on workspace. The button sits at the bottom right of the screen. Cancel returns you to operations without uploading.
- Wait on the tracker page. You are redirected to the import's own page, titled Tracker import or Operations import with your file name underneath. It polls every couple of seconds on its own; you do not need to refresh.
If the upload is rejected you stay on the upload form with a red banner. The six messages you can get are “Select a tracker file (.xlsx, .xls, or .csv) to upload.”, “Tracker upload is larger than 25 MB. Split it into smaller files and try again.”, “Tracker file is empty. Re-export and try again.”, “Upload an Excel (.xlsx, .xls) or CSV (.csv) tracker.”, “Your workspace cannot upload trackers.”, and “We could not save the tracker upload. Try again.”
What runs before you see rows
The tracker page shows a single status line while work is in flight, with the note “This page refreshes automatically.” The four working states read:
- Queued
- “Queued — your tracker is in line for parsing.” The file is stored but the parser has not picked it up.
- Parsing tracker
- “Parsing tracker — reading sheets and mapping columns…” The parser is reading the workbook, matching headers against known aliases, and falling back to a model only for sheets whose headers it cannot place.
- Re-applying column mapping
- “Re-applying column mapping…” You changed the mapping and a re-extract is running.
- Applying approved rows
- “Applying approved rows…” Rows are being written to your operations list.
For forwarder and importer tracker imports, the auto-confirm pass runs immediately in batches of 500. It takes every row that is in the Ready bucket, has no missing required fields, and has a usable identifier, and applies it — created as a new tracked container, or matched onto one you already track. Those rows are then attributed to you as the confirming user. After that, Conterminal queues LongShorty lookups for the new containers so the terminal, rail, and steamship-line sites get checked for milestones. Carrier imports skip auto-confirm and leave all rows staged for an operator decision.
The counts on this screen are written twice and can disagree with the grid. Straight after parsing, the header line and the three tiles still show the parse-time totals — including rows that were just auto-confirmed and are no longer in the grid. They are recalculated against pending rows only the first time you edit a cell or confirm a selection, which is when High confidence usually drops to zero. Nothing is lost; the tiles simply catch up late. Trust the grid.
Reading the review grid
The review screen is headed Parsing complete — pending review and reads something like “41 rows ready to review (1,204 detected).” The first number is what still needs a decision; the number in parentheses is how many data rows the parser counted in the workbook.
Three tiles sit under that line. On a wide screen they are labeled High confidence, Needs review, and Errors; on a phone the same three are abbreviated to Ready, Review, and Errors. The Errors tile turns amber when it is above zero.
Every row carries a status badge, and the grid is sorted worst-first — errors, then unmapped, then needs-review, then ready — so the rows that block you are always at the top:
- Ready
- Every parser-required field is present and the parser was confident about the columns it used. Forwarder/importer rows may auto-confirm before the page loads; carrier rows remain visible until you confirm them.
- Needs review
- Complete, but the parser's average confidence in the columns it read was under 60%. These can be approved after review. In a carrier import, a valid container remains enough even when optional values are uncertain.
- Unmapped
- At least one managed-tracking field came back empty. Forwarder/importer rows must be repaired. Carrier rows can still be confirmed when the container is valid because those fields are optional there.
- Error
- No usable identifier. Carrier imports specifically require a valid container number; forwarder/importer imports accept container, bill of lading, or booking number.
The Row column is a button. It shows #12 over the source location — the sheet name and the original spreadsheet row, as Sheet1 · src 14. Those two numbers differ: the # number is the position in this import, and src is the line in the customer's file, which is the one to quote back to them. Selecting it opens a side panel with Raw cells — the untouched spreadsheet values — Normalized values, and any Warnings.
On a phone the table is replaced by one card per row showing the container, the row number, the badge, any missing fields, and a Review row button that opens the same panel with editable fields inside it.
Fixing the column mapping
When a whole column landed on the wrong field — or on nothing — fix the mapping rather than editing rows one at a time. The collapsed Column mapping panel sits between the tiles and the grid. Its right-hand side is a live summary: either all required fields covered or missing required: pickup_terminal in amber.
- Expand the panel. You get one table per worksheet, with columns Col, Source header, Samples, and Mapped field. The samples are up to three real values from that column, which is normally enough to recognize what it holds even when the header is useless.
- Repoint the column. Each row's dropdown lists every field Conterminal understands, with — Unmapped — at the top and (required) appended to container_number, eta, and pickup_terminal. Changing anything raises an unsaved chip in the panel header.
- Select Re-extract rows. The button reads Re-extracting… while it runs. Cancel next to it discards your draft and returns to the mapping currently saved.
The panel states its own contract: “Re-extract runs deterministically from stored raw values — no LLM call, no original-file re-read. Only rows still pending review are recomputed.” That is worth internalizing. Re-extract cannot recover a column the parser never captured, and it will not disturb rows that were already applied.
Because only pending rows are recomputed, a mapping fix arrives too late for the rows that were auto-confirmed at parse time. If a column was mapped wrongly but the rows still looked complete, they are already on your operations list with the wrong value. Re-extract will not correct them — fix those on the shipment itself.
Three refusals happen before any write, so the rows are untouched. Above 2,000 pending rows you get a message that names the exact count and tells you to split the original spreadsheet or approve some rows first. And if the import is no longer in review — already confirmed, failed, or archived — you get “Cannot remap an import in status "confirmed".” If another tab saved a mapping or edited pending rows first, you are asked to reload before re-extracting again.
Editing rows
Seven fields are editable directly in the grid: Container, MBL, Vessel, Voyage, ETA, Pickup terminal, and LFD. Container shows a placeholder of APMU1234567; the two date fields show YYYY-MM-DD.
- Type into the cell. Press Enter to commit, or click away — leaving the field saves it.
- Press Escape to abandon what you typed. The cell snaps back to its stored value and nothing is sent.
- Watch the value settle. Your entry is normalized on the server and written back, so 5/15/26 in an ETA becomes 2026-05-15 and a container number is rewritten to its canonical form. If the cell changes after you leave it, that is the normalizer, not a mistake.
- A failed save rolls the cell back to its previous value and prints the reason underneath in red, usually “Could not save that change.”
Each successful edit re-settles that row: the badge, the missing: list, and the tiles all update without a reload. Filling in a missing ETA moves a row out of Unmapped on the spot.
Booking number is not one of the seven editable fields. If a row is an Error because the parser never found an identifier, the only identifiers you can supply from the grid are the container number and the MBL. A tracker that identifies shipments purely by booking number has to be fixed through the column mapping instead, or re-sent by the partner with a container column.
Approving rows
Carrier imports also provide Confirm all valid containers. It drains the import in independent 500-row database transactions, so files larger than 25 rows do not become one browser payload or one long-running transaction. The 50,000-row parser limit remains the effective file ceiling.
Select rows with the checkboxes. The header checkbox is Select all visible rows — it takes the rows currently loaded, so with a long import you must Load more rows first if you mean the whole thing.
A bar appears at the bottom of the screen showing 7 selected, a Clear button, and a blue Confirm 7 rows button that reads Applying... while it works.
One bad selected row blocks that selection.
If any row in your selection cannot be applied, the Confirm button is disabled and the bar names the first offender — Row #12 can't be approved (missing: eta, pickup_terminal). The server re-checks the same rules, so a stale selection is rejected outright with “Cannot approve row: …” and nothing at all is applied. Deselect the offending row, or fix it, then confirm again. Approving in smaller batches makes this far less painful on a messy tracker. Carrier Confirm all valid containers skips rows without a valid container and leaves them in review.
On success the approved rows drop out of the grid and a green summary appears, for example “Approved 12 rows: 9 created, 2 updated, 1 linked.” Read those words literally:
- created
- Forwarder/importer: a new managed tracked container. Carrier: a native delivery-order job shell with no document requirement.
- updated
- A managed-tracking row matched a container you already track and refreshed it. Carrier imports do not overwrite existing delivery orders through this count.
- linked
- Carrier imports link only when exactly one active delivery order matches the container plus a secondary identifier such as MBL, booking/PO, or broker reference. Container alone never merges jobs.
- skipped / errored
- Skipped means the row had been discarded earlier. Errored means the write itself failed; the row comes back into the grid as an Error with an apply_failed warning explaining why.
Once nothing is left pending, the page flips to a Confirmed panel — “All 1,204 approved rows are live on the operations list.” — with a View operations button. That figure is the parse-time detected count, not a recount of what was written, so treat it as the size of the file rather than a receipt. Check the container dashboard for what actually landed.
When another tab changes the import
Reload before retrying a stale edit or mapping.
A re-extract now saves the mapping, every pending row rewrite, and the refreshed counts together. If two tabs submit different mappings, one complete mapping wins and the other is rejected with “This import changed in another tab. Reload before re-extracting again.” The rejected attempt makes no partial changes.
Reload the page and inspect the mapping that won. If your change is still needed, apply it again from the refreshed panel. Re-extracting remains deterministic: the same saved raw cells and mapping produce the same normalized row values.
Individual row edits use the same protection. If a row was applied, remapped, or edited elsewhere after the page loaded, Conterminal leaves the newer value untouched and asks you to reload. If a fresh retry still fails, contact support with the import's URL and the exact message before approving more rows.
Duplicate uploads
Uploading the same file twice does not create a second import. Conterminal fingerprints the file's contents and, if your workspace already has an import of that exact file that has not failed or been archived, it reuses it and takes you to the existing import instead. The upload form says as much: “Re-uploading the same file is safe; we detect duplicates and reuse the existing import.”
The fingerprint is of the bytes, not the name. Renaming the file makes no difference; opening it in Excel and saving it, even without changing a cell, usually does — you will get a fresh, separate import. If a partner sends you a genuinely updated tracker, that new file will import on its own and the overlapping containers show up as updated rather than duplicates.
Re-uploading an identical file does more than open the old page: it re-runs the parser over that same import and rewrites its rows in place by sheet position. Any cell corrections you made in the grid are replaced by the parser's own values. This is genuinely useful when an import is wedged in Queued — it is the way to re-fire the parse — but do not use it as a refresh once you have started editing.
Troubleshooting
The import sits on “Queued” and never moves
The file uploaded but the parser was never started. If this happened at upload you will have seen “Upload saved, but the parser could not be started. Open the tracker and use Retry parse.” There is no Retry parse button on the tracker page today — that message names a control that does not exist. The working recovery is to go back to Import tracker and upload the exact same file again: the duplicate check reuses this same import and re-fires the parse. If it queues a second time, send support the import URL.
“Import failed” with a row-limit message
“This tracker has more than 50,000 rows. Split it into smaller files and upload again.” The count is across every sheet in the workbook, so a tracker with several large tabs can trip it even when no single sheet looks big. Split the file and upload the pieces; each becomes its own import.
“Import failed” with a parse or model error
“The parser could not read this tracker. Verify the file opens in Excel and re-upload.” means the workbook itself would not open — most often a file that is really HTML or a report export with an .xls extension. “The parser ran into a model error while reading this tracker. Try uploading again in a minute.” is transient; wait and re-upload. A failed import is excluded from the duplicate check, so re-uploading the same file after a failure correctly starts a fresh import.
The whole batch is refused because of one row
Approve applies all-or-nothing to the rows you selected. The bar names the first blocking row as Row #N can’t be approved (…). If instead you get “Some selected rows are no longer accessible — reload the page.”, someone else changed those rows while you had them selected; reload and reselect. Selecting fewer rows per approval makes both of these much easier to work through.
The tiles show zero, or disagree with the grid
The counts are recalculated against rows still pending review, and only when you edit a cell or confirm a selection. High confidence dropping to zero normally means the clean rows were auto-confirmed at parse time and are already live — not that they vanished. Conversely, immediately after parsing the tiles can be higher than the grid, because they still hold the parse-time totals. The grid is authoritative in both directions.
Rows show missing: eta, pickup_terminal
The parser found no column it could map to those fields, or the cells are empty. Open Column mapping and check whether the tracker carries them under an unusual header. Forwarder/importer rows cannot be approved without them. Carrier rows can still be confirmed when the container is valid; ETA and terminal are optional for a native job shell.
A row is an Error but the container looks fine
Open the row panel and compare Raw cells against Normalized values. A container number is only accepted in canonical ISO form, so an entry carrying a check-digit typo, extra punctuation, or a trailing size code is discarded rather than guessed at. Retype it in the Container cell and the row re-settles.
The grid says “No rows in this import.”
Nothing is pending. Either every row was applied already, or the parser wrote no rows at all — which happens when every sheet was header-only or unreadable. Check the header line: if it reads 0 rows ready to review with a non-zero detected count, the rows were applied, not lost.
“Loading rows…” stays on screen, or rows never appear
The page landed on the review state before the rows were fetched and is populating them in the background. If it settles on a red error instead, reload the page — the fetch is retried on every visit. Persistent failure with rows you know exist is worth a support ticket with the import URL.
“We could not find that tracker import.”
“…It may have been archived or you may not have access to it.” The import belongs to another workspace, or it was archived. An archived import shows its own panel — “This tracker import was archived. Upload a new tracker to ingest more containers.” — and cannot be reopened; upload the tracker again.
“Unknown state”
The page reports a status it does not know how to render and suggests refreshing. Refresh once. If it persists, the import is in an unexpected state — send support the import URL and the status string it quoted rather than re-uploading.
Approved containers show no tracking activity yet
Approving a row creates the tracked container and queues LongShorty to sign in to the terminal, rail, and steamship-line systems for it. That happens after the apply, not during it, so a brand-new import will show containers with no milestones for a while. If a container still has nothing after a day, check that its terminal and steamship line are ones your workspace has tracking coverage for.