> ## Documentation Index
> Fetch the complete documentation index at: https://terminal49-cursor-api-risk-gates-8528.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Rail carriers

> List of North American Class I and short-line rail carriers Terminal49 tracks for inland container milestones, rail last free day, and destination ETA.

export const coverageUpdatedOn = "2026-10-13";

export const railCarrierCoverage = {
  "BNSF": {
    "features": {
      "railLoaded": "unsupported",
      "railDeparted": "unsupported",
      "railArrived": "supported",
      "railUnloaded": "unsupported",
      "arrivedAtDestination": "supported",
      "available": "supported",
      "fullOut": "unsupported",
      "emptyReturned": "unsupported",
      "lastFreeDay": "supported",
      "estArrivalAtDestination": "supported",
      "podRailCarrier": "supported",
      "destinationRailCarrier": "supported",
      "t49RailEta": "supported"
    }
  },
  "UPRR": {
    "features": {
      "railLoaded": "unsupported",
      "railDeparted": "supported",
      "railArrived": "supported",
      "railUnloaded": "unsupported",
      "arrivedAtDestination": "limited",
      "available": "supported",
      "fullOut": "supported",
      "emptyReturned": "limited",
      "lastFreeDay": "supported",
      "estArrivalAtDestination": "supported",
      "podRailCarrier": "supported",
      "destinationRailCarrier": "supported",
      "t49RailEta": "supported"
    }
  },
  "NSRR": {
    "features": {
      "railLoaded": "signed_in_only",
      "railDeparted": "signed_in_only",
      "railArrived": "signed_in_only",
      "railUnloaded": "limited",
      "arrivedAtDestination": "supported",
      "available": "limited",
      "fullOut": "limited",
      "emptyReturned": "unsupported",
      "lastFreeDay": "limited",
      "estArrivalAtDestination": "signed_in_only",
      "podRailCarrier": "supported",
      "destinationRailCarrier": "supported",
      "t49RailEta": "supported"
    }
  },
  "CSXT": {
    "features": {
      "railLoaded": "limited",
      "railDeparted": "supported",
      "railArrived": "supported",
      "railUnloaded": "supported",
      "arrivedAtDestination": "supported",
      "available": "supported",
      "fullOut": "unsupported",
      "emptyReturned": "unsupported",
      "lastFreeDay": "supported",
      "estArrivalAtDestination": "supported",
      "podRailCarrier": "supported",
      "destinationRailCarrier": "supported",
      "t49RailEta": "supported"
    }
  },
  "CNRU": {
    "features": {
      "railLoaded": "supported",
      "railDeparted": "supported",
      "railArrived": "supported",
      "railUnloaded": "limited",
      "arrivedAtDestination": "supported",
      "available": "limited",
      "fullOut": "supported",
      "emptyReturned": "unsupported",
      "lastFreeDay": "supported",
      "estArrivalAtDestination": "supported",
      "podRailCarrier": "supported",
      "destinationRailCarrier": "supported",
      "t49RailEta": "supported"
    }
  },
  "CPRS": {
    "features": {
      "railLoaded": "unsupported",
      "railDeparted": "signed_in_only",
      "railArrived": "signed_in_only",
      "railUnloaded": "unsupported",
      "arrivedAtDestination": "signed_in_only",
      "available": "signed_in_only",
      "fullOut": "signed_in_only",
      "emptyReturned": "unsupported",
      "lastFreeDay": "supported",
      "estArrivalAtDestination": "supported",
      "podRailCarrier": "supported",
      "destinationRailCarrier": "supported",
      "t49RailEta": "supported"
    }
  }
};

export const railCarrierFeatures = [{
  "key": "railLoaded",
  "label": "Rail Loaded",
  "group": "Container milestones"
}, {
  "key": "railDeparted",
  "label": "Rail Departed",
  "group": "Container milestones"
}, {
  "key": "railArrived",
  "label": "Rail Arrived",
  "group": "Container milestones"
}, {
  "key": "railUnloaded",
  "label": "Rail Unloaded",
  "group": "Container milestones"
}, {
  "key": "arrivedAtDestination",
  "label": "Arrived At Destination",
  "group": "Container milestones"
}, {
  "key": "available",
  "label": "Available",
  "group": "Container milestones"
}, {
  "key": "fullOut",
  "label": "Full Out",
  "group": "Container milestones"
}, {
  "key": "emptyReturned",
  "label": "Empty Returned",
  "group": "Container milestones"
}, {
  "key": "lastFreeDay",
  "label": "Rail LFD",
  "group": "Rail attributes",
  "requirements": ["rail_plan"]
}, {
  "key": "estArrivalAtDestination",
  "label": "Carrier ETA",
  "group": "Rail attributes"
}, {
  "key": "podRailCarrier",
  "label": "POD Rail Carrier",
  "group": "Rail attributes"
}, {
  "key": "destinationRailCarrier",
  "label": "Destination Rail Carrier",
  "group": "Rail attributes"
}, {
  "key": "t49RailEta",
  "label": "T49 Rail ETA",
  "group": "Terminal49 estimates"
}];

export const railCarriers = [{
  "name": "BNSF Railway",
  "scac": "BNSF",
  "group": "US Class I"
}, {
  "name": "Union Pacific",
  "scac": "UPRR",
  "group": "US Class I"
}, {
  "name": "Norfolk Southern",
  "scac": "NSRR",
  "group": "US Class I"
}, {
  "name": "CSX",
  "scac": "CSXT",
  "group": "US Class I"
}, {
  "name": "Canadian National",
  "scac": "CNRU",
  "group": "Canadian Class I"
}, {
  "name": "Canadian Pacific / KCS",
  "scac": "CPRS",
  "group": "Canadian Class I"
}];

export const ShippingCarrierCoverageDetails = ({features, coverage, Status}) => {
  const sections = [{
    label: "Port of Lading (POL)",
    group: "Origin",
    shortLabels: true
  }, {
    label: "Port of Discharge (POD)",
    group: "Destination port",
    shortLabels: true
  }, {
    label: "Final Destination",
    group: "Inland destination",
    shortLabels: true
  }, {
    label: "Container Details",
    group: "Container attributes"
  }, {
    label: "Core Transport Milestones",
    group: "Container milestones"
  }, {
    label: "Extended Transport Milestones",
    group: "Additional milestones"
  }, {
    label: "Other Events",
    group: "Other events"
  }];
  const FeatureBadges = ({items}) => <ul className="shipping-feature-badges">
      {items.map(feature => <li key={feature.key} data-feature-key={feature.key}>
          {feature.href ? <a href={feature.href} className="inline-flex max-w-full rounded-full hover:underline focus-visible:outline focus-visible:outline-2 focus-visible:outline-green-600"><Status status={coverage?.features?.[feature.key]} label={feature.label} availability /></a> : <Status status={coverage?.features?.[feature.key]} label={feature.label} availability />}
        </li>)}
    </ul>;
  return <dl className="shipping-coverage-details text-sm text-gray-900 dark:text-white">
      {sections.map(section => <div key={section.group} className="shipping-feature-group">
          <dt>{section.label}</dt>
          <dd>
            <FeatureBadges items={features.filter(feature => feature.group === section.group).map(feature => section.shortLabels ? {
    ...feature,
    label: feature.label.replace(/^(POL|POD|Destination) /, "")
  } : feature)} />
          </dd>
        </div>)}
    </dl>;
};

export const CarrierCoverageRows = ({rows, features, coverage, selectedScac, toggleRow, idPrefix, summaryFeatures, summaryLabel, carrierLabel, availability, Status, Details}) => {
  return <div className="shipping-coverage-table rounded border border-gray-200 text-sm dark:border-white/15">
      <div className="shipping-carrier-columns shipping-table-heading bg-gray-50 text-xs font-medium text-gray-600 dark:bg-white/5 dark:text-white/70" aria-hidden="true"><span>{carrierLabel}</span><span>SCACs</span><span>{summaryLabel}</span><span /></div>
      {rows.map(carrier => {
    const isSelected = selectedScac === carrier.scac;
    const detailId = `${idPrefix}-details-${carrier.scac}`;
    const buttonId = `${idPrefix}-toggle-${carrier.scac}`;
    return <article key={carrier.scac} data-carrier-scac={carrier.scac} className={`shipping-carrier ${isSelected ? "shipping-carrier-expanded" : ""}`} aria-label={carrier.name}>
            <button id={buttonId} type="button" aria-expanded={isSelected} aria-controls={isSelected ? detailId : undefined} aria-label={`${isSelected ? "Hide" : "Show"} ${carrier.name} details`} aria-describedby={`${buttonId}-scacs ${buttonId}-tracking`} onClick={() => toggleRow(carrier.scac)} className={`shipping-carrier-columns shipping-carrier-header ${isSelected ? "shipping-carrier-selected" : ""}`}>
              <span className="shipping-carrier-name min-w-0 font-semibold text-gray-900 dark:text-white">{carrier.name}</span>
              <span id={`${buttonId}-scacs`} className="shipping-carrier-scacs break-words font-mono text-[11px] text-gray-500 dark:text-white/50">{[carrier.scac, ...carrier.alternativeScacs || []].join(", ")}</span>
              <span id={`${buttonId}-tracking`} className="shipping-tracking-badges">
                <span className="sr-only">{summaryLabel}: </span>
                {summaryFeatures.map(feature => <span key={feature.key} data-feature-key={availability ? undefined : feature.key} data-summary-feature-key={availability ? feature.key : undefined} title={feature.title}><Status status={coverage[carrier.scac]?.features?.[feature.key]} label={feature.label} availability={availability} /></span>)}
              </span>
              <svg className="shipping-row-chevron" aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m9 6 6 6-6 6" /></svg>
            </button>
            {isSelected ? <section id={detailId} aria-labelledby={buttonId}><Details features={features} coverage={coverage[carrier.scac]} Status={Status} /></section> : null}
          </article>;
  })}
      {rows.length === 0 ? <p className="px-3 py-10 text-center text-gray-500 dark:text-white/60">No carriers match these filters. Change the search or required feature.</p> : null}
    </div>;
};

export const CarrierCoverageDetails = ({features, coverage, Status}) => {
  const groups = [...new Set(features.map(feature => feature.group))];
  return <dl className="shipping-coverage-details text-sm text-gray-900 dark:text-white">
      {groups.map(group => <div key={group} className="shipping-feature-group">
          <dt>{group}</dt>
          <dd>
            <ul className="shipping-feature-badges">
              {features.filter(feature => feature.group === group).map(feature => {
    const description = [feature.field, ...(feature.requirements || []).map(requirement => requirement === "rail_plan" ? "Requires the Rail Plan" : requirement)].filter(Boolean).join(". ");
    return <li key={feature.key} data-feature-key={feature.key}>
                    {feature.href ? <a href={feature.href} className="inline-flex max-w-full rounded-full hover:underline focus-visible:outline focus-visible:outline-2 focus-visible:outline-green-600"><Status status={coverage?.features?.[feature.key]} label={feature.label} description={description} availability /></a> : <Status status={coverage?.features?.[feature.key]} label={feature.label} description={description} availability />}
                  </li>;
  })}
            </ul>
          </dd>
        </div>)}
    </dl>;
};

export const CarrierCoverageStatus = ({status, compact = false, availability = false, label, description}) => {
  const statuses = {
    supported: {
      label: availability ? "Available" : "Supported",
      symbol: "✓",
      className: "bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400"
    },
    limited: {
      label: availability ? "Limited" : "Partial",
      symbol: "◐",
      className: "bg-amber-50 text-amber-800 dark:bg-amber-500/10 dark:text-amber-300"
    },
    unsupported: {
      label: availability ? "Not available" : "Not supported",
      symbol: "−",
      className: "bg-gray-100 text-gray-600 dark:bg-white/10 dark:text-white/60"
    },
    unknown: {
      label: "Unknown",
      symbol: "?",
      className: "bg-gray-100 text-gray-600 dark:bg-white/10 dark:text-white/60"
    },
    signed_in_only: {
      label: "Requires carrier credentials",
      symbol: "⚿",
      className: "bg-blue-50 text-blue-700 dark:bg-blue-500/10 dark:text-blue-300"
    }
  };
  const value = statuses[status] || statuses.unknown;
  return <span title={[label ? `${label}: ${value.label}` : value.label, description].filter(Boolean).join(". ")} className={`${label ? "shipping-feature-badge " : ""}inline-flex items-center justify-center gap-1.5 rounded-full px-2 py-1 text-xs font-medium ${value.className}`}>
      <span aria-hidden="true" className="shrink-0">{value.symbol}</span>
      {label ? <><span className="shipping-feature-label">{label}</span><span className="sr-only">, {value.label}{description ? `. ${description}` : ""}</span></> : compact ? <span className="sr-only">{value.label}</span> : value.label}
    </span>;
};

export const CarrierCoverageExplorer = ({carriers, features: sourceFeatures, coverage = {}, summaryKeys, access, updatedOn, carrierLabel = "Carrier", layout = "rail"}) => {
  const features = layout === "rail" ? sourceFeatures.map(feature => feature.key === "available" ? {
    ...feature,
    label: "Available for pickup"
  } : feature) : sourceFeatures;
  const [query, setQuery] = useState("");
  const [requiredFeature, setRequiredFeature] = useState("all");
  const [includeLimited, setIncludeLimited] = useState(false);
  const [includeCredentials, setIncludeCredentials] = useState(false);
  const [selectedScac, setSelectedScac] = useState(null);
  const eligible = carriers.filter(carrier => !access || carrier.access === access);
  const rows = eligible.filter(carrier => {
    const matchesQuery = [carrier.name, carrier.legalName, carrier.scac, ...carrier.alternativeScacs || []].join(" ").toLowerCase().includes(query.trim().toLowerCase());
    const status = coverage[carrier.scac]?.features?.[requiredFeature];
    return matchesQuery && (requiredFeature === "all" || status === "supported" || includeLimited && status === "limited" || includeCredentials && status === "signed_in_only");
  });
  const summary = layout === "shipping" ? [{
    key: "billOfLading",
    label: "MBOL",
    title: "Master bill of lading number"
  }, {
    key: "bookingNumber",
    label: "Booking",
    title: "Booking number"
  }, {
    key: "containerNumber",
    label: "Container",
    title: "Container number"
  }] : summaryKeys.map(key => features.find(feature => feature.key === key)).filter(Boolean);
  const idPrefix = `${carrierLabel}-${access || "all"}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
  const controlClass = "w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-green-600 dark:border-white/10 dark:bg-white/5 dark:text-white";
  const changeFilter = (setter, value) => {
    setter(value);
    setSelectedScac(null);
  };
  const toggleRow = scac => setSelectedScac(selectedScac === scac ? null : scac);
  const hasCredentials = eligible.some(carrier => Object.values(coverage[carrier.scac]?.features || ({})).includes("signed_in_only"));
  return <div className="carrier-coverage not-prose min-w-0 space-y-4">
      <style>{`
        .carrier-coverage { container-type: inline-size; }
        .shipping-carrier + .shipping-carrier { border-top: 1px solid rgb(156 163 175 / 0.25); }
        .shipping-carrier-columns { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 14px 16px; }
        .shipping-table-heading { display: none; }
        .shipping-carrier-header { width: 100%; border: 0; text-align: left; font: inherit; color: inherit; cursor: pointer; background: rgb(var(--background-light, 255 255 255)); }
        .shipping-carrier-header:hover { background: #f9fafb; }
        .shipping-carrier-header:focus-visible { outline: 2px solid #16a34a; outline-offset: -2px; }
        .dark .shipping-carrier-header { background: rgb(var(--background-dark, 10 10 10)); }
        .dark .shipping-carrier-header:hover { background: #1f2937; }
        .shipping-carrier-expanded { background: rgb(var(--background-light, 255 255 255)); box-shadow: inset 3px 0 #737373; border-bottom: 2px solid #d4d4d4; }
        .shipping-carrier-expanded + .shipping-carrier { border-top: 0; }
        .shipping-carrier-header.shipping-carrier-selected { position: sticky; top: var(--carrier-coverage-sticky-top, 6rem); z-index: 10; background: #f0f0f0; border-bottom: 1px solid #d4d4d4; box-shadow: inset 3px 0 #737373; }
        .dark .shipping-carrier-expanded { background: rgb(var(--background-dark, 10 10 10)); border-bottom-color: #525252; box-shadow: inset 3px 0 #a3a3a3; }
        .dark .shipping-carrier-header.shipping-carrier-selected { background: #262626; border-bottom-color: #525252; box-shadow: inset 3px 0 #a3a3a3; }
        .shipping-carrier-name { grid-column: 1; grid-row: 1; }
        .shipping-carrier-scacs { grid-column: 1; grid-row: 2; }
        .shipping-tracking-badges { display: flex; grid-column: 1 / -1; grid-row: 3; flex-wrap: wrap; gap: 6px; font-size: 12px; }
        .shipping-row-chevron { grid-column: 2; grid-row: 1; justify-self: end; transition: transform 120ms; }
        .shipping-carrier-header[aria-expanded="true"] > .shipping-row-chevron { transform: rotate(90deg); }
        .shipping-coverage-details { margin: 0 12px 0 16px; }
        .shipping-feature-group { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; gap: 10px 16px; padding: 14px 16px; }
        .shipping-feature-group + .shipping-feature-group { border-top: 1px solid rgb(156 163 175 / 0.15); }
        .shipping-feature-group > dt { margin: 0; font-weight: 500; }
        .shipping-feature-group > dd { min-width: 0; margin: 0; }
        .shipping-feature-badges { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
        .shipping-feature-badges > li { min-width: 0; max-width: 100%; }
        .shipping-feature-badge { max-width: 100%; padding: 6px 12px; text-align: left; }
        .shipping-feature-label { min-width: 0; overflow-wrap: anywhere; }
        @container (min-width: 640px) {
          .shipping-carrier-columns { grid-template-columns: minmax(0, 1.2fr) minmax(70px, 0.55fr) minmax(0, 1.8fr) 18px; }
          .shipping-table-heading { display: grid; border-bottom: 1px solid rgb(156 163 175 / 0.25); }
          .shipping-carrier-name, .shipping-carrier-scacs, .shipping-tracking-badges, .shipping-row-chevron { grid-column: auto; grid-row: auto; }
          .shipping-feature-group { grid-template-columns: minmax(0, 1fr) minmax(0, 2.6fr); }
        }
      `}</style>
      <div className="grid gap-3 sm:grid-cols-2">
        <label className="text-xs font-medium text-gray-600 dark:text-white/70">Search carriers
          <input type="search" value={query} onChange={event => changeFilter(setQuery, event.target.value)} placeholder="Carrier name or SCAC" className={`${controlClass} mt-1`} />
        </label>
        <label className="text-xs font-medium text-gray-600 dark:text-white/70">Required feature
          <select value={requiredFeature} onChange={event => changeFilter(setRequiredFeature, event.target.value)} className={`${controlClass} mt-1`}>
            <option value="all">All features</option>
            {features.map(feature => <option key={feature.key} value={feature.key}>{feature.label}</option>)}
          </select>
        </label>
      </div>
      {requiredFeature !== "all" ? <div className="flex flex-wrap gap-4 text-sm text-gray-600 dark:text-white/70">
        <label className="flex items-center gap-2"><input type="checkbox" checked={includeLimited} onChange={event => changeFilter(setIncludeLimited, event.target.checked)} className="accent-green-600" />Include limited availability</label>
        {hasCredentials ? <label className="flex items-center gap-2"><input type="checkbox" checked={includeCredentials} onChange={event => changeFilter(setIncludeCredentials, event.target.checked)} className="accent-green-600" />Include features requiring carrier credentials</label> : null}
      </div> : null}
      <p className="text-xs text-gray-500 dark:text-white/60">Showing {rows.length} of {eligible.length} carriers. Select a carrier row for data availability.</p>
      <div className="flex flex-wrap items-center gap-2" aria-label="Data availability legend">
        <span className="mr-2 text-xs text-gray-600 dark:text-white/70">{layout === "shipping" ? "Data available through the carrier integration" : "Data available through the rail integration and Terminal49 estimates"}</span>
        {["supported", "limited", "unsupported", "unknown", ...hasCredentials ? ["signed_in_only"] : []].map(status => <CarrierCoverageStatus key={status} status={status} availability />)}
      </div>
      <CarrierCoverageRows rows={rows} features={features} coverage={coverage} selectedScac={selectedScac} toggleRow={toggleRow} idPrefix={idPrefix} summaryFeatures={summary} summaryLabel={layout === "shipping" ? "Tracking number support" : "Data availability"} carrierLabel={carrierLabel} availability={layout !== "shipping"} Status={CarrierCoverageStatus} Details={layout === "shipping" ? ShippingCarrierCoverageDetails : CarrierCoverageDetails} />
      <p className="text-xs text-gray-500 dark:text-white/60">Available fields may be absent for an individual container. <a href="/coverage/fields" className="underline underline-offset-2">See field availability</a>. Unknown means no feature status is available.</p>
      {updatedOn ? <p className="text-xs leading-relaxed text-gray-500 dark:text-white/60">Data last updated {updatedOn}. We continuously improve our integrations, so coverage may have changed since this update. <a href="mailto:support@terminal49.com" className="underline underline-offset-2">Contact support</a> to confirm coverage for your carrier.</p> : null}
    </div>;
};

Terminal49 keeps tracking after the container leaves the ocean terminal. For inland moves on North American rail, the same container and shipment objects pick up rail milestones, the rail carrier's ETA, and the rail last free day — no separate tracking request needed.

<Note>
  Rail last free day data (`import_deadlines.pickup_lfd_rail` and the
  `container.pickup_lfd_rail.changed` webhook) requires the Rail Plan on your
  account. See [entitlements](/api-docs/useful-info/entitlements).
</Note>

## North American Class I rail

Terminal49 covers all six Class I railroads that move intermodal containers in North America:

Search by carrier name or Standard Carrier Alpha Code (SCAC), filter by a required feature, and select a carrier row to see all container milestones, rail attributes, and Terminal49 estimates.

T49 Rail ETA shows Terminal49 estimate coverage; Carrier ETA shows estimates supplied by the railroad.

<CarrierCoverageExplorer carriers={railCarriers} features={railCarrierFeatures} coverage={railCarrierCoverage} summaryKeys={["railArrived", "available", "lastFreeDay", "estArrivalAtDestination", "t49RailEta"]} carrierLabel="Rail carrier" updatedOn={coverageUpdatedOn} />

[Complete rail carrier feature table](/data/coverage/rail-carriers) · [JSON](/data/coverage/rail-carriers.json) · [CSV](/data/coverage/rail-carriers.csv)

Browse the [complete inland rail terminal directory](/coverage/inland-rail-terminals) for terminal names, locations, and facility codes.

<Note>
  Features marked “Requires carrier credentials” need authenticated access to the
  rail carrier. [Contact support](mailto:support@terminal49.com) to confirm setup
  for your account. Carrier credentials and the [Rail
  Plan](/api-docs/useful-info/entitlements) are separate requirements.
</Note>

## Rail data

Feature availability varies by rail carrier. Select a carrier above to check data availability for:

* Rail loaded, departed, arrived, and unloaded events
* Arrival at the inland destination, with the rail carrier's ETA and ATA
* Rail last free day (LFD) at the inland facility — requires the [Rail Plan](/api-docs/useful-info/entitlements)
* Pickup availability after unload
* The rail carrier SCAC at port of discharge and at the inland destination (they can differ)

See the [rail integration guide](/api-docs/in-depth-guides/rail-integration-guide) for webhook names, container attributes, and API vs DataSync setup.

## Rail events

```mermaid theme={null}
graph LR
A[Rail Loaded] --> B[Rail Departed]
B --> C[Arrived at Inland Destination]
C --> D[Rail Unloaded]
D --> G[Available for Pickup]
G --> E[Full Out]
E --> F[Empty Return]
```

| Event | Webhook |
| - | - |
| Rail loaded | `container.transport.rail_loaded` |
| Rail departed | `container.transport.rail_departed` |
| Rail arrived | `container.transport.rail_arrived` |
| Arrived at inland destination | `container.transport.arrived_at_inland_destination` |
| Rail unloaded | `container.transport.rail_unloaded` |
| Rail LFD changed | `container.pickup_lfd_rail.changed` |
| Inland ETA changed | `container.transport.estimated.arrived_at_inland_destination` |

Some railroads do not share every event. The events above are the ones you should plan around.

## Inland ETA: rail vs shipping line

For an inland move, two arrival views can differ:

| Field | Lives on | Source |
| - | - | - |
| `ind_eta_at` / `ind_ata_at` | container | Rail carrier |
| `destination_eta_at` / `destination_ata_at` | shipment | Ocean carrier |

Use the rail fields when you want the inland railroad's view. Use the shipment fields when you want the ocean carrier's view of the same destination.

## Rail last free day

`pickup_lfd` on the container is coalesced from `import_deadlines`, in this order:

1. `pickup_lfd_line` — shipping line
2. `pickup_lfd_terminal` — port of discharge terminal
3. `pickup_lfd_rail` — rail carrier at the inland destination

Subscribe to `container.pickup_lfd_rail.changed` when you need the inland railroad's LFD specifically. Rail LFD data requires the [Rail Plan](/api-docs/useful-info/entitlements); without it, `pickup_lfd_rail` values and the webhook are not delivered.

## Complete structured coverage

Last updated 2026-10-13.

[Download JSON](/data/coverage/rail-carriers.json).

Supported means the source returns the feature when applicable. Partial means it returns the feature in some cases. Not supported means this source does not return the feature. Unknown means no feature assessment is available. Carrier credentials required means the feature requires credentials for the carrier integration.

Coverage describes integration capabilities. A supported field may be absent until its milestone occurs. We continually improve our integrations. Contact support to confirm current coverage.

Rail Last Free Day (LFD) requires the Rail Plan. This entitlement is separate from carrier credential requirements.

Standard Carrier Alpha Code (SCAC) identifies carriers. Terminal identities include the port location code and terminal code.

## BNSF Railway

SCAC `BNSF`. US Class I.

| Section | Feature | Coverage |
| - | - | - |
| Container milestones | Rail Loaded | Not supported |
| Container milestones | Rail Departed | Not supported |
| Container milestones | Rail Arrived | Supported |
| Container milestones | Rail Unloaded | Not supported |
| Container milestones | Arrived At Destination | Supported |
| Container milestones | Available | Supported |
| Container milestones | Full Out | Not supported |
| Container milestones | Empty Returned | Not supported |
| Rail attributes | Rail LFD | Supported |
| Rail attributes | Carrier ETA | Supported |
| Rail attributes | POD Rail Carrier | Supported |
| Rail attributes | Destination Rail Carrier | Supported |
| Terminal49 estimates | T49 Rail ETA | Supported |

## Union Pacific

SCAC `UPRR`. US Class I.

| Section | Feature | Coverage |
| - | - | - |
| Container milestones | Rail Loaded | Not supported |
| Container milestones | Rail Departed | Supported |
| Container milestones | Rail Arrived | Supported |
| Container milestones | Rail Unloaded | Not supported |
| Container milestones | Arrived At Destination | Partial |
| Container milestones | Available | Supported |
| Container milestones | Full Out | Supported |
| Container milestones | Empty Returned | Partial |
| Rail attributes | Rail LFD | Supported |
| Rail attributes | Carrier ETA | Supported |
| Rail attributes | POD Rail Carrier | Supported |
| Rail attributes | Destination Rail Carrier | Supported |
| Terminal49 estimates | T49 Rail ETA | Supported |

## Norfolk Southern

SCAC `NSRR`. US Class I.

| Section | Feature | Coverage |
| - | - | - |
| Container milestones | Rail Loaded | Carrier credentials required |
| Container milestones | Rail Departed | Carrier credentials required |
| Container milestones | Rail Arrived | Carrier credentials required |
| Container milestones | Rail Unloaded | Partial |
| Container milestones | Arrived At Destination | Supported |
| Container milestones | Available | Partial |
| Container milestones | Full Out | Partial |
| Container milestones | Empty Returned | Not supported |
| Rail attributes | Rail LFD | Partial |
| Rail attributes | Carrier ETA | Carrier credentials required |
| Rail attributes | POD Rail Carrier | Supported |
| Rail attributes | Destination Rail Carrier | Supported |
| Terminal49 estimates | T49 Rail ETA | Supported |

## CSX

SCAC `CSXT`. US Class I.

| Section | Feature | Coverage |
| - | - | - |
| Container milestones | Rail Loaded | Partial |
| Container milestones | Rail Departed | Supported |
| Container milestones | Rail Arrived | Supported |
| Container milestones | Rail Unloaded | Supported |
| Container milestones | Arrived At Destination | Supported |
| Container milestones | Available | Supported |
| Container milestones | Full Out | Not supported |
| Container milestones | Empty Returned | Not supported |
| Rail attributes | Rail LFD | Supported |
| Rail attributes | Carrier ETA | Supported |
| Rail attributes | POD Rail Carrier | Supported |
| Rail attributes | Destination Rail Carrier | Supported |
| Terminal49 estimates | T49 Rail ETA | Supported |

## Canadian National

SCAC `CNRU`. Canadian Class I.

| Section | Feature | Coverage |
| - | - | - |
| Container milestones | Rail Loaded | Supported |
| Container milestones | Rail Departed | Supported |
| Container milestones | Rail Arrived | Supported |
| Container milestones | Rail Unloaded | Partial |
| Container milestones | Arrived At Destination | Supported |
| Container milestones | Available | Partial |
| Container milestones | Full Out | Supported |
| Container milestones | Empty Returned | Not supported |
| Rail attributes | Rail LFD | Supported |
| Rail attributes | Carrier ETA | Supported |
| Rail attributes | POD Rail Carrier | Supported |
| Rail attributes | Destination Rail Carrier | Supported |
| Terminal49 estimates | T49 Rail ETA | Supported |

## Canadian Pacific / KCS

SCAC `CPRS`. Canadian Class I.

| Section | Feature | Coverage |
| - | - | - |
| Container milestones | Rail Loaded | Not supported |
| Container milestones | Rail Departed | Carrier credentials required |
| Container milestones | Rail Arrived | Carrier credentials required |
| Container milestones | Rail Unloaded | Not supported |
| Container milestones | Arrived At Destination | Carrier credentials required |
| Container milestones | Available | Carrier credentials required |
| Container milestones | Full Out | Carrier credentials required |
| Container milestones | Empty Returned | Not supported |
| Rail attributes | Rail LFD | Supported |
| Rail attributes | Carrier ETA | Supported |
| Rail attributes | POD Rail Carrier | Supported |
| Rail attributes | Destination Rail Carrier | Supported |
| Terminal49 estimates | T49 Rail ETA | Supported |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.