# Bulk edit railcar charge history Source: https://docs.cedarai.com/api-reference/bulk-edit-railcar-charge-history /user-docs/api-reference/external-openapi.json post /ims/equipment/bulk-edit-charged-history Create and delete multiple charged history records in one request (supports dry run). # Get Charges Table Definition Source: https://docs.cedarai.com/api-reference/chargeservice/get-charges-table-definition /user-docs/api-reference/charge.swagger.json get /t/v1/charges-table-def Returns the available charges export columns and default columns. Downstream finance systems such as NetSuite, Sage, or ERP middleware can use this metadata to map Cedar fields before requesting charge rows. This response is metadata only: it tells consumers which columns are available, how Cedar labels them, which columns are searchable, and which columns Cedar returns by default. Common export-oriented columns: | Column | Meaning for downstream systems | | --- | --- | | `chargeId` | Stable Cedar charge identifier for reconciliation, upserts, or idempotent imports. | | `customerLocationAccountNumber` | Customer location account number often used to map a charge into an external account or business unit. | | `invoice` | Invoice number or sequence used to group already-invoiced charges. | | `accountingPeriod` | Cedar accounting period label that can be used for period-close exports or batching. | | `billingType` | High-level charge category such as storage, demurrage, switching, or ISS shipment. | | `serviceType` | Service-specific classification that can help downstream mapping rules route charges to the right workflow. | | `glCode` | General ledger code used for financial posting and account mapping. | | `rateTableEntry` / `rateDescription` | Human-readable pricing fields that explain why the amount was calculated. | | `adjustment_total` | Net difference between the original amount and the final adjusted amount. | The response example below shows a representative subset of these columns. # Get Charges Table Summary Source: https://docs.cedarai.com/api-reference/chargeservice/get-charges-table-summary /user-docs/api-reference/charge.swagger.json post /t/v1/charges-table-summary Returns aggregate summary values for the charges table using the requested filters and aggregations, without returning full row detail. Downstream finance systems can use this endpoint to validate export scope, reconcile totals, and compare Cedar results against imported batches in NetSuite, Sage, or another ERP. Common reconciliation patterns: | Aggregate request | Typical downstream use | | --- | --- | | `COUNT` on `chargeId` | Confirm the number of charges in an export batch. | | `SUM` on `amount` | Compare Cedar totals with external invoice or journal totals. | | `SUM` on `adjustment_total` | Measure the net effect of adjustments before posting. | | `MIN` / `MAX` on `appliedAt` | Verify the date window covered by an incremental export. | Use the same filter set you would pass to `List Charges Table Rows` when you want summary numbers for the exact same population of charges. # List Charges Table Rows Source: https://docs.cedarai.com/api-reference/chargeservice/list-charges-table-rows /user-docs/api-reference/charge.swagger.json post /t/v1/charges-table-rows Returns a page of charges export rows using the requested columns, filters, sorting, and pagination. Downstream finance systems such as NetSuite, Sage, or ERP middleware typically call `Get Charges Table Definition` first, choose a subset of fields, and then request rows for export, reconciliation, or incremental sync jobs. Key request fields: | Input | How downstream systems commonly use it | | --- | --- | | `table_data_request.requested_columns` | Select the Cedar fields to include in each exported row. | | `table_data_request.additional_filters` | Limit the export to a specific invoice, accounting period, billing type, service type, GL code, customer, or other supported charge dimension. | | `table_data_request.sort_columns` | Create a stable export order for repeatable batching and reconciliation. | | `page_size`, `page_next_token`, `page_previous_token` | Page through large exports without re-reading the full result set. | Each row is returned as a column-keyed structure rather than a fixed finance schema, so consumers can request only the columns they actively map into their downstream system. # Classify a class list Source: https://docs.cedarai.com/api-reference/classify-a-class-list /user-docs/api-reference/external-openapi.json post /ims/work-orders/class-lists/classify Creates a class list (switch list) from a list of car numbers by automatically picking destination tracks based on the carrier's configured block-to-track scope. This is the API equivalent of the inventory **Classify** dialog: you provide just the cars, and Cedar mirrors the UI logic to compute where each car goes. Customers replacing the existing class-list API typically batch 5–60 cars per call, scoped to the lead/shift the crew is working — see the `switchListBatch` example for a realistic shape. Classification logic (per car, in request order): 1. Find the parent grouping of the carrier-configured block type (for example `yard_block`). 2. Look up the assigned tracks for that block in priority order. 3. Pick the first assigned track with capacity for the car. 4. Otherwise fall back to the lowest-priority assigned track. 5. Otherwise — only when a block exists — fall back to the car's current track if `classifyFallbackToCurrentTrack` is enabled in carrier settings. The operation is atomic: if any car cannot be resolved (missing in inventory, has no block of the carrier-configured type, or has no usable destination) the entire request is rejected and no class list is created. Cars without a block are always rejected, regardless of the fallback setting, mirroring the inventory dialog's behaviour. Usage notes: - `equipmentInitialAndNumbers` accepts entries like `"BNSF 999001"`. The order is preserved in the resulting class list (it determines `workOrderPriority` on the persisted tasks) and is also used for capacity accounting. - `scope` is optional. When omitted, the first scope accessible to the caller is used. Scopes that do not start with `block2track_` are automatically prefixed. A scope that is not configured for the carrier is rejected with `400 Bad Request`. - `jobId` is optional. Carriers commonly pass the train or job number the crew is working (for example `350` or `MORNING-JOB-12`); when omitted, a label like `Classify 2026-04-30 22:34:11 UTC` is generated. - `isBack` defaults to `false`; set to `true` to switch from the back of the track. - The inventory page also offers a **Classify by Current Track** action that splits a multi-track selection into one class list per source track. To replicate that, partition the cars by current track yourself and call this endpoint once per group (see the `byCurrentTrackPerCall` example). Permission required: `workOrderManagement.classList.classifyThirdParty`. # Complete class list tasks Source: https://docs.cedarai.com/api-reference/complete-class-list-tasks /user-docs/api-reference/external-openapi.json post /ims/work-orders/tasks/complete Marks one or more class list tasks as completed. Usage notes: - Each item in the request specifies a taskId and optionally a finalTrackId (the track the equipment was moved to). - When all tasks on a class list are completed, the class list is automatically archived. - Use this endpoint after moving equipment (via the Move Equipment API) to mark the corresponding class list tasks as done. - The completedAt timestamp defaults to the current time if not specified. # Create a class list Source: https://docs.cedarai.com/api-reference/create-a-class-list /user-docs/api-reference/external-openapi.json post /ims/work-orders/class-lists/create Creates a new class list (switch list) with the specified equipment moves. Usage notes: - Each item represents an equipment move to a target track location. - The jobId is a user-specified label for the class list. # Create bill of lading Source: https://docs.cedarai.com/api-reference/create-bill-of-lading /user-docs/api-reference/external-openapi.json post /ims/waybills/bill-of-lading Create a bill of lading for a waybill. It will always create a bill of lading regardless of what is provided in the request. When a `billOfLadingNumber` already exists within the last 6 months for this carrier (regardless of lead equipment), the request is rejected with HTTP 409 — use the update endpoint instead, including to correct lead equipment on an existing bill. When `waybillTemplateId` is set, Cedar merges template data with the request. Static parties (shipper, consignee, freight bill party, in-care-of) are merged field-by-field; all other parties from the request and template are kept. See [Cross-border (Mexico) waybills](/user-docs/api-reference/cross-border-mexico#parties) for party merge rules when using templates. # Attaches Voucher Source: https://docs.cedarai.com/api-reference/invoicesservice/attaches-voucher /user-docs/api-reference/invoices.swagger.json post /shipper/invoices/{id}/vouchers Associate a voucher to a shipper's invoice # Get Shipper Invoice Source: https://docs.cedarai.com/api-reference/invoicesservice/get-shipper-invoice /user-docs/api-reference/invoices.swagger.json get /shipper/invoices/{id} Returns a single invoice # List Shipper Invoices Source: https://docs.cedarai.com/api-reference/invoicesservice/list-shipper-invoices /user-docs/api-reference/invoices.swagger.json get /shipper/invoices Returns list of invoices # AI summary of a note thread Source: https://docs.cedarai.com/api-reference/lindaservice/ai-summary-of-a-note-thread /user-docs/api-reference/service.swagger.json post /v1/notes/summarize-entity Generates a one-paragraph AI summary of the note thread for an entity. Synchronous LLM call — expect 2 to 6 seconds latency. Cache results client-side if you display them frequently; the response is not cached server-side. **Billing:** This endpoint invokes a Cedar.AI language model and is billed under AI pricing. The other notes endpoints (`/v1/notes/list`, `/v1/notes/create`, `/v1/notes/search`, etc.) are not AI-backed and follow standard API metering. # Batch get note summaries Source: https://docs.cedarai.com/api-reference/lindaservice/batch-get-note-summaries /user-docs/api-reference/service.swagger.json post /v1/notes/batch-get-summaries Returns note summaries for many entities in one round trip. Designed for list/grid pages that show a notes-count column. Entities with zero notes are omitted from the response. # Create a note Source: https://docs.cedarai.com/api-reference/lindaservice/create-a-note /user-docs/api-reference/service.swagger.json post /v1/notes/create Creates a new threaded note on an entity (shipment, equipment, waybill, etc.). The caller's verified identity (from JWT or assumed user) becomes the note author. Reference tokens (`<>`) embedded in `content` should also be supplied as structured `references` for reverse-lookup. # Delete a note Source: https://docs.cedarai.com/api-reference/lindaservice/delete-a-note /user-docs/api-reference/service.swagger.json post /v1/notes/delete Soft-deletes a note. The row is retained for audit but excluded from all reads. Owners may always delete; non-owners require the `linda.notes.deleteAny` permission. # Get note summary for one entity Source: https://docs.cedarai.com/api-reference/lindaservice/get-note-summary-for-one-entity /user-docs/api-reference/service.swagger.json post /v1/notes/get-summary Returns a one-row summary for a single entity: total note count and the latest note. Use this to populate badges/counters without fetching the full thread. # List notes Source: https://docs.cedarai.com/api-reference/lindaservice/list-notes /user-docs/api-reference/service.swagger.json post /v1/notes/list Returns notes on a given entity in descending chronological order (newest first). Supports cursor-based pagination via `page_size` and `page_token`. When both `referenced_entity_type` and `referenced_entity_id` are set, the request switches to reverse-lookup mode (notes mentioning the given entity), capped at 100 results without pagination. # Search notes (full-text) Source: https://docs.cedarai.com/api-reference/lindaservice/search-notes-full-text /user-docs/api-reference/service.swagger.json post /v1/notes/search Full-text search across all notes for the carrier, ranked by Postgres `ts_rank`. Returns ``-highlighted snippets via `ts_headline`. The index strips `<>` reference token wrappers and normalizes hashtag-group syntax (`#group(content)`) so chip text and automation-written hashtag content are searchable as plain words. # Search referenceable entities for mentions Source: https://docs.cedarai.com/api-reference/lindaservice/search-referenceable-entities-for-mentions /user-docs/api-reference/service.swagger.json post /v1/notes/search-references Searches across all configured entity types in parallel and returns the top N matches per type. Used by the note editor's `@`-mention typeahead to look up equipment, shipments, customers, waybills, work orders, invoices, etc. by identifier or display text. # Update a note Source: https://docs.cedarai.com/api-reference/lindaservice/update-a-note /user-docs/api-reference/service.swagger.json post /v1/notes/update Edits an existing note's content and (optionally) its references. Owners may always edit; non-owners require the `linda.notes.editAny` permission. Set `update_references=true` to replace the prior reference set; otherwise prior references are preserved. # List class list tasks Source: https://docs.cedarai.com/api-reference/list-class-list-tasks /user-docs/api-reference/external-openapi.json post /ims/work-orders/class-lists/tasks Retrieves the list of tasks associated with specified class lists. Usage notes: - Pagination: Use pageSize, pageNextToken, and pagePrevToken to navigate paginated results. - Filtering: Combine multiple criteria (e.g., workOrderId, status, equipmentName) to narrow results. - Date ranges: carrierDateRange is assumed to be in the carrier's timezone. # List class lists Source: https://docs.cedarai.com/api-reference/list-class-lists /user-docs/api-reference/external-openapi.json post /ims/work-orders/class-lists Retrieves a list of class lists. Usage notes: - Pagination: Use pageSize, pageNextToken, and pagePrevToken to navigate paginated results. - Filtering: Combine multiple criteria (e.g., status, customerName, equipmentName) to narrow results. - Date ranges: carrierDateRange is assumed to be in the carrier's timezone. # List customers Source: https://docs.cedarai.com/api-reference/list-customers /user-docs/api-reference/external-openapi.json post /ims/customers Retrieves a list of customers for the specified carrier. # List groupings Source: https://docs.cedarai.com/api-reference/list-groupings /user-docs/api-reference/external-openapi.json post /ims/groupings/list Returns a simplified list of groupings for a carrier, filtering out consist-related grouping types for third-party consumers. # List railcar charge history Source: https://docs.cedarai.com/api-reference/list-railcar-charge-history /user-docs/api-reference/external-openapi.json post /ims/equipment/charged-history Retrieves charged history records, filterable by equipment, time range, and flags. # List railcar history Source: https://docs.cedarai.com/api-reference/list-railcar-history /user-docs/api-reference/external-openapi.json post /equipment-history/ Retrieves equipment history records, filterable by equipment, time range, and flags. # List railcar inventory Source: https://docs.cedarai.com/api-reference/list-railcar-inventory /user-docs/api-reference/external-openapi.json post /ims/equipment/inventory Retrieves a list of railcar inventory items based on specified criteria (pagination, filters like loadStatus, station, track, etc.). Usage notes: - Pagination: Use pageSize, pageNextToken, and pagePrevToken to navigate paginated results. - Filtering: Combine multiple criteria (e.g., loadStatus, aarCarType, station, track, tag) to narrow results. - IDs: Station, track, and tag identifiers should come from the listStationTracks endpoint. # List station tracks Source: https://docs.cedarai.com/api-reference/list-station-tracks /user-docs/api-reference/external-openapi.json get /ims/groupings/station-tracks Retrieves a list of station tracks and their associated groupings for a specific carrier. # Get the Network Hierarchy Source: https://docs.cedarai.com/api-reference/networkstructureservice/get-the-network-hierarchy /user-docs/api-reference/network_structure.swagger.json post /t/v1/network-hierarchy Get the Carrier Network as a hierarchical tree structure. # Get Quote Preferences Source: https://docs.cedarai.com/api-reference/quotesservice/get-quote-preferences /user-docs/api-reference/quotes.swagger.json get /shipper/quote-preferences # Get Shipper Quote Source: https://docs.cedarai.com/api-reference/quotesservice/get-shipper-quote /user-docs/api-reference/quotes.swagger.json get /shipper/quotes/{name} # List Shipper Quotes Source: https://docs.cedarai.com/api-reference/quotesservice/list-shipper-quotes /user-docs/api-reference/quotes.swagger.json post /shipper/quotes # Update Quote Preferences Source: https://docs.cedarai.com/api-reference/quotesservice/update-quote-preferences /user-docs/api-reference/quotes.swagger.json put /shipper/quote-preferences # Submit railcar switch request Source: https://docs.cedarai.com/api-reference/submit-railcar-switch-request /user-docs/api-reference/external-openapi.json post /ims/equipment/switch-request Submit switch requests for one or more equipment to spots/tracks. Usage notes: - When a spot does not exist yet, providing a spot name will create it on the fly. - requestType codes: PL (Pull), IP (In-place), TR (Transfer), RELEASE, LEAVE. # Toolswork load equipment Source: https://docs.cedarai.com/api-reference/toolswork-load-equipment /user-docs/api-reference/external-openapi.json post /ims/equipment/load-toolswork Bulk load equipment with groupings and weights; supports on-the-fly grouping creation. # Create Truck Load Tender Source: https://docs.cedarai.com/api-reference/truckloadtenderservice/create-truck-load-tender /user-docs/api-reference/load_tender.swagger.json post /t/v1/load-tender/create Creates a Truck Load Tender. # Delete Truck Load Tender Source: https://docs.cedarai.com/api-reference/truckloadtenderservice/delete-truck-load-tender /user-docs/api-reference/load_tender.swagger.json put /t/v1/load-tender/delete Deletes a Truck Load Tender. # Get Truck Load Tender Source: https://docs.cedarai.com/api-reference/truckloadtenderservice/get-truck-load-tender /user-docs/api-reference/load_tender.swagger.json get /t/v1/load-tender/get Returns a single Truck Load Tender. # List Truck Load Tenders Source: https://docs.cedarai.com/api-reference/truckloadtenderservice/list-truck-load-tenders /user-docs/api-reference/load_tender.swagger.json get /t/v1/load-tender/list Returns Truck Load Tenders. # Update Truck Load Tender Source: https://docs.cedarai.com/api-reference/truckloadtenderservice/update-truck-load-tender /user-docs/api-reference/load_tender.swagger.json put /t/v1/load-tender/update Updates a Truck Load Tender. # Update bill of lading Source: https://docs.cedarai.com/api-reference/update-bill-of-lading /user-docs/api-reference/external-openapi.json put /ims/waybills/bill-of-lading Update an existing bill of lading identified by `billOfLadingNumber` (within the last 6 months for this carrier). Immutable fields: `billOfLadingNumber`, `waybillNumber`, and `waybillDate`. Lead equipment (`equipmentDetails[0].equipmentInitial` / `equipmentNumber`) may be changed via update. Cedar archives the prior bill and creates a replacement bill with the new lead equipment. When a prior outbound 404 EDI was sent for the archived bill, Cedar sends a cancellation 404 (BX01=04, ZC1=CA) for the archived bill after creating the replacement. For in-place field changes (same lead equipment), when a prior outbound 404 EDI was sent for this bill, Cedar automatically sends a correction 404 (BX01=04, ZC1=CO) after a successful update. When `waybillTemplateId` is set, Cedar merges template data with the request using the same rules as create. # Update equipment notes Source: https://docs.cedarai.com/api-reference/update-equipment-notes /user-docs/api-reference/external-openapi.json post /ims/equipment/notes/update Updates notes on one or more pieces of equipment. Usage notes: - Use equipmentIds + notes for bulk updates (same note on multiple equipment). - Use the updates array for per-equipment notes (different note per equipment). - Pass null for the note value to clear an existing note. - Notes are limited to 280 characters. - The response returns the updated equipment objects with third-party visible fields. Permission required: `inventoryManagement.equipment.updateNotes` # Update railcar inventory (move equipment) Source: https://docs.cedarai.com/api-reference/update-railcar-inventory-move-equipment /user-docs/api-reference/external-openapi.json post /ims/equipment/move Move equipment between tracks/spots. Supports sequencing and batch moves. Usage notes: - Use to.grouping.resourceId to target a track and to.groupingIndex to control position (0 = front, -1 = back). - Provide updateIntermodalUnits=true to keep intermodal units in sync when moving equipment. # Arrive train Source: https://docs.cedarai.com/api-reference/workorderservice/arrive-train /user-docs/api-reference/work_order.swagger.json post /t/v1/arrive-train Arrive a train to a customer or serving location. # Depart train Source: https://docs.cedarai.com/api-reference/workorderservice/depart-train /user-docs/api-reference/work_order.swagger.json post /t/v1/depart-train Depart a train from a station. # List Train Reason Codes Source: https://docs.cedarai.com/api-reference/workorderservice/list-train-reason-codes /user-docs/api-reference/work_order.swagger.json post /t/v1/list-train-reason-codes Returns the carrier's train reason codes grouped by category. # List Work Order Tasks Source: https://docs.cedarai.com/api-reference/workorderservice/list-work-order-tasks /user-docs/api-reference/work_order.swagger.json post /t/v1/list-work-order-tasks Returns a list of tasks for a given work order. # List Work Orders Source: https://docs.cedarai.com/api-reference/workorderservice/list-work-orders /user-docs/api-reference/work_order.swagger.json post /t/v1/list-work-orders Returns list of Work Orders # Pickup cars Source: https://docs.cedarai.com/api-reference/workorderservice/pickup-cars /user-docs/api-reference/work_order.swagger.json post /t/v1/pickup-cars Pickup cars. On success, completes the Pickup tasks. # Record Train Event Source: https://docs.cedarai.com/api-reference/workorderservice/record-train-event /user-docs/api-reference/work_order.swagger.json post /t/v1/record-train-event Record a train event. # Resequence a train Source: https://docs.cedarai.com/api-reference/workorderservice/resequence-a-train /user-docs/api-reference/work_order.swagger.json post /t/v1/resequence-train Used for resequence of active trains. For editing the consist of Pending trains, use UpdateWorkOrder. # Setout Cars Source: https://docs.cedarai.com/api-reference/workorderservice/setout-cars /user-docs/api-reference/work_order.swagger.json post /t/v1/setout-cars Setout cars. On success, completes the Setout tasks. # Update a Work Order Source: https://docs.cedarai.com/api-reference/workorderservice/update-a-work-order /user-docs/api-reference/work_order.swagger.json post /t/v1/update-work-order Update a Work Order. Used for editing consist of a pending train. # Accounting Integrations Source: https://docs.cedarai.com/user-docs/accounting-integrations/overview Sync your Cedar ARMS billing data with external accounting software Cedar integrates with popular accounting software to automatically sync your ARMS charges and invoices, eliminating manual data entry and keeping your financial records up to date. ## Available Integrations ### QuickBooks QuickBooks | Integration | Status | Description | | --------------------------------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------- | | [QuickBooks Desktop](/user-docs/accounting-integrations/quickbooks-web-connector) | **Available** | Sync invoices using the QuickBooks Web Connector (QBWC) | | [QuickBooks Online](/user-docs/accounting-integrations/quickbooks-online) | **Pilot / limited availability** | Requires Cedar administrator approval; directly synchronizes finalized invoices | *** ### Sage Sage | Integration | Status | Description | | ------------ | ----------- | ---------------------------------- | | Sage Intacct | Coming soon | Cloud-based accounting integration | *** ### NetSuite NetSuite | Integration | Status | Description | | --------------- | ----------- | -------------------------------- | | Oracle NetSuite | Coming soon | Enterprise cloud ERP integration | *** ### JD Edwards JD Edwards | Integration | Status | Description | | ----------------------- | ----------- | ------------------------------------------- | | JD Edwards Orchestrator | Coming soon | Enterprise ERP integration via Orchestrator | ## How It Works All accounting integrations follow a similar workflow: Track railcar storage, switching, and other billable services in Cedar ARMS Group charges into invoices for your customers The integration sends charges or invoices that meet its configured billing-status policy Monitor successful synchronization and resolve any mappings or connection issues that need attention ## What Gets Synced | Cedar ARMS | QuickBooks Online | | -------------------------- | --------------------------------------------------------- | | Finalized invoice | Posting Invoice | | Customer location | Customer selected in the explicit mapping | | Service type | Item selected in the explicit mapping | | Charge | Invoice line with description, quantity, rate, and amount | | First invoiced charge date | Transaction date | QuickBooks Online synchronization is future-only. It does not backfill invoices finalized before connection or during a disconnected interval. | Cedar ARMS | QuickBooks Desktop | | ---------------------------- | ---------------------------------------------------------- | | Invoice | Sales Order | | Invoice line items (charges) | Line items with service type, quantity, and rate | | Customer | Customer reference through the customer location GL number | | Invoice date | Transaction date | By default, QuickBooks Desktop synchronizes Invoiced charges after invoice finalization. Cedar can configure QBWC to include Assigned charges so they synchronize before finalization. Charges must also have a **General Ledger (GL) Number** configured on the customer location. ## Billing Status Requirements QuickBooks Online synchronizes only finalized invoices with **Invoiced** charges. It is future-only and does not backfill invoices finalized before connection or during a disconnected interval. By default, QuickBooks Desktop synchronizes **Invoiced** charges. Cedar can configure QBWC to include **Assigned** charges for an earlier sync. Ask your Cedar administrator which billing statuses are enabled for your Desktop connection. QuickBooks Online requires explicit Customer and Item mappings. QuickBooks Desktop uses matching GL numbers and service item names. See the integration-specific guide before enabling automatic synchronization. ## Related Pages * [QuickBooks Online Setup](/user-docs/accounting-integrations/quickbooks-online) * [QuickBooks Web Connector Setup](/user-docs/accounting-integrations/quickbooks-web-connector) # QuickBooks Online Source: https://docs.cedarai.com/user-docs/accounting-integrations/quickbooks-online Connect QuickBooks Online and synchronize finalized Cedar ARMS invoices QuickBooks Online synchronization sends finalized Cedar ARMS invoices to one QuickBooks Online company. It runs in the background, reports progress in ARMS, and retries temporary failures automatically. QuickBooks Online is available only to approved pilot and limited-availability accounts. Contact your Cedar administrator to request access. This setup guide does not mean the integration is enabled for your account. QuickBooks Online creates **posting Invoices in accounts receivable**. This differs from the QuickBooks Desktop integration, which creates non-posting Sales Orders. ## Before You Connect You need: * Permission to view and update invoices in Cedar ARMS * An Intuit user who can authorize applications for the QuickBooks Online company * Active Customers and Items in QuickBooks Online for the customer locations and service types you invoice Synchronization is future-only. ARMS does not enroll invoices first finalized before the connection was confirmed or while the integration was disconnected. Reconnecting does not scan or backfill those invoices. If **QuickBooks Online** does not appear under Invoice settings, the integration has not been enabled for your account. ## Connect a Company In Cedar ARMS, go to **Settings → Invoice settings → QuickBooks Online**. Select **Connect QuickBooks Online**, sign in to Intuit, and choose the company that should receive finalized ARMS invoices. Intuit returns you to ARMS after authorization. Review the company name before selecting **Connect company**. You can cancel without changing the existing connection. Canceling revokes the pending authorization and removes its stored credential. Start **Connect QuickBooks Online** again when you are ready. Map every customer location and service type used by your invoices. An invoice cannot synchronize until all required mappings are valid. ## Configure Mappings ARMS uses explicit mappings instead of matching names automatically. ### Customer location mappings For each Cedar customer location, search for and select the active QuickBooks Online **Customer** that should receive its invoices. All charges on one ARMS invoice must resolve to the same QuickBooks Online Customer. If they map to different Customers, the invoice needs attention. ### Service type mappings For each Cedar service type, search for and select the active QuickBooks Online **Item** used for that charge. After you correct a missing Customer or Item mapping, ARMS automatically requeues affected invoices. You do not need to finalize them again. ## What Gets Synchronized | Cedar ARMS | QuickBooks Online | | ----------------------------------- | ------------------------------------------------------------ | | Finalized invoice | Posting Invoice | | Invoice ID | Document number | | First invoiced charge date | Transaction date | | Mapped customer location | Customer | | Mapped service type | Item | | Charge description | Line description, including equipment details when available | | Charge rate and calculated quantity | Unit price and quantity | | Charge amount | Line amount | Only finalized invoices with invoiced charges are eligible. A new eligible invoice is normally queued immediately, and synchronization usually begins within one minute. ## Choose an Unfinalize Policy The policy controls what happens in QuickBooks Online after a synchronized ARMS invoice is unfinalized and then finalized again. It does not change ARMS invoice history. ARMS keeps the existing QuickBooks Online Invoice while the ARMS invoice is unfinalized. When you finalize it again, ARMS updates that same QuickBooks Online Invoice and keeps its QuickBooks Online ID. ARMS voids the existing QuickBooks Online Invoice. If the ARMS invoice is finalized again, ARMS waits for the void to succeed before creating a replacement with a new QuickBooks Online ID. Change the policy under **When a finalized invoice is unfinalized** on the QuickBooks Online settings page. For an invoice generation that ARMS already tracks, unfinalization and re-finalization intent is preserved while synchronization is paused or the company is disconnected. ARMS resumes that proven work only after the eligible connection is safely restored. This does not enroll or backfill invoices first finalized during the disconnected period. ## Monitor Synchronization The settings page shows queued, synchronizing, action-required, and recently successful invoices. A synchronized invoice also shows a link to the matching QuickBooks Online Invoice from its ARMS invoice details. Temporary Intuit, network, and throttling failures move to **Retrying**. ARMS retries them automatically with increasing delays and duplicate-safe request identifiers. If automatic retries are exhausted, the invoice moves to **Action required**. Common action-required conditions include: * A Customer or Item mapping is missing or no longer active * Charges on one invoice map to more than one QuickBooks Online Customer * The invoice no longer contains eligible invoiced charges * Intuit authorization was revoked or expired * QuickBooks Online rejected the invoice data When authorization must be renewed, select **Reconnect QuickBooks Online**, authorize the company, and confirm it again. Reauthorizing the same company keeps its mappings and resumes eligible work already proven for that company. Connecting a different company requires new mappings and never replays work that belongs to the old company. ## Disconnect Select **Disconnect**, review the company name, and confirm. Disconnecting: * Stops new invoices from being queued * Revokes Cedar's authorization and removes its stored refresh credential * Does not delete or void existing QuickBooks Online Invoices * Does not backfill the disconnected interval after a later reconnect You can reconnect from the same settings page. Only invoices finalized after the new connection is confirmed are eligible. ## Security Cedar requests only the QuickBooks Online accounting permission needed for this integration. Access and refresh tokens are never returned in browser payloads. Cedar stores refresh credentials in its managed secret store and rotates them when Intuit issues a replacement. Connection attempts expire, can be used only once, and are bound to the Cedar user and carrier that started them. ## Troubleshooting The integration must be enabled for your account, and your Cedar role must allow you to view and update invoices. Return to QuickBooks Online settings and start a new connection. An expired or already-used request cannot be confirmed. Open the Customer location mappings and Service type mappings sections. Select active QuickBooks Online records for every source listed on the invoice. Saving the missing mapping automatically requeues matching invoices. Select **Reconnect QuickBooks Online**, sign in to Intuit, select the intended company, and confirm it in ARMS. ARMS synchronizes only invoices finalized after the current connection was confirmed. It does not backfill invoices finalized before connection or during a disconnected interval. ## Related Pages * [Accounting Integrations Overview](/user-docs/accounting-integrations/overview) * [QuickBooks Web Connector for QuickBooks Desktop](/user-docs/accounting-integrations/quickbooks-web-connector) # QuickBooks Web Connector Source: https://docs.cedarai.com/user-docs/accounting-integrations/quickbooks-web-connector Automatically sync Cedar ARMS invoices to QuickBooks Desktop QuickBooks Logo The QuickBooks Web Connector (QBWC) integration automatically syncs your Cedar ARMS invoices to QuickBooks Desktop as Sales Orders. This keeps your accounting records in sync without manual data entry. ## Overview This integration requires **QuickBooks Desktop** (Pro, Premier, or Enterprise). If you use the cloud product, see [QuickBooks Online setup](/user-docs/accounting-integrations/quickbooks-online). The integration works by: 1. Running on a schedule you configure in QuickBooks Web Connector 2. Fetching invoice charges that are eligible under your configured QBWC billing statuses 3. Creating or updating Sales Orders in QuickBooks Desktop 4. Tracking sync status to ensure data consistency By default, only **Invoiced** charges are eligible, so they are fetched after invoice finalization. Cedar can also configure QBWC to include **Assigned** charges for synchronization before finalization. ## What is QuickBooks Web Connector? QuickBooks Web Connector (QBWC) is a free application from Intuit that enables third-party applications like Cedar to exchange data with QuickBooks Desktop. It runs in the background on your Windows computer and periodically syncs data between Cedar and your QuickBooks company file. Intuit's official guide for installing and configuring QBWC Get the latest version from Intuit Developer Fix common QBWC error codes (QBWC1005, QBWC1006, etc.) Detailed technical documentation from Intuit ## Prerequisites Before setting up the integration, ensure you have: * **QuickBooks Desktop** (Pro, Premier, or Enterprise) installed * **QuickBooks Web Connector** installed — [download from Intuit](https://developer.intuit.com/app/developer/qbdesktop/docs/get-started/get-started-with-quickbooks-web-connector) and follow their [official setup guide](https://quickbooks.intuit.com/learn-support/en-us/help-article/install-products/set-quickbooks-web-connector/L4Vp7VI44_US_en_US) * **Administrator access** to both QuickBooks and your Cedar account * **Customers configured** in QuickBooks with names matching the GL numbers in Cedar * **Service items configured** in QuickBooks matching your Cedar service types If you're new to QuickBooks Web Connector, we recommend reviewing Intuit's [official setup guide](https://quickbooks.intuit.com/learn-support/en-us/help-article/install-products/set-quickbooks-web-connector/L4Vp7VI44_US_en_US) first. It includes screenshots and detailed instructions for installing and configuring QBWC. ## Setup Contact Cedar support to enable the QuickBooks Web Connector integration for your account. You'll receive: * A **QWC file** (QuickBooks Web Connector configuration file) * A **password** for authentication Keep your QBWC password secure. It provides access to sync data between Cedar and QuickBooks. 1. Open QuickBooks Web Connector 2. Click **Add an Application** 3. Select the QWC file provided by Cedar 4. When prompted, open your QuickBooks company file 5. Authorize the Cedar application to access your QuickBooks data In QuickBooks Web Connector: 1. Find the Cedar application in the list 2. Click in the **Password** column 3. Enter the password provided by Cedar support 4. Check the box to save the password Before enabling automatic sync, run several manual syncs to verify the integration works correctly: 1. Click **Update Selected** to run a manual sync 2. Check that the sync completes without errors 3. Verify Sales Orders appear in QuickBooks matching your Cedar invoices 4. Review the data mapping (customers, service items, amounts) 5. Run 2-3 more manual syncs to confirm consistency If the sync behavior is not what you expect (wrong customers, missing items, incorrect amounts), **do not enable auto-sync**. Contact Cedar support at [support@cedarai.com](mailto:support@cedarai.com) to resolve any issues before proceeding. Once you've verified the integration works correctly with manual syncs: 1. Select the Cedar application 2. Set the **Auto-Run** interval (e.g., every 30 minutes) 3. Enable **Auto-Run** We recommend syncing every 15-30 minutes during business hours to keep your accounting data current without overloading the system. ## How Invoices Are Synced ### Invoice to Sales Order Mapping Each Cedar invoice becomes a Sales Order in QuickBooks: | Cedar Invoice Field | QuickBooks Sales Order Field | | ------------------- | ---------------------------- | | Invoice ID | Reference Number | | Invoice date | Transaction Date | | Customer GL Number | Customer | | Charges | Line Items | ### Charge to Line Item Mapping Each charge on an invoice becomes a line item: | Cedar Charge Field | QuickBooks Line Item Field | | --------------------------------- | -------------------------- | | Service Type | Item | | Description (with equipment info) | Description | | Rate | Rate | | Calculated quantity | Quantity | | Amount | Amount | The line item description includes the railcar number (e.g., "BNSF 123456 | Storage | Railcar Storage") to help you identify specific equipment on the invoice. ## Sync Behavior The examples below distinguish the default **Invoiced-only** policy from a connection configured to include **Assigned** charges. ### New Invoices Under the Default Policy Under the default Invoiced-only policy, finalizing an invoice makes its charges eligible: 1. The next QBWC sync picks up the new invoice 2. A new Sales Order is created in QuickBooks 3. The sync status is tracked to prevent duplicates When Assigned is enabled, eligible Assigned charges can synchronize before invoice finalization. QBWC creates or updates the Desktop Sales Order using the charges whose statuses are currently enabled. ### Updated Invoices When eligible charges are added or removed from an existing invoice: 1. The QBWC sync detects the change 2. The existing Sales Order in QuickBooks is updated 3. Line items are replaced with the charges that remain eligible under the configured billing statuses ### Unfinalized Invoices Under the Default Policy Under the default Invoiced-only policy, unfinalizing a synced invoice makes its charges ineligible: 1. The QBWC sync detects that the invoice no longer has eligible charges 2. The Sales Order is deleted from QuickBooks 3. You can re-finalize and synchronize it again when ready When Assigned is enabled, unfinalization does not necessarily delete the Desktop Sales Order. The Sales Order remains and is updated as long as at least one charge remains eligible under the configured billing statuses. QBWC deletes it only after no eligible charges remain. ## Configuration Checklist Before syncing, ensure the following items are configured correctly in both Cedar and QuickBooks. Most sync errors can be resolved by checking these settings. ### Cedar Configuration Each **Customer Location** in Cedar must have a **GL Number** configured. This GL number is used to match the customer in QuickBooks. **In Cedar ARMS:** 1. Go to the Customer Location settings 2. Find the **General Ledger Number** field 3. Enter a value that matches the customer name in QuickBooks (or note it to create a matching customer in QuickBooks) Charges without a GL number on their customer location will **not sync** to QuickBooks. They are intentionally skipped to prevent errors. Each **Service Type** used on charges must match a **Service Item** name in QuickBooks exactly. You can either: * Update service types in Cedar to match existing QuickBooks items, OR * Create new service items in QuickBooks to match Cedar's service types **Common service types include:** * Storage * Switching * Demurrage * Handling For accurate rate and quantity display in QuickBooks: * Charges with rate information will show the **rate** and **calculated quantity** * Charges without rate information will show the **total amount** as the rate with **quantity = 1** To ensure rates sync correctly, configure your rates in Cedar's rate management. The rate is extracted from the charge's rate information. The default QBWC policy synchronizes only **Invoiced** charges. Under that policy: 1. Create charges in ARMS 2. Assign charges to an invoice 3. Finalize the invoice to set charges to "Invoiced" status Cedar can configure QBWC to include **Assigned** charges when your accounting workflow needs an earlier sync. With that configuration, Assigned charges can appear in QuickBooks before invoice finalization. Ask your Cedar administrator which statuses are enabled for your connection. ### QuickBooks Configuration If you already have customers and service items in QuickBooks, you can skip creating new ones and instead update the GL numbers and service types in Cedar to match your existing QuickBooks data. Each GL number in Cedar must correspond to a **Customer** in QuickBooks. You can either: **Option A: Update Cedar to match QuickBooks** * Set the GL number in Cedar to match an existing QuickBooks customer name **Option B: Create customers in QuickBooks to match Cedar** 1. Go to **Customers** → **Customer Center** 2. Click **New Customer & Job** → **New Customer** 3. Enter the **Customer Name** exactly matching the GL number in Cedar | Cedar GL Number | QuickBooks Customer Name | | --------------- | ------------------------ | | `ACME-001` | `ACME-001` | | `Customer ABC` | `Customer ABC` | Names must match **exactly**, including capitalization and special characters. Each service type in Cedar must correspond to a **Service Item** in QuickBooks. You can either: **Option A: Update Cedar to match QuickBooks** * Change your service types in Cedar to match existing QuickBooks service item names **Option B: Create service items in QuickBooks to match Cedar** 1. Go to **Lists** → **Item List** 2. Click **Item** → **New** 3. Select **Service** as the item type 4. Enter the **Item Name** exactly matching the Cedar service type | Cedar Service Type | QuickBooks Service Item | | ------------------ | ----------------------- | | `Storage` | `Storage` | | `Switching` | `Switching` | | `Demurrage` | `Demurrage` | Ensure customers and service items are **Active** in QuickBooks. Inactive items will cause sync errors. ### Quick Reference: What Must Match The GL numbers and service types in Cedar must match the customer names and service items in QuickBooks. **You can update either system** to make them match — whichever is easier for your workflow. | Cedar Field | QuickBooks Field | Notes | | ----------------------------- | ----------------- | -------------------------------------------- | | Customer Location → GL Number | Customer Name | Must match exactly | | Charge → Service Type | Service Item Name | Must match exactly | | Charge billing status | — | Invoiced by default; Assigned can be enabled | **Already have customers and items in QuickBooks?** Instead of creating new ones, you can update the GL numbers and service types in Cedar to match your existing QuickBooks data. ## Troubleshooting For QBWC-specific error codes (QBWC1005, QBWC1006, QBWC1007, etc.), see Intuit's official guide: [Fix common Web Connector errors](https://quickbooks.intuit.com/learn-support/en-us/help-article/open-programs/fix-common-web-connector-errors-quickbooks-desktop/L9slolvg0_US_en_US) * Verify your password is entered correctly in QBWC * Ensure the password hasn't expired (contact Cedar support if needed) * Check that QuickBooks is open and logged in during sync Charges require a **General Ledger (GL) Number** on the customer location to sync. Check that: 1. The customer location in Cedar has a GL number configured 2. The GL number matches a customer name in QuickBooks 3. The charge has a billing status enabled for your QBWC connection The default policy requires Invoiced charges. Assigned charges are eligible only when Cedar has configured that status for your connection. Charges without a GL number are intentionally skipped to prevent errors in QuickBooks. The customer name in QuickBooks must exactly match the GL number configured in Cedar. To fix: 1. Check the GL number on the customer location in Cedar 2. Ensure a customer with that exact name exists in QuickBooks 3. Create the customer in QuickBooks if missing 4. Verify the customer is **Active** (not inactive) Each service type in Cedar must have a matching Service Item in QuickBooks. To fix: 1. Check which service types are on the failing invoice in Cedar 2. Create matching Service Items in QuickBooks (**Lists** → **Item List** → **New** → **Service**) 3. Ensure the names match exactly (case-sensitive) 4. Verify the item is **Active** The integration extracts rate information from the charge's rate configuration: * If rate info exists: displays the **rate** and **calculated quantity** (amount ÷ rate) * If no rate info: displays the **total amount** as rate with **quantity = 1** To fix, ensure your rates are properly configured in Cedar's rate management. This can happen if a sync was interrupted. The next sync will automatically update the existing Sales Order instead of creating a duplicate. If invoices are stuck in a pending state: 1. Close and reopen QuickBooks Web Connector 2. Click **Update Selected** to force a manual sync 3. Contact Cedar support if the issue persists This happens when an invoice no longer has charges eligible under your configured QBWC billing-status policy. Under the default Invoiced-only policy, unfinalizing an invoice makes its charges ineligible and the corresponding Sales Order is automatically deleted from QuickBooks. To restore it under the default policy, re-finalize the invoice in Cedar. It will synchronize again on the next run. ## Best Practices QBWC requires QuickBooks to be open and logged in during sync. Consider running it on a dedicated workstation. Schedule syncs during times when QuickBooks is actively used to ensure the company file is open. Periodically check QBWC logs for errors and address customer/item mapping issues promptly. Ensure all customer locations have GL numbers configured before finalizing invoices. ## Getting Help If you encounter issues not covered here: * Check the QuickBooks Web Connector log for detailed error messages * Review [Intuit's official troubleshooting guide](https://quickbooks.intuit.com/learn-support/en-us/help-article/open-programs/fix-common-web-connector-errors-quickbooks-desktop/L9slolvg0_US_en_US) for QBWC-specific errors * Contact Cedar support at [support@cedarai.com](mailto:support@cedarai.com) for Cedar-specific issues ## Related Pages * [Accounting Integrations Overview](/user-docs/accounting-integrations/overview) * [QuickBooks Online Setup](/user-docs/accounting-integrations/quickbooks-online) # Activity Log Source: https://docs.cedarai.com/user-docs/admin/activity-log Review changes made in the Admin Portal. The Activity Log shows a history of all changes to access and identity settings. Use it for audits, troubleshooting, and compliance. Activity log showing recent access changes ## What you can see Every entry in the log includes: Who made the change (email address) What was changed (user, group, role, binding) What happened (create, update, delete) When it happened ## When to use the Activity Log Review who has made changes over a period of time. Useful for compliance reviews and security audits. **Example questions:** * Who created this binding? * When was this group modified? * What changes were made last week? Investigate when something stopped working. Look for recent changes that might explain the issue. **Example scenario:** A user suddenly can't access a feature. Check if their group membership or binding was recently changed. Confirm that changes you requested were actually made. After asking someone to update access, check the log to verify. ## Understanding actions | Action | Meaning | | ------------- | --------------------------------- | | `create` | A new resource was created | | `update` | An existing resource was modified | | `delete` | A resource was removed | | `add_user` | A user was added to a group | | `remove_user` | A user was removed from a group | ## Best practices Review the activity log periodically, not just when there's a problem. This helps you catch unexpected changes early. When troubleshooting, note when the issue started and look for changes around that time. If you see a change you don't recognize, follow up with the actor to understand why it was made. The Activity Log is read-only. You can't undo changes from here—you'll need to make corrective changes through the appropriate pages (Users, Groups, Roles, or Bindings). ## Related pages See recent activity at a glance Review access grants Check group memberships Review user details # Bindings Source: https://docs.cedarai.com/user-docs/admin/bindings Grant access by linking a user group to a role and a scope. A **binding** is the access grant. It connects three things: **who** (user group), **what** (role), and **where** (scope). ## The binding formula **Who** gets access **What** they can do **Where** it applies ``` Binding = User Group + Role + Scope ``` Think of it as: "The **Operations Team** can perform **Operator actions** on **Carrier TRLDBLKDRY**" ## View existing bindings Use the list to search by group, role, or resource. This is helpful for audits or troubleshooting access issues. Bindings list showing groups, roles, and resources ## Create a new binding From the Bindings page or Dashboard, click **Add Binding**. Choose which group should receive access. If you haven't created the group yet, do that first. Choose what the group can do. Pick a built-in role or a custom role you've created. Choose where the access applies: * **Carrier** — access to the entire carrier * **Customer** — access limited to a specific customer * **Organization** — access across multiple carriers Carrier-level scope grants broader access. Only use it when the group truly needs access to everything. Review your selections and save. The binding takes effect immediately. Create New Binding dialog with group, role, and resource fields ### Dialog fields explained | Field | Description | | --------------------------- | ---------------------------------------- | | **Group** | The user group that will receive access | | **Role** | The set of permissions to grant | | **Primary Resource Type** | Usually "Carrier" — the main scope level | | **Primary Resource** | The specific carrier (e.g., TRLDBLKDRY) | | **Secondary Resource Type** | Optional narrower scope (e.g., Customer) | ## Binding details Binding details panel ## Common mistakes Picking **Carrier** scope when you meant **Customer** scope grants much broader access than intended. Always double-check the scope before saving. | Scope | Access level | | ------------ | -------------------------------- | | Customer | Limited to one customer's data | | Carrier | All data for the carrier | | Organization | All carriers in the organization | Linking a group to the wrong role (e.g., Admin instead of Operator) can grant too much access. Review role permissions before creating bindings. Creating multiple bindings with the same group/role but different scopes is sometimes intentional, but can also be confusing. Document why you need multiple bindings. Changes to bindings take effect immediately. There's no undo button, so review carefully before saving. ## Best practices Grant the minimum access needed. It's easier to add permissions later than to clean up over-provisioned access. Never create bindings directly to users. Always use groups, even for single users. When creating bindings, make sure the group name and role name clearly indicate the purpose. ## Related: Admin Portal Create groups before binding Understand what roles include Review binding changes Quick term reference ## Related: IAM Concepts Deep dive into identities, resources, and permissions How bindings create policies Understanding scope inheritance Granting customer access with bindings # Dashboard Source: https://docs.cedarai.com/user-docs/admin/dashboard Get a quick view of access coverage, roles, and recent activity. The dashboard gives you a quick snapshot of access across your organization or carrier. It's the fastest way to see what's set up and what might need attention. Admin Portal dashboard overview showing organization scope, metrics, and charts ## Organization scope (optional) Organizations are an optional feature for accounts managing multiple carriers. If you don't see the organization scope section, your account uses single-carrier mode. If your account has an organization set up, the dashboard shows your **organization scope** at the top left. This displays: * The organization name * Number of carriers in scope * Permission layers configured * Carrier bindings Click **Open organization view** to manage your organization hierarchy and layers. See [Organization](/user-docs/admin/organization) for details. ## At a glance Teams with access People across groups Permission sets Active access grants ## What you can do See how many user groups, members, roles, and bindings exist at your carrier. The charts show the distribution between custom and built-in roles. The **Recent activity** section shows the latest changes. Click **View log** to see the full history. Use the action buttons to jump directly to: * **Add Binding** — grant new access * **Create Group** — set up a new team ## When to use the dashboard Quickly verify that access is configured for a new team by checking the metrics and recent activity. After making changes, return to the dashboard to confirm they appear in the activity feed. Use the dashboard as a launchpad to jump directly to Bindings, User Groups, or Roles. ## Next steps Manage organization hierarchy Grant access to groups Manage teams Review permission sets # Getting Started Source: https://docs.cedarai.com/user-docs/admin/getting-started Sign in, choose your carrier, and learn the basics of the Admin Portal. This guide helps new admins get into the portal quickly and confidently. ## Quick start Go to **[https://admin.cedarai.com](https://admin.cedarai.com)** and sign in with your Cedar account. Use the same credentials you use for other Cedar applications. Your work happens within a **carrier** (the rail operator or business you manage). 1. Look at the top of the left sidebar 2. Confirm you see your carrier name (e.g., **TRLDBLKDRY**) 3. If you don't see the right carrier, contact your Cedar admin or Support Carrier selection is shown at the top of the left sidebar Use the left sidebar to access different sections: | Section | What it's for | | ---------------- | ----------------------------------- | | **Users** | Add or manage people | | **User Groups** | Organize people by team | | **Roles** | Define what each group can do | | **Bindings** | Connect a group to a role and scope | | **Activity Log** | Review recent changes | ## Best practices Double-check before you save any changes. There's no "draft" mode—your changes take effect right away. If you're unsure where to begin, start with **User Groups** and **Roles** before creating **Bindings**. This makes it easier to manage access at scale. Always assign access through groups instead of directly to individual users. This makes it much easier to manage access when team members change. ## Next steps Manage individual accounts Organize teams Define permissions Grant access # Glossary Source: https://docs.cedarai.com/user-docs/admin/glossary Key terms used in the Admin Portal. This glossary defines the key terms you'll encounter when using the Admin Portal. Understanding these concepts will help you manage access effectively. For a deeper technical understanding, see the [IAM Concepts guide](/user-docs/iam/concepts). ## Core concepts The rail operator or business you are managing. Everything in the portal is scoped to a carrier. **Example:** TRLDBLKDRY, BNSF, UP Your carrier appears at the top of the left sidebar. All users, groups, roles, and bindings you see are specific to that carrier. A higher-level grouping that can include multiple carriers. **Use case:** A company that operates several regional railroads might group them under one organization for easier management. Organizations allow shared settings and cross-carrier access when needed. An individual person who can sign in to Cedar. Each user has: * Email address (used for login) * Display name * Account status (Registered, Pending, etc.) * MFA settings Users don't have direct permissions—they get access through group membership. A named team of users managed together. **Purpose:** Groups make access management scalable. Instead of assigning permissions to each user individually, you assign them to groups. **Best practice:** Always use groups, even for single users. It's easier to add more people later. A named set of abilities (permissions). **Types:** * **Built-in roles** — provided by Cedar for common jobs * **[Feature sets](/user-docs/iam/feature-sets)** — the columns of the IAM matrix; check one to grant a whole product feature * **Custom roles** — tailored to your organization's needs (best built from matrix columns) Roles define *what* someone can do, not *where* they can do it. The *where* comes from the binding's scope. One column of the IAM matrix on the [Roles](/user-docs/admin/roles) page. Each column represents a single product feature at a specific access level — for example **Notes — View**, **Inventory waybills — Operate**, or **Reporting — Manage**. Checking the box on a row grants every permission that role needs to use that feature. **Three standard levels:** * **View** — read-only access to the feature * **Operate** — create, edit, and delete your own work in the feature * **Manage** — moderate other people's work and change feature-level settings **Why use them:** Cedar maintains the columns. When a feature gains a new capability, every role with that column checked picks it up automatically — no admin work required. Custom roles built from hand-picked permissions don't get this, and silently drift as the product grows. See the [Feature Sets guide](/user-docs/iam/feature-sets) for full details. The access grant that connects a user group to a role and a scope. **Formula:** `Binding = User Group + Role + Scope` **Example:** "The Operations Team (group) can perform Operator actions (role) on Carrier TRLDBLKDRY (scope)" Without a binding, groups have no permissions. Where a role applies, such as a carrier or customer. **Scope levels (from narrow to broad):** | Scope | Access | | ------------ | -------------------------------- | | Customer | One customer's data | | Carrier | All data for the carrier | | Organization | All carriers in the organization | Always use the narrowest scope that meets your needs. ## Portal sections Overview of access metrics and recent activity Where you create and manage access grants Where you view and create permission sets Where you manage individual accounts Where you organize users into teams Audit trail of all changes Identity provider provisioning connections Organization setup, enablements, API keys ## How concepts relate ```mermaid theme={null} flowchart LR U[Users] --> G[User Groups] G --> B[Bindings] R[Roles] --> B S[Scope] --> B B --> A[Access Granted] style U fill:#E0F2FE style G fill:#E0F2FE style R fill:#F5F3FF style S fill:#ECFDF5 style B fill:#FEF3C7 style A fill:#D1FAE5 ``` 1. **Users** are added to **User Groups** 2. **Roles** define permissions 3. **Bindings** connect groups to roles with a scope 4. Result: **Access is granted** | Term | Answers | Managed in | | ------- | ---------------------- | ---------------- | | User | Who is this person? | Users page | | Group | What team are they on? | User Groups page | | Role | What can they do? | Roles page | | Scope | Where can they do it? | Bindings page | | Binding | Put it all together | Bindings page | ## Deep dive: IAM Concepts These conceptual guides explain the **why** behind IAM and provide technical details for advanced users. How identity & access management works in Cedar Deep dive into identities, resources, and permissions How bindings create policies The columns of the IAM matrix — Cedar curates them so your roles stay current The problem IAM solves ## Start using the Admin Portal Practical walkthrough Admin Portal introduction # Organization Source: https://docs.cedarai.com/user-docs/admin/organization Manage your organization hierarchy, layers, and access controls. The Organization page becomes available after Cedar sets up your initial organization structure. Once enabled, you can manage your own organization hierarchy, including creating layers and assigning access. Once your organization is set up, the **Organization** menu item appears in the sidebar, allowing you to manage your organization's structure. Organization page showing hierarchy tree and role bindings ## What you can do See your organization's structure as a visual tree Add new organizational layers (divisions, regions, etc.) Drag and drop to reorganize the hierarchy Assign roles and access at each level ## Understanding the hierarchy The organization hierarchy is a tree structure that represents how your business is organized. Each level in the hierarchy can have: * **Name** — A descriptive label for the layer * **Child layers** — Sub-divisions nested underneath * **Bindings** — Role assignments that grant access at this level Access is inherited down the hierarchy. Users with access to a parent layer automatically have access to all child layers beneath it. ## Create a new layer Layers allow you to structure your organization into logical divisions (e.g., regions, departments, business units). From the Organization page, click the **New layer** button in the Hierarchy section. Give the layer a descriptive name that reflects its purpose in your organization. Choose the parent layer in the hierarchy. Select "No Parent" for a top-level layer, or choose an existing layer to nest underneath. Click **Create Layer**, then configure bindings to grant access at this layer level. Create Layer dialog with name and parent selection ### Dialog fields explained | Field | Description | | ---------- | ----------------------------------------------------------------------------- | | **Name** | A descriptive name for the layer (e.g., "West Region", "Operations Division") | | **Parent** | The parent layer in the hierarchy, or "No Parent" for top-level layers | ## Reorganize with drag and drop You can rearrange the hierarchy by dragging layers to new positions: 1. Click and hold on a layer in the tree 2. Drag it to its new parent 3. Release to reparent the layer Reparenting a layer moves all its children and affects access inheritance. Users who had access through the old parent may lose access after the move. ## Manage bindings at each level Each layer in the hierarchy can have its own bindings. Click on a layer to see and manage its bindings in the right panel. | Column | Description | | ------------ | ------------------------------------------------- | | **Group** | The user group that has access | | **Role** | The permissions granted | | **Resource** | The scope of access (Organization, Carrier, etc.) | Bindings at a higher level in the hierarchy cascade down to all child layers. You don't need to recreate bindings at every level. ## Best practices Design your hierarchy to match how your organization actually operates. This makes it intuitive for users to understand access levels. Avoid creating too many layers. A deep hierarchy can be confusing and harder to manage. Most organizations work well with 2-4 levels. Layer names should be immediately understandable. Avoid abbreviations or codes that require explanation. Sketch out your hierarchy before creating it. Reorganizing later is possible but affects access inheritance. ## Getting started with organizations Organizations are set up by Cedar as part of the initial configuration. Contact your account representative to enable organization management for your account. To request organization setup: 1. Contact Cedar support or your account representative 2. Describe your organizational structure needs 3. Cedar will configure the initial structure in the [Tools](/user-docs/admin/tools-api-keys) page 4. Once set up, the Organization menu item appears and you can manage it yourself ## Related pages Initial organization setup and advanced options Learn more about role bindings Manage the groups that get access Deep dive into access control # Overview Source: https://docs.cedarai.com/user-docs/admin/overview A friendly guide to the Cedar Admin Portal for managing users, roles, and access. The Admin Portal is where you control who can access Cedar and what they can do. It's designed for admins and operators who manage users, teams, and permissions. ## What you can do Invite new users and manage existing accounts Group users by team or responsibility Create sets of abilities (permissions) Connect groups to roles using bindings Structure carriers into a hierarchy (optional) Track all changes in the activity log Configure SCIM for identity provider sync ## Where to sign in Use the production portal at **[https://admin.cedarai.com](https://admin.cedarai.com)** ## Portal navigation The left sidebar organizes features by workflow: Quick overview of access coverage and recent activity Manage your organization hierarchy (optional — only visible if your account has an organization set up) **Bindings** — connect groups to roles\ **Roles** — define what groups can do **Users** — individual accounts\ **User Groups** — teams of users **Activity Log** — history of all changes **SCIM** — identity provider connections\ **Tools** — organization settings ## Dashboard preview Admin Portal dashboard overview ## Get started Sign in, pick your carrier, and learn basic navigation Manage your organization hierarchy (optional) Find and manage the people who can sign in Organize people by team or responsibility Define what groups can do, and where Connect groups to roles and resources ## How it all fits together The diagram below shows how Admin Portal concepts connect to grant access: ```mermaid theme={null} flowchart TB subgraph Identity["🔐 Identity"] IDP([Identity Provider
Azure AD / Okta]):::optional SCIM([SCIM Provisioning
— optional]):::optional Users[Users] Groups[User Groups] end subgraph Access["🔑 Access Control"] Roles[Roles] Permissions[Permissions] Bindings[Bindings] end subgraph Resources["📦 Resources"] Org([Organization
— optional]):::optional Carrier[Carrier] Customer[Customer] end subgraph Audit["📋 Audit"] ActivityLog[Activity Log] end IDP -.->|auto-sync| SCIM SCIM -.->|syncs| Users SCIM -.->|syncs| Groups Users -->|belong to| Groups Roles -->|contain| Permissions Groups --> Bindings Roles --> Bindings Bindings -->|grant access to| Org Bindings -->|grant access to| Carrier Bindings -->|grant access to| Customer Org -.->|contains| Carrier Carrier -->|contains| Customer Users -.->|tracked in| ActivityLog Groups -.->|tracked in| ActivityLog Bindings -.->|tracked in| ActivityLog classDef optional fill:#f9f9f9,stroke:#999,stroke-dasharray: 5 5 ``` **The key formula:** A **Binding** = **User Group** + **Role** + **Resource Scope**. This is how access is granted in Cedar. ## Learn the concepts Want to understand **why** IAM works the way it does? These guides explain the conceptual foundation. How identity and access management works in Cedar Deep dive into users, groups, roles, and permissions How policies bind members to roles on resources Quick reference for all terms # Roles Source: https://docs.cedarai.com/user-docs/admin/roles Roles define what actions a user group can take. A **role** is a named set of abilities (permissions). Roles are assigned to groups through bindings to grant access. Roles list with search and permissions ## Types of roles Cedar provides built-in roles for common jobs. These are maintained by Cedar and cover typical use cases. **Examples:** * `arms.carrierAdmin` — Full carrier administration * `arms.carrierOperator` — Day-to-day operations * `arms.customerAdmin` — Customer-level administration * `arms.dataWarehouseAdmin` — Data Warehouse settings access (create, list, and read Data Warehouse configuration). Bind this role to a narrowly-scoped user group to limit Data Warehouse access to specific users. Start with built-in roles if you're unsure what permissions you need. Cedar ships **[feature sets](/user-docs/iam/feature-sets)** — the columns of the IAM matrix on this page. Each column represents one product feature at one access level (View, Operate, or Manage), and a single checkbox grants every permission that feature needs. The big win: Cedar maintains the columns. When a feature gains a new capability, every role with that column checked picks it up automatically. Roles built from hand-picked permissions don't get that, so prefer matrix columns whenever possible. Create custom roles when built-in roles don't match your needs exactly. **When to use:** * You need a specific combination of permissions * Built-in roles grant too much or too little access * You want to enforce least-privilege access Keep custom roles focused. A role that does "everything" defeats the purpose of access control. Build custom roles by checking [feature set](/user-docs/iam/feature-sets) columns in the matrix instead of opening the raw permission picker. That way Cedar's ongoing curation flows through to your role — when a feature gains a new capability later, your role picks it up automatically. ## Find and review roles Use the search box to find roles by name. Type part of the name to filter the list. Click on a role to see its details and the permissions it includes. Check that the role includes the permissions you need—and nothing more. ## Role details Role details panel with permissions ## Edit role permissions Click on any role to view and edit its permissions. The permissions panel shows all the capabilities included in the role. Role permissions editor showing all included permissions The permissions view displays: * **Role name and parent** — the role's identity and inheritance * **Permission list** — all permissions included in this role * **Permission groups** — permissions organized by feature area Use the search box to quickly find specific permissions within a role. ## Create a custom role Select **New role** from the Roles page. Give your role a clear name and description. The name should indicate what the role allows. | ✅ Good | ❌ Avoid | | ----------------- | ------------------ | | Inventory Viewer | Custom Role 1 | | Billing Read-Only | John's Permissions | Choose the specific permissions this role should include. Only select what's needed. Save the role, then create a **binding** to grant it to a group. Create Role dialog with name, parent, and description fields ### Dialog fields explained | Field | Required | Description | | --------------- | -------- | ------------------------------------------------------------------ | | **Name** | Yes | Unique identifier for the role (e.g., `mycompany.inventoryViewer`) | | **Parent** | Yes | The parent role this role inherits from | | **Description** | No | Brief description of what this role allows | Custom roles inherit permissions from their parent role. Choose a parent that has the base permissions you need, then the child role can add or restrict further. ## Best practices Built-in roles cover most common scenarios. Only create custom roles when you have a specific need that isn't met. Each role should represent a clear job function. If you find yourself adding unrelated permissions, consider creating multiple roles instead. Anyone should be able to understand what a role does from its name. Include the resource type and action level (e.g., "Inventory Editor", "Billing Viewer"). For custom roles, add a clear description explaining what the role is for and who should have it. ## Related: Admin Portal Connect roles to groups Manage the teams that get roles Key terms explained Track role changes ## Related: IAM Concepts The columns of this page's IAM matrix — Cedar curates them so your roles stay current How roles fit into the IAM policy model Deep dive into permissions and conditions Customer-specific role examples # SCIM Source: https://docs.cedarai.com/user-docs/admin/scim Connect your identity provider to Cedar for automated user provisioning. SCIM (System for Cross-domain Identity Management) automates user provisioning. Your identity provider can automatically create, update, and deactivate users in Cedar. This page covers **creating SCIM mappings in the Admin Portal**. For technical setup in your identity provider, see the [SCIM Setup Guide](/user-docs/sso/scim/overview). SCIM mappings list with create action ## What SCIM does New employees are added to Cedar automatically User details stay in sync with your IdP Departing employees lose access automatically ## When to use SCIM * Your organization uses an identity provider (Azure AD, Okta, etc.) * You have many users to manage * You want automatic provisioning/deprovisioning * You need to ensure timely access revocation * You have a small number of users * You prefer manual user management * Your identity provider doesn't support SCIM ## Create a SCIM mapping In your identity provider (Azure AD, Okta, etc.), find the SCIM tenant ID that will be used for provisioning. From the SCIM page, click **New mapping**. Paste the SCIM tenant ID from your identity provider. Choose where users should be provisioned: * **Organization** — users can access all carriers in the organization * **Carrier** — users are limited to a specific carrier Choose carefully. This determines the scope of access for all users provisioned through this mapping. Save the mapping, then configure your identity provider to use the provided client ID and secret. Associate Tenant dialog with tenant ID and organization/carrier selection ### Dialog fields explained | Field | Required | Description | | ---------------- | ------------ | ------------------------------------------------------- | | **Tenant ID** | Yes | The unique identifier from your identity provider | | **Organization** | One required | Select if users should have access across all carriers | | **Carrier** | One required | Select if users should be limited to a specific carrier | You must select either an organization **or** a carrier — not both. This determines the scope of access for all users provisioned through this mapping. ## SCIM mapping details SCIM mapping details The detail view shows: * **Tenant ID** — the identifier from your IdP * **Organization/Carrier** — where users are provisioned * **Client ID** — used by your IdP to authenticate * **Client Secret** — keep this secure (click to copy) * **Metadata** — creation and update timestamps ## Include deleted mappings Toggle **Include deleted** to see mappings that were removed or deactivated. This is useful for: * Auditing previous configurations * Understanding historical setup * Restoring accidentally deleted mappings ## Best practices The client secret is only shown once. Copy it immediately and store it securely in your identity provider. Before enabling SCIM for your entire organization, test with a small group of users to ensure provisioning works as expected. After setting up SCIM, monitor the Users page to ensure users are being created correctly. SCIM creates users, but you still need to add them to groups and create bindings for access. Consider using your IdP's group sync features. ## Related: SCIM Setup Guides After creating a mapping here, you'll need to configure your identity provider. Use these guides: Supported SCIM features and protocol details Step-by-step Azure configuration ## Related: Admin Portal View provisioned users Organize provisioned users into teams Grant access to provisioned users Monitor provisioning activity # Tools & API Keys Source: https://docs.cedarai.com/user-docs/admin/tools-api-keys Advanced settings for organizations, feature enablements, and API keys. The Tools page contains advanced settings. Some functions are currently restricted to Cedar employees. If you see a warning banner, contact Support before making changes. These advanced options will be available to all customers in a future release. Tools page with organization and enablements tabs ## Available tools Manage how your carrier relates to organizations. **Available actions:** * **Create new Organization** — set up a new organization that can contain multiple carriers * **Add to existing Organization** — attach this carrier to an existing organization Organizations allow you to manage multiple carriers under a single umbrella with shared settings and access controls. Control which advanced features are available for your carrier. This tab may not be visible for all accounts. If available, it allows you to: * Enable/disable specific features * Configure feature-specific settings Changing enablements can affect your users immediately. Review the impact before making changes. Feature enablements are subject to pricing and contract terms. Contact your account representative for details on available features and associated costs. Once Cedar sets up your initial organization structure, you can manage it yourself. See the [Organization](/user-docs/admin/organization) page for details on managing your hierarchy, creating layers, and assigning access. *** ## API Key Management **Coming Soon** — API key management will be available in a future release of the Admin Portal. The information below describes the planned functionality. ### Create an API key Navigate to the API Keys section and click **Create**. Enter a clear description so you know what this key is for. **Good descriptions:** * "Production ERP integration" * "Development testing - John's team" * "Warehouse management system sync" Set up security options: * **IP allowlist** — restrict which IP addresses can use this key * **Expiration** — set when the key should automatically expire * **Scopes** — limit what the key can access (if available) The API key is only shown once. Copy it immediately and store it securely. Never share API keys in code repositories, emails, or chat messages. Use secure secret management. ### API key best practices Anyone reviewing API keys should understand what each key is for without having to ask. Keys that don't expire are a security risk. Set reasonable expiration dates and rotate keys regularly. When possible, restrict API keys to specific IP addresses. This limits damage if a key is compromised. Regularly audit your API keys and revoke any that are no longer in use. Create separate keys for each integration or system. This makes it easier to revoke access without affecting other systems. ## When to contact Support Before creating or modifying organization structures If you're unsure about enabling/disabling features If you need help with API key configuration If you see a warning about restricted functions ## Related pages Manage your organization hierarchy and layers Learn how to use the Cedar API Review changes to settings Key terms explained # User Groups Source: https://docs.cedarai.com/user-docs/admin/user-groups Organize users into groups so you can manage access in one place. User groups let you manage access for a team at once instead of person-by-person. This is the recommended way to grant access in Cedar. User groups list with search ## Why use groups? Change access for many users at once Know exactly who has what access Reduce errors from individual assignments ## Create a group From the User Groups page or Dashboard, click the **Create Group** button. Choose a clear, descriptive name like: * "Customer Admins" * "Operations Team" * "Billing Specialists" Use names that describe the team's function, not individual people. Search for and add the users who should be in this group. Create a **binding** to connect this group to a role and scope. Without a binding, the group has no permissions. Create User Group dialog with name, email, and description fields ### Dialog fields explained | Field | Required | Description | | --------------- | -------- | ---------------------------------------------------------- | | **Name** | Yes | A descriptive name for the group (e.g., "Operations Team") | | **Email** | No | Optional email address for the group | | **Description** | No | Brief description of the group's purpose | ## Group details User group details panel The detail panel shows: * Group name and email * Description * Role assignments (via bindings) * Members in the group ## Add or invite users to a group Users are invited to Cedar through the User Group detail page. This ensures every user has proper access from the start. Click on a group to open its detail panel. In the **Users in Group** section, click the **+** button. Type user email addresses and click **Add** for each one. Invite user dialog Click **Add Users** to complete. New users receive an invitation email; existing users are added immediately. For details on user status and the invitation process, see the [Users documentation](/user-docs/admin/users). ## Best practices Good names describe the team's function clearly. Avoid generic names like "Team 1" or names that include specific people. | ✅ Good | ❌ Avoid | | ------------------- | ----------- | | Customer Admins | Admin Team | | Billing Specialists | John's Team | | Operations - West | Group 1 | Always assign access through groups, even if there's only one person. This makes it easy to add more people later. If different teams need the same role but on different scopes (e.g., different customers), create separate groups for each. A group without a binding has no permissions. After creating a group, always create a binding to grant access. ## Related pages Connect groups to roles Define what groups can do Manage individual accounts Key terms explained # Users Source: https://docs.cedarai.com/user-docs/admin/users Invite, view, and manage individual users. The Users page is where you manage individual people who can sign in to Cedar. Users list with search *** ## How to invite a user Users are invited through the **User Groups** page. When you invite a user, they're automatically added to the group — this ensures every user has proper access from the start. Navigate to **User Groups** in the left sidebar of the Admin Portal. Click on the group you want to add the user to. The group's detail panel will open. In the **Users in Group** section, click the **+** button to open the invitation dialog. Type the user's email address and click **Add** to add it to the list. You can add multiple emails. Invite user dialog Click **Add Users** to send invitation emails. The users will appear in the group with **Invited** status. Each user will receive an email with a link to set up their account. Once they complete registration (or sign in via SSO), their status changes to **Registered**. **Why invite through groups?** This design ensures users always have proper access. A user without group membership has no permissions, so inviting directly into a group streamlines onboarding. *** ## How to add an existing user to another group If a user already exists and you want to add them to an additional group: Navigate to **User Groups** in the left sidebar. Click on the group you want to add the user to. Click the **+** button in the **Users in Group** section, enter the user's email, and click **Add Users**. If the user already exists, they'll be added to the group immediately without receiving a new invitation email. Users inherit all role assignments from their groups. This is the preferred approach over assigning roles directly to individuals. *** ## How to check why a user can't log in When someone reports they can't access Cedar, follow these steps to investigate. Use the search box to find the user by their email address. Look at the **Status** column: | Status | Meaning | | -------------- | ------------------------------------ | | **Registered** | Account is active and ready to use | | **Pending** | Invitation sent but not yet accepted | | **Disabled** | Account has been deactivated | Make sure the email address matches exactly what the user is trying to sign in with. Open the user detail panel and verify they belong to a group that has the necessary role bindings for what they're trying to access. If the user's status is **Pending** and they can't find the email, resend the invitation. If a user has no group memberships or their groups have no role bindings, they won't be able to access any resources even if their account is registered. *** ## User details view User details panel Click on any user to see their detail panel, which includes: * **Display name and email** — How they appear in the system * **Account status** — Registered, Pending, or Disabled * **MFA status** — Whether multi-factor authentication is enabled * **Last login time** — When they last signed in * **Group memberships** — Which groups they belong to * **Role assignments** — Direct roles (if any) assigned to this user *** ## User status lifecycle Users go through different states as they interact with Cedar. Understanding these states helps you manage accounts effectively. ```mermaid theme={null} stateDiagram-v2 [*] --> Invited: Admin invites Invited --> Confirmed: Opens email link
(Cedar managed only) Invited --> Registered: First SSO login
(SSO users) Invited --> Invitation_Expired: 2 weeks expire Confirmed --> Registered: Completes registration Registered --> Deactivated: Admin deactivates Deactivated --> Registered: Admin reactivates Invitation_Expired --> Invited: Resend invite note right of Confirmed Optional state Only for Cedar managed users end note ``` Go through **Confirmed** state when they click the email link, then complete registration to become **Registered**. **Skip Confirmed** entirely — they go directly from **Invited** to **Registered** on first SSO login. | Status | Description | Can sign in? | | ---------------------- | ------------------------------------------------------------ | ------------ | | **Invited** | Invitation sent, waiting for user to take action | No | | **Confirmed** | User opened the registration email link (Cedar managed only) | No | | **Registered** | Account is active and fully set up | Yes | | **Invitation Expired** | User didn't respond within 2 weeks | No | | **Deactivated** | Account has been disabled by an administrator | No | **Why SSO users skip Confirmed**: SSO users authenticate through your identity provider (Okta, Azure AD, or Google), so there's no separate email verification step. When they sign in via SSO for the first time, Cedar recognizes them as an external provider user and automatically marks them as Registered. **Invitation expiration**: Invitations expire after **2 weeks**. If an invitation expires, you can resend it from the Admin Portal to reset the timer and move the user back to **Invited** status. **Reactivating users**: If a user was previously Deactivated but has valid credentials (e.g., they previously completed registration), an admin can reactivate them back to Registered status. *** ## SSO users vs Cedar managed users There are two ways users can authenticate with Cedar. Understanding the difference helps you choose the right approach for your organization. **Cedar managed users** have accounts created and maintained directly in Cedar. **How they're created:** * Manually invited through the Admin Portal * You enter their email, first name, and last name **How they sign in:** * Use the Cedar login page * Enter their email and password * Optionally use MFA (if enabled) **Who manages credentials:** * Users set their own password during registration * Password resets go through Cedar * MFA is configured in Cedar **Best for:** * Small teams without an identity provider * External partners or contractors * Organizations not using SSO **SSO users** authenticate through your organization's identity provider (IdP) like Okta, Azure AD, or Google. **How they're created:** * Manually invited through the Admin Portal (same as Cedar managed) * Optionally via [SCIM provisioning](/user-docs/admin/scim) for automated sync **How they sign in:** * Redirected to your identity provider * Authenticate with corporate credentials * Automatically signed into Cedar **Who manages credentials:** * Your IT team manages passwords in the IdP * MFA is enforced by the IdP * Cedar trusts the IdP's authentication **Best for:** * Enterprise organizations with existing IdPs * Centralized security and compliance requirements * Teams wanting single sign-on convenience For SSO setup, see the [SSO documentation](/user-docs/sso/overview). ### Key differences at a glance | Aspect | Cedar Managed | SSO | | ----------------------- | ------------------------------ | ---------------------------------------- | | **Account creation** | Manual invite | Manual invite or SCIM (optional) | | **Password management** | Cedar (Cognito) | Identity Provider | | **MFA** | Cedar SMS-based MFA (optional) | Identity Provider handles MFA | | **Offboarding** | Manually disable in Cedar | Manually disable, or via SCIM if enabled | | **Group sync** | Manual assignment | Manual, or automatic via SCIM if enabled | | **Registration flow** | Invite → Confirm → Register | Invite → Register (skips Confirm) | **MFA for SSO users**: If a user authenticates via SSO (Okta, Azure AD, Google), their MFA settings are managed by your identity provider, not Cedar. The MFA settings in the Admin Portal only apply to Cedar managed users. **Hybrid approach**: You can have both SSO and Cedar managed users in the same organization. This is common when you have internal employees using SSO and external partners using Cedar managed accounts. **Learn more**: For SSO setup instructions, see the [SSO Overview](/user-docs/sso/overview). For optional automated user provisioning, see [SCIM Provisioning](/user-docs/sso/scim/overview). *** ## Best practices Instead of assigning roles directly to users, add users to groups and assign roles to the groups. This makes access much easier to manage when team members change. If someone isn't receiving their invitation email, ask them to check their spam folder. Also verify the email address is spelled correctly. For Cedar managed users, encourage enabling SMS-based MFA for extra security. You can see each user's MFA status in their detail panel. SSO users' MFA is managed by your identity provider. Maintain up-to-date names and email addresses. This helps with auditing and makes it easier for colleagues to identify users. *** ## Related pages Organize users into teams for easier access management See how users get access through group memberships Understand what permissions roles grant Track user activity and changes # Cross-border (Mexico) waybills Source: https://docs.cedarai.com/user-docs/api-reference/cross-border-mexico Carta Porte data requirements for bill-of-lading calls whose origin or destination is in Mexico. Mexican law (SAT *Carta Porte*) requires customs and tariff data on top of a standard bill of lading whenever a shipment crosses the US–Mexico border. Cedar enforces these rules during 824 application advice validation against every waybill created or updated through [`/ims/waybills/bill-of-lading`](/api-reference/create-bill-of-lading) (and every equivalent inbound EDI message). Missing or malformed data surfaces as an `816*` or `825*` error code on the resulting waybill. ## When the requirements apply The Carta Porte data block is required when **both** of the following are true: * `shipmentQualifier` is one of `6` (split first bill), `7` (split subordinate), `B` (single BOL), `C` (consolidated), `F` (stop-off), `M` (master BOL), `S` (submaster BOL), `W` (revenue empty). * Exactly one of `originStation` and `destinationStation` resolves to Mexico (origin **xor** destination — pure intra-Mexico moves are currently not validated by this rule). Cedar resolves the country from `countryCode` if present, otherwise from `stateOrProvince`. Empty, intermodal, switch, blind-memo, and company-business qualifiers (`1`, `8`, `E`, `G`, `H`, `I`, `N`, `X`) are exempt regardless of route. ## Where the data goes Carta Porte data is attached to the **equipment**, not to the top-level `lineItems[]` array: | Array | Schema | Purpose | | ------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------- | | `waybill.lineItems[]` | `LineItem` | Describes the lading commodity for the rail waybill itself. Required on every waybill, MX or not. | | `waybill.equipmentDetails[].shipmentInfo[]` | `EquipmentShipmentInformation` | Per-equipment Carta Porte block transmitted to Mexican customs. Required only for cross-border waybills. | The two arrays are **not** interchangeable. `waybill.lineItems[].quantity` is a nested `LineItemQuantity` object (`billedAsQuantity`, `weightQualifier`, etc.); `shipmentInfo[].lineItems[].quantity` is a flat numeric field corresponding to the X12 417 N1001 element. A cross-border waybill needs both populated. When `waybillTemplateId` is set on a [`/ims/waybills/bill-of-lading`](/api-reference/create-bill-of-lading) request, Cedar merges template data with the request rather than replacing the waybill wholesale. ### `equipmentDetails[].shipmentInfo[]` * Template fields (for example `referenceIdQualifier`, `referenceId`, `extendedReferenceInfo`, commodity scaffolding on line items) fill in when the request omits them. * Request fields override template values **only when the request value is non-null**. An explicit `null` or omitted field in the request does not clear template data. * When the request includes a non-null `shipmentInfo[].lineItems[].weight`, that value is also written to the lead equipment's `netWeightLbs` and `grossWeightLbs` (converted to pounds when `weightUnitCode` is `K`). You can send minimal request `shipmentInfo` containing only dynamic line-item fields (`quantity`, `weight`, `weightUnitCode`) and rely on the template for Carta Porte reference data. ### `parties[]` * **Shipper, consignee, freight bill party, and in-care-of** (one per bill): Cedar merges each matching pair. Request address data is kept unless the template party includes a non-empty address block (name, address lines, city/state/zip, etc.), in which case the template address block is used. Administrative contacts, billing info, and reference info from the request and template are all retained. * **All other party types** (for example Rule 11): every party from the request and every party from the template is kept. Nothing is replaced or deduplicated. ## Required content of each `shipmentInfo[]` entry For each commodity on each piece of equipment: | Field | Required value | | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `referenceIdQualifier` | `UNC` — flags the entry as a UNSPSC-classified commodity. | | `referenceId` | The UNSPSC code. Must exist in Cedar's Carta Porte reference data, otherwise validation returns `816801010CE`. | | `extendedReferenceInfo[]` with `referenceIdQualifier = MTC` | At least one entry. `referenceId` must be a 10-digit Mexico Tariff Rate Code with no punctuation, and must exist in the reference data. | | `lineItems[]` | At least one entry. Each entry must populate `quantity` (N1001), `weight` (N1008), `weightUnitCode` (N1007), and `smallestExteriorPackageType` (N1010). | ## Hazardous shipments If the waybill has any `hazardousInfo[]` entries, every `shipmentInfo[]` block with `referenceIdQualifier = UNC` must additionally include at least one `extendedReferenceInfo[]` entry with `referenceIdQualifier = MHC` (Mexico SAT Hazardous Code). The MHC value must be prefixed with `UN` and must exist in the Carta Porte reference data. ## Required shipper contact Cross-border waybills must include a `parties[]` entry with `partyType = SH` (shipper) that has at least one `administrativeContacts[]` entry containing all of: * `contactFunctionCode = SP` * a non-empty `name` * `communicationNumbers[]` with the first entry `qualifier = TE` (telephone) and a non-empty `number`, and the second entry `qualifier = EM` (email) and a non-empty `number` The same validation runs whether a waybill is created via `/ims/waybills/bill-of-lading` or arrives over EDI. The error codes returned in 824 application advice are identical, so the troubleshooting flow is the same regardless of source. # API Introduction Source: https://docs.cedarai.com/user-docs/api-reference/introduction REST and gRPC APIs for Cedar ARMS — railcar inventory, waybills, work orders, and network structure. The ARMS external API supports HTTP/2 and HTTP/1.1. All endpoints use HTTP POST. ## Regions Cedar's production APIs run in two regions: **US** (primary, `cedarai.com`) and **EU** (`cedarai.se`). Same paths, same headers, same key shape — only the hostname suffix changes. | | US | EU | | ------------------------------ | -------------------------------------- | ------------------------------------- | | Hostname suffix | `cedarai.com` | `cedarai.se` | | REST + gRPC HTTP/2 (ARMS) | `https://api-lg.arms.cedarai.com` | `https://api-lg.arms.cedarai.se` | | gRPC HTTP/1.1 (ARMS) | `https://api-lg-k-h1.arms.cedarai.com` | `https://api-lg-k-h1.arms.cedarai.se` | | Shipper APIs (Quotes/Invoices) | `https://api-lg-k.arms.cedarai.com` | `https://api-lg-k.arms.cedarai.se` | | Notes (Linda) | `https://api.linda.cedarai.com` | `https://api.linda.cedarai.se` | Every other production hostname follows the same `.com` ↔ `.se` mapping — just swap the TLD. **API keys are region-scoped.** A key issued for the US region won't authenticate against an EU host (and vice versa). Use whichever region your account was provisioned in. The per-endpoint reference pages expose a **server dropdown** above each "Try it" cURL snippet so you can flip between US and EU without editing the URL by hand. The base-URL blocks throughout this page are also shown as tabs for the same reason. Staging and dev environments are US-only (`.com`) — there is no `.se` mirror for `-staging` or `-dev` hosts. ## Authentication Include the following headers on every request: | Header | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `x-arms-api-key` | Your API key, issued by Cedar. | | `x-arms-assume-user` | Email of the Cedar user the request is acting on behalf of. **Must be a member of at least one user group bound to the API key.** See the linkage rules below. | | `Content-Type` | `application/json` | ### How API keys, user groups, and assumed users link up Cedar's IAM model makes API keys flow permissions through a user group, not directly through individual users: When the key was created, your admin attached it to one or more user groups (for example, `prod-integrations`). The key can only act as users that are members of those exact same groups. Whatever email you put in `x-arms-assume-user` must be a current member of at least one of the user groups bound to the API key. If the user exists but isn't in a bound group, the request is rejected with **401**. The effective permissions for the request are the union of all roles assigned to the assumed user (via their group memberships and/or direct bindings). A valid key + valid user with no permissions on the target endpoint returns **403**, not 401. ### Choosing what to pass in `x-arms-assume-user` You have two reasonable approaches, and they trade off **operational simplicity** against **audit-trail fidelity**. Pick based on whether your integration needs to attribute every action to the real human in your other system. Use **one dedicated service-account user** for all calls from a given integration (e.g. `integrations@yourco.example`). | | | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **How it works** | Create one Cedar user, put it in one dedicated group (e.g. `api-integrations`), bind the API key to that group, assign one or more [API access roles](#api-access-roles). Every API call sets `x-arms-assume-user: integrations@yourco.example`. | | **Pros** | Zero user management — one user, one group, one role assignment. Rotating the key or adding a second integration changes nothing on the user side. Onboarding is a 5-minute Admin Portal task. | | **Cons** | Cedar's audit log, event history, and `created_by` fields will all read as the service account — you **lose attribution** to the real human in your upstream system. If you need to answer "who did this?", you have to cross-reference your own application logs. | | **Best for** | Background jobs, ETL, batch syncs, webhooks, or any integration where the action genuinely originates from a system rather than a user. | Pass **the actual end-user's email** through `x-arms-assume-user` on every request — typically the user who clicked the button in your application. | | | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **How it works** | Every human user of your upstream system gets a corresponding Cedar user provisioned with the right roles. Your integration captures the calling user and forwards their email in `x-arms-assume-user` per request. The API key is bound to a group that contains all of those users. | | **Pros** | Cedar's audit log, event history, `created_by` fields, and Notes authorship all attribute the action to the real human. Investigations and compliance reviews stay inside Cedar — no cross-system log correlation. Per-user permissions still apply, so a user without a role can't escalate via the integration. | | **Cons** | Every active human in your application must exist as a Cedar user and be a member of the API key's bound group. Joiners, movers, and leavers in your IdP must keep that membership in sync, otherwise users hit **401**. Manually adding everyone in the Admin Portal does not scale. | | **Best for** | Interactive integrations where a human took the action — embedded UIs, partner portals, custom dashboards, mobile companion apps. | **Use SCIM to make Option B sustainable.** [SCIM](/user-docs/sso/scim/overview) provisions users and group memberships into Cedar from your IdP (Okta, Azure AD, etc.) automatically — every joiner, mover, and leaver in your directory is reflected in Cedar without manual Admin Portal work. Bind your API key to a group that's managed by SCIM (e.g. `cedar-api-users`), and your IdP becomes the single source of truth for who can call the API as themselves. New hires get access automatically; departing employees lose it the moment they're deactivated upstream — no orphan service accounts, no out-of-band reviews. Many customers run **both** patterns in parallel: a service-account user for system-to-system jobs, and SCIM-managed pass-through for human-driven flows in their custom apps. Bind the API key to two groups (one per pattern), assign the same API access role(s) to both, and let your client decide which email to send per request. Need an API key? API key management is coming soon to the [Admin Portal](/user-docs/admin/tools-api-keys). Contact your account representative for access. ### AI agents (MCP) Coding agents (Cursor, Claude Desktop, and other MCP clients) can call the same public ARMS APIs documented here through Cedar's **Model Context Protocol** endpoint at `https://mcp.arms.cedarai.com/mcp`. Sign in with your Cedar account via OAuth — there is no separate MCP API key. Carrier admins choose which catalog operations each user may invoke by creating **MCP access** configs in [Cedar Data Depot](https://ddepot.cedarai.com) (open the **MCP** tab after selecting a carrier). Add users as members of a config; if a user belongs to more than one config, their agent sees the union of allowed operations. MCP access management requires Data Depot permissions. If you do not see the **MCP** tab, ask your Cedar account team to grant MCP manager access for your carrier. ### Troubleshooting `401 Unauthorized` A 401 means Cedar couldn't authenticate the request — the key, the assumed user, or the link between them is wrong. Run through this checklist: * **Key is expired or rotated.** Ask your admin to confirm the key is still active in the Admin Portal. Rotated keys stop working immediately. * **Wrong header name.** Cedar expects `x-arms-api-key` (lowercase). Some HTTP clients normalize header casing — verify the wire format if you're behind a proxy. * **Header value contains whitespace or quotes.** The key value should be raw, no `Bearer ` prefix and no surrounding quotes. * **Key was bound to a different environment.** Production keys won't work against staging URLs and vice versa. * **User doesn't exist.** The email in `x-arms-assume-user` must match a real, active Cedar user for your carrier. * **User is deactivated.** Deactivated users fail auth even if the key is valid. Reactivate the user in the Admin Portal. * **Email casing or typo.** The lookup is case-sensitive in some flows — confirm the exact spelling against the user's profile. * **Wrong header name.** Must be `x-arms-assume-user` (lowercase, with the dash before `user`, not `userid`). * **The assumed user isn't in any group bound to the key.** This is the single most common cause. Confirm in the Admin Portal that the user belongs to at least one user group that the API key is also bound to. * **The user group lost its API-key binding.** Group bindings can be removed independently of the key itself. Re-attach the key to the right group. * **The user was removed from the group.** Adding the user back to the bound group fixes auth immediately — no key rotation required. * **Group has no roles.** A user that's in the right group but has no roles assigned will pass auth (avoid 401) but every endpoint will return 403. If you're seeing 401, the linkage itself is missing. * **Real-user pass-through with stale group membership.** If you're using Option B (real users), confirm your IdP push reached Cedar — the user may exist but not yet be in the bound group. [SCIM](/user-docs/sso/scim/overview) usually syncs within a minute; a manual re-push from your IdP is the fastest fix for one-off cases. * **Wrong carrier scope.** API keys are scoped to one carrier. Calling against another carrier's data — for example, by passing a `carrierId` query parameter from a different carrier — fails auth. * **Cross-environment or cross-region call.** Confirm the base URL matches both the environment and the region the key was issued in. Production ARMS uses `api-lg.arms.cedarai.com` (US) / `.se` (EU); production Notes uses `api.linda.cedarai.com` (US) / `.se` (EU); staging/dev use the `-staging` / `-dev` variants and are US-only. See [Regions](#regions) for the full mapping. **Keys are region-scoped** — a US key against an EU host (or vice versa) returns 401. * **Clock skew.** If you sign or timestamp the request out of band, large clock drift can look like 401 from intermediate proxies. Sync your client clock. Capture the **request id** from the failing response (look for the `x-arms-request-id` header) and email [support@cedarai.com](mailto:support@cedarai.com) with: * The full failing endpoint and HTTP method. * The masked `x-arms-api-key` (first 4 characters only) and the `x-arms-assume-user` email. * The response status, headers, and body. * The `x-arms-request-id` so support can trace the request end-to-end in our logs. ## API access roles Cedar ships a **predefined system role per API section** so you can grant a service account the exact permissions it needs without composing custom roles. Assign one (or more) of these to the user that your API key calls as via `x-arms-assume-user`. | Role | Covers | Permissions bundled | | -------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | | `arms.railcarApi` | [Railcar API](#railcar-api-endpoints) (15 endpoints) | 14 (equipment list/move/notes/switch-request, charged history, toolswork, class-lists, customers list, etc.) | | `arms.waybillApi` | [Waybill API](#waybill-api-endpoints) (1 endpoint) | 1 (waybill create) | | `arms.workOrderApi` | [Work Order API](#work-order-api) (9 endpoints) | 5 (work order list/update, task list, train work order list/recordEvent) | | `arms.chargeApi` | [Charges API](#api-documentation) (3 endpoints) | 3 (charges list, exportCharges, viewChargesPage) | | `shipping.invoiceApi` | [Shipper Invoices API](#api-documentation) (3 endpoints) | 3 (invoices list/get/attachVoucher) | | `shipping.quoteApi` | [Shipper Quotes API](#api-documentation) (1 endpoint) | 1 (quotes list) | | `arms.networkStructureApi` | [Network Structure API](#network-structure-api) (1 endpoint) | 2 (grouping listThirdParty, hierarchy summary list) | | `linda.notesApi` | [Notes API](#notes-api) (9 endpoints) | 7 (notes create/list/edit/editAny/delete/deleteAny/search) | Each section role grants only what's needed to call the endpoints in that section. You can combine multiple roles on one user — for example, a finance integration that exports charges and reads invoices would get `arms.chargeApi` + `shipping.invoiceApi`. For pricing-tier roles (`cedar.apiBasic`, `cedar.apiEssential`, `cedar.apiProfessional`), see the [API pricing](/user-docs/api-reference/pricing) page. ## REST endpoints ### Base URL for REST endpoints ``` https://api-lg.arms.cedarai.com ``` ``` https://api-lg.arms.cedarai.se ``` ### Railcar API Endpoints A high-level list of available endpoints: | Endpoint | Description | Docs | | ------------------------------------------ | ------------------------------------------ | --------------------------------------------------------------------------------------- | | `/ims/equipment/inventory` | List railcar inventory | [List railcar inventory API](/api-reference/list-railcar-inventory) | | `/ims/groupings/list` | List groupings for a specific carrier | [List groupings API](/api-reference/list-groupings) | | `/ims/groupings/station-tracks` | List station tracks for a specific carrier | [List groupings API](/api-reference/list-station-tracks) | | `/ims/equipment/move` | Update railcar inventory | [Update railcar inventory API](/api-reference/update-railcar-inventory-move-equipment) | | `/ims/equipment/switch-request` | Submit railcar switch request | [Submit railcar switch request API](/api-reference/submit-railcar-switch-request) | | `/ims/equipment/charged-history` | List railcar charge history | [List railcar charge history API](/api-reference/list-railcar-charge-history) | | `/ims/equipment/bulk-edit-charged-history` | Bulk edit charge history | [Bulk edit railcar charge history API](/api-reference/bulk-edit-railcar-charge-history) | | `/ims/equipment/load-toolswork` | Toolswork: load equipment | [Toolswork load equipment API](/api-reference/toolswork-load-equipment) | | `/ims/equipment/notes/update` | Update equipment notes | [Update equipment notes API](/api-reference/update-equipment-notes) | ### Waybill API Endpoints A high-level list of available endpoints: | Endpoint | Description | Docs | | ------------------------------ | --------------------- | ----------------------------------------------------------------- | | `/ims/waybills/bill-of-lading` | Create bill of lading | [Create bill of lading API](/api-reference/create-bill-of-lading) | | `/ims/waybills/bill-of-lading` | Update bill of lading | [Update bill of lading API](/api-reference/update-bill-of-lading) | Shipments that cross the US–Mexico border have additional required fields beyond the base schema. See [Cross-border (Mexico) waybills](/user-docs/api-reference/cross-border-mexico) before calling `/ims/waybills/bill-of-lading` for a MX origin or destination. ## gRPC transcoded endpoints These endpoints are sent to Envoy over HTTP and get proxied to a gRPC service. ### Base URL for gRPC transcoded endpoints If your service supports HTTP/2, use the following base URL: ``` https://api-lg.arms.cedarai.com ``` ``` https://api-lg.arms.cedarai.se ``` If your service does not support HTTP/2, use the following base URL: ``` https://api-lg-k-h1.arms.cedarai.com ``` ``` https://api-lg-k-h1.arms.cedarai.se ``` ### Work Order API A high-level list of available endpoints: | Endpoint | Description | Docs | | ------------------------------- | ----------------------- | -------------------------------------------------------------------------------------- | | `/t/v1/arrive-train` | Arrive train | [Arrive Train API](/api-reference/workorderservice/arrive-train) | | `/t/v1/depart-train` | Depart train | [Depart Train API](/api-reference/workorderservice/depart-train) | | `/t/v1/list-work-orders` | List Work Orders | [List Work Orders API](/api-reference/workorderservice/list-work-orders) | | `/t/v1/list-work-order-tasks` | List Work Order Tasks | [List Work Order Tasks API](/api-reference/workorderservice/list-work-order-tasks) | | `/t/v1/resequence-train` | Resequence a train | [Resequence Train API](/api-reference/workorderservice/resequence-a-train) | | `/t/v1/update-work-order` | Update a Work Order | [Update Work Order API](/api-reference/workorderservice/update-a-work-order) | | `/t/v1/record-train-event` | Record Train Event | [Record Train Event API](/api-reference/workorderservice/record-train-event) | | `/t/v1/list-train-reason-codes` | List Train Reason Codes | [List Train Reason Codes API](/api-reference/workorderservice/list-train-reason-codes) | | `/t/v1/setout-cars` | Setout Cars | [Setout Cars API](/api-reference/workorderservice/setout-cars) | | `/t/v1/pickup-cars` | Pickup Cars | [Pickup Cars API](/api-reference/workorderservice/pickup-cars) | ### Network Structure API A high-level list of available endpoints: | Endpoint | Description | Docs | | ------------------------- | --------------------------- | ----------------------------------------------------------------------------------------- | | `/t/v1/network-hierarchy` | Fetch the Network Hierarchy | [Network Structure API](/api-reference/networkstructureservice/get-the-network-hierarchy) | ### Notes API Threaded notes on shipments, equipment, waybills, work orders, invoices, and other records. See the [Notes user guide](/user-docs/arms/ops/notes) for the in-app experience these endpoints power. The Notes API is served by Cedar's Linda service on its **own dedicated host** — not the ARMS gateway base URL above. Use the base URL below for all `/v1/notes/*` endpoints; calls to `api-lg.arms.cedarai.com/v1/notes/...` will not resolve. #### Base URL for Notes API ``` https://api.linda.cedarai.com ``` ``` https://api.linda.cedarai.se ``` | Endpoint | Description | Docs | | ------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | `/v1/notes/create` | Create a note on an entity | [Create a note](/api-reference/lindaservice/create-a-note) | | `/v1/notes/update` | Update note content and references | [Update a note](/api-reference/lindaservice/update-a-note) | | `/v1/notes/delete` | Soft-delete a note | [Delete a note](/api-reference/lindaservice/delete-a-note) | | `/v1/notes/list` | List notes on an entity (or reverse-lookup) | [List notes](/api-reference/lindaservice/list-notes) | | `/v1/notes/get-summary` | Note count + latest note for one entity | [Get note summary for one entity](/api-reference/lindaservice/get-note-summary-for-one-entity) | | `/v1/notes/batch-get-summaries` | Note summaries for many entities at once | [Batch get note summaries](/api-reference/lindaservice/batch-get-note-summaries) | | `/v1/notes/search` | Full-text search across notes | [Search notes (full-text)](/api-reference/lindaservice/search-notes-full-text) | | `/v1/notes/summarize-entity` | AI summary of a note thread | [AI summary of a note thread](/api-reference/lindaservice/ai-summary-of-a-note-thread) | | `/v1/notes/search-references` | Search referenceable entities for `@`-mentions | [Search referenceable entities](/api-reference/lindaservice/search-referenceable-entities-for-mentions) | ## View OpenAPI Specs Use the links to view and save the OpenAPI specs in JSON format. JSON spec JSON spec JSON spec JSON spec JSON spec JSON spec ## Related guides Manage users, groups, roles, and access Understand identity and access management Configure single sign-on Automate user provisioning API pricing calculator Key terms explained # EDI Waybill Messaging Source: https://docs.cedarai.com/user-docs/arms/edi-messaging Automated EDI transmission for railroad waybills and car orders ## Overview Cedar automates the transmission of EDI (Electronic Data Interchange) messages between railroads. Whether you're sending waybills to connecting carriers, submitting car orders, or managing haulage arrangements, Cedar handles the complexity of interline communication. EDI is the standard method railroads use to exchange shipment information electronically. Cedar generates industry-standard messages that work with all Class I railroads and most regional carriers. *** ## Message Types Cedar supports multiple EDI message types for different operational needs: The standard message for communicating shipment details between railroads. Includes equipment, route, commodity, and party information. Used when shippers or customers submit car orders directly to railroads. Supports sending as either the railroad or the customer. *** ## Automated Transmission Features Send waybill information to connecting carriers automatically, with options to include haulage billing in the same workflow. Submit car orders on behalf of customers, with flexibility to send as your railroad or as the customer depending on your operational needs. Cedar tracks EDI acknowledgments and maintains a complete audit trail of all messages sent and received. *** ## Workflow Integration EDI messaging integrates with Cedar's workflow automation system: ```mermaid theme={null} flowchart LR Trigger[Waybill Event] --> Workflow[Automation Workflow] Workflow --> EDI[EDI Transmission] EDI --> Carrier[Connecting Carrier] Carrier --> Ack[Acknowledgment] Ack --> Status[Status Update] ``` A waybill event triggers the workflow (new waybill, update, etc.) Cedar processes the waybill according to your workflow configuration EDI messages are generated and sent to the appropriate recipients Acknowledgments are tracked and waybill status is updated *** ## Related Features Automated haulage bill generation for movement carriers. Railinc-compliant waybill submission with full normalization. Terminal switching services billing automation. *** ## Getting Started EDI messaging is configured through Cedar's workflow automation. Contact your Cedar implementation team to set up your EDI workflows. For questions about EDI configuration or to enable additional features, contact your Cedar account team or email **[support@cedarai.com](mailto:support@cedarai.com)**. # Forward & Store Waybills Source: https://docs.cedarai.com/user-docs/arms/forward-and-store Railinc-compliant waybill submission with automatic normalization ## What is Forward & Store? **Forward & Store (F\&S)** is Railinc's centralized waybill repository that facilitates interline settlement and car tracing across the North American rail network. When you submit waybills to F\&S, they become available to all connecting carriers who need the information. Railinc is the railroad industry's technology provider. Their Forward & Store system is the authoritative source for waybill information used in interline operations. *** ## Why F\&S Compliance Matters Submitting non-compliant waybills to Forward & Store can result in: - **Rejection** of your waybill submission - **Settlement delays** when interline charges can't be reconciled - **Operational issues** when connecting carriers lack accurate information Cedar automatically handles F\&S compliance requirements so you don't have to manage them manually. *** ## Automatic Normalization When you send waybills through Cedar's F\&S automation, the system automatically applies industry-required transformations: Cleans up route information to meet F\&S requirements, including removing haulage details that downstream carriers don't need to see. Ensures all required references are present and properly formatted, and normalizes party data to meet Railinc validation rules. Applies appropriate billing codes and equipment defaults based on the shipment type and load status. F\&S normalization goes beyond simple route cleanup - it applies the full set of transformations required for Railinc compliance. *** ## How It Works ```mermaid theme={null} flowchart LR Waybill[Original Waybill] --> Cedar[Cedar F&S Processing] Cedar --> Normalized[Normalized Waybill] Normalized --> Railinc[Railinc F&S] Railinc --> Carriers[Connecting Carriers] ``` Your waybill with full route and party information Cedar applies all required F\&S transformations automatically The compliant waybill is submitted to Railinc Connecting carriers access the waybill through F\&S *** ## Validation & Error Handling Cedar validates waybills before submission and provides clear feedback when issues are found: Checks for required fields and formatting before sending to Railinc. When validation fails, Cedar reports exactly what needs to be corrected. If a waybill can't be normalized (for example, missing required party information for Rule 11 shipments), Cedar will report the specific issue so you can correct the source data. *** ## Integration with Haulage F\&S normalization works seamlessly with Cedar's haulage management: 1. **Haulage bills** are sent to movement carriers with full haulage information 2. **F\&S waybills** are sent to Railinc with haulage information removed This ensures each recipient gets exactly the information they need - movement carriers see the haulage segment, while Railinc and downstream carriers see a clean route. *** ## Getting Started Forward & Store submission is configured through Cedar's workflow automation. Contact your Cedar implementation team to enable F\&S features for your railroad. Work with Cedar to identify which waybills should be submitted to F\&S. Set up automation rules for F\&S submission. Review sample normalized waybills to ensure they meet your requirements. Turn on automated F\&S submission. *** ## Questions? For questions about Forward & Store configuration or troubleshooting submission issues, contact your Cedar account team or email **[support@cedarai.com](mailto:support@cedarai.com)**. # Haulage Management Source: https://docs.cedarai.com/user-docs/arms/haulage Automated haulage billing and EDI messaging for interline rail operations ## What is Haulage? In railroad operations, **haulage** occurs when one railroad uses another railroad's track to move freight. It's a common arrangement that allows railroads to extend their reach without building new infrastructure. The railroad with the **commercial relationship** - they have the customer contract and negotiate rates, but don't own the track for a segment. The railroad that **physically moves** the freight - they own the track and provide the locomotives and crews for that segment. Think of it like a shipping company that doesn't own trucks in a certain region. They contract with a local trucking company to move packages, but the shipping company keeps the customer relationship and handles billing. *** ## Why Haulage Management Matters Without proper haulage management, railroads face: - **Revenue leakage** from missed billing opportunities - **Compliance issues** from incorrect EDI messages - **Operational confusion** from unclear responsibilities Cedar's haulage automation handles the complexity so your team can focus on operations. *** ## How Cedar Handles Haulage Cedar identifies haulage arrangements by analyzing route codes in waybills - no manual flagging required. The system automatically generates the right EDI messages: - **Haulage messages** to movement carriers with appropriate content - **Forward & Store messages** to downstream carriers with cleaned routes Routes are intelligently processed to show only what each recipient needs to see - protecting your commercial relationships while ensuring operational accuracy. Complex routes with multiple haulage segments? Cedar handles them all, generating separate messages for each movement carrier. *** ## Key Features Cedar identifies haulage arrangements from your waybill routes and automatically generates and sends the appropriate EDI messages to movement carriers - no manual tracking required. Routes are automatically processed so each recipient sees only the information they need, protecting your commercial relationships while ensuring operational accuracy. Empty car movements are detected automatically and processed with the appropriate billing codes and documentation. When cars return empty, Cedar reverses routes while preserving haulage relationships and carrier responsibilities. Cedar handles real-world complexity including routes where the same railroad appears multiple times with different roles, or routes with multiple haulage segments. *** ## Supported Scenarios Cedar's haulage module handles a wide range of real-world scenarios: Standard arrangements where your railroad has commercial rights and another performs the movement. Complex routes with haulage arrangements at multiple points along the journey. Whether haulage occurs before or after your railroad's origination point. Routes where the same railroad appears multiple times with different responsibilities (e.g., origin and haulage rights). *** ## Integration with Other EDI Features Haulage management works seamlessly with Cedar's other EDI automation features: Send waybills to connecting carriers with optional haulage support built in. Submit F\&S-compliant waybills to Railinc with automatic haulage route processing. Bill switch carriers for terminal services at origin or destination. *** ## Benefits **Automated Processing** Eliminate manual haulage bill creation and tracking. Cedar processes haulage automatically as waybills flow through the system. **Reduced Errors** Rule-based processing ensures consistent, accurate EDI messages every time. **Faster Turnaround** Real-time processing means haulage bills go out immediately, not when someone remembers to create them. **No Missed Bills** Every haulage arrangement is identified and billed - nothing falls through the cracks. **Accurate Settlement** Correct route and party information ensures proper interline settlement. **Complete Audit Trail** Full visibility into what was sent, when, and to whom. **AAR-Compliant EDI** Messages follow Association of American Railroads standards for interline communication. **Proper Information Sharing** Each carrier sees only what they need to see - protecting commercial relationships. **Consistent Processing** Same rules applied every time, reducing compliance risk. *** ## Getting Started Haulage processing is automatic once your workflows are configured. Contact your Cedar implementation team to enable haulage features for your operations. Identify which carriers you have haulage relationships with. Work with Cedar to set up your EDI workflows with haulage options enabled. Review sample outputs to ensure messages meet your requirements. Enable automated haulage processing in production. *** ## Questions? For questions about haulage configuration or to enable haulage features for your railroad, contact your Cedar account team or email **[support@cedarai.com](mailto:support@cedarai.com)**. # Notes Source: https://docs.cedarai.com/user-docs/arms/ops/notes Add threaded notes with rich formatting, file attachments, entity references, and AI search to shipments, equipment, waybills, and other records. ## Overview Notes are a system-wide way to leave context, observations, and follow-ups on the records you work with every day. Unlike a single free-text field, Notes are a chronological thread — each entry has an author, a timestamp, rich formatting, file attachments, and links to other records in your system. You can use Notes to: * Capture operational context that doesn't fit in a structured field ("waiting on customer to confirm release") * Hand off work between shifts or teams without leaving the record * Attach photos, PDFs, or supporting documents directly to the entity they relate to * Cross-reference equipment, shipments, customers, and other records from inside a note * Search across every note your team has ever written for a given entity Notes are scoped to your carrier. Other organizations that share an entity (for example, a partner railroad on the same shipment) cannot see your notes. *** ## Where you can add notes Notes are available on every major operational record in ARMS. The same threaded experience shows up everywhere, so you only need to learn it once. Document tracking issues, customer communication, or special handling instructions. Capture car-specific context. Coexists with the legacy single-field equipment notes. Note billing exceptions, routing questions, or rebill instructions. Track follow-ups during switching, classification, and yard work. Document disputes, adjustments, or context on individual charges. Note exceptions or follow-ups during car exchanges between carriers. Capture context against an AEI scan event. Record account-level context shared across the team. More entity types are added regularly. If you don't see a Notes button on a record where you expect one, ask your Cedar contact — wiring a new entity in is a small change. *** ## Opening Notes on a record Most detail pages have a **Notes** button in the page header. On Shipments, Notes appear inline as one of the activity tabs alongside Files and History. Navigate to the shipment, equipment, waybill, work order, invoice, charge, or interchange you want to annotate. A side drawer opens on the right with the full note thread for that record. On Shipments, click the Notes tab on the activity panel instead. Append `?notes=open` to the record's URL to open the Notes drawer automatically — useful for sharing direct links over email or chat. The thread reads top-down chronologically — oldest notes at the top, newer below. The first 20 notes load when you open the drawer; click **Load more** at the bottom of the list to fetch the next batch. When you post a new note it appears at the bottom and the thread auto-scrolls to it. *** ## Writing a note The composer at the bottom of the thread supports rich formatting. Type your note and click **Add note** (or press the send shortcut) to post it. ### Formatting The toolbar provides the same editor used elsewhere in Cedar: bold, italic, underline, headings, ordered and unordered lists, links, code blocks, and inline code. Anything you write is stored as Markdown, so notes always render the same in the thread, in summary previews, and in search results. ### Mentioning other records You can link any other record in the system inline by typing `@` in the composer. A typeahead popup opens at the cursor, grouped by record type (Equipment, Shipment, Customer, and so on). Start typing the identifier (car number, shipment ID, customer name, waybill number…). Results are returned across all configured record types and grouped by category. Use the arrow keys to navigate, then press Enter — or click — to insert a reference chip. The chip shows the record's icon and display text. In the saved note, the chip becomes a clickable link that opens that record's detail page in a new tab when right-clicked. Reference chips work across **Equipment, Waybill, Shipment, User, Customer, Work Order, Invoice, Grouping/Fleet, Customer Location, X12 Message, Trip Plan, Workflow, Carrier, Commodity Lot, Motor Carrier**, and more. **Mentions don't notify.** Inserting a reference creates a link and makes the note discoverable in **search** and **Related Notes** — it does **not** send a notification, email, or in-app alert to the referenced user, owner, or watcher. Notes are a passive context channel, not a messaging system. If a record referenced in an old note has since been deleted, the chip renders dimmed with strikethrough text and the tooltip explains that the record no longer exists. Existing notes are never broken by downstream deletions. ### Attaching files Drag files directly into the composer or use the upload button. Images, PDFs, Excel spreadsheets, and other documents are supported. * Attachments upload through Cedar's backend — no browser-to-S3 configuration needed * Attachments appear as thumbnails (for images) or chips (for documents) below the note content * You can remove attachments while editing a note before saving * Each note can carry multiple attachments * **Limits:** up to **10 attachments per note** and **50 MiB per file**. Larger files are rejected before they leave your browser — split big PDFs or compress images to stay under the cap. For inline images that flow with your text, paste a Markdown image (`![alt text](url)`) — the rich text editor will render it inline in both the composer and the saved view. *** ## Editing and deleting your notes Hover over any of your own notes to reveal the actions menu (⋯) on the right. | Action | Who can do it | Notes | | ---------- | ------------------------------- | ------------------------------------------------------------ | | **Edit** | The original author only | Click Edit, modify the content inline, then Save or Cancel | | **Delete** | The original author or an admin | Confirms via dialog before removing the note from the thread | Edited notes show an "(edited)" indicator next to their timestamp so the audit trail stays clear. Carrier admins with the appropriate role can edit or delete any note in the thread, not just their own — useful for removing accidental sensitive data or correcting stale information. *** ## Searching notes within a record The Notes drawer has a search box at the top. Type a query and the thread is replaced with full-text search results from every note on that record. * **Snippet highlighting** — matched terms are highlighted in yellow inside each result snippet * **Reference chip text is searchable** — searching for an equipment number finds notes that linked to that car, even if the number only appears inside a chip * **Hashtag content is searchable** — content inside `#group(...)` syntax (used by automation) is normalized so you can find it by plain words * **Result count** is shown at the top of the results list * Clear the search box to return to the full thread The search is debounced as you type, so you can refine your query without spamming the server. *** ## AI summary For long threads, the **AI Summary** button (sparkle icon) on the notes summary chip generates a one-paragraph digest of the thread on demand. * Click the sparkle icon next to a notes count * A popover opens and shows a summary that captures the key themes, latest status, and any unresolved concerns * Summaries are generated fresh each time — they reflect the current thread, not a cached snapshot * For very long threads, the summary is built from the **100 most recent notes**. Older context isn't included, so summarize earlier and save the result in a fresh note if you need a long-running record to stay accessible. Use AI summary as a fast way to "get up to speed" when picking up a record handed off from another shift, especially on shipments and equipment with extensive history. **AI summary is billed under AI pricing.** All other notes features (writing, viewing, searching, attaching files, references) are included with your Cedar subscription and are not separately metered. *** ## Notes on list pages List pages (Shipments, Inventory, Waybills, Work Orders) include a **Notes** column that summarizes notes per row at a glance. | Cell content | Meaning | | -------------------------------------- | --------------------------------------------------------------------------- | | Note icon + count badge + preview text | The row has notes; the most recent note's first line is shown as a preview | | "Add note" link | The row has no notes yet — click to open the drawer and write the first one | Clicking the cell either opens the Notes drawer in place or navigates to the row's detail page with the drawer open, depending on the screen. Notes columns are **batch-loaded** with the rest of the page, so adding the column doesn't slow down list rendering even on large views. *** ## Related Notes — reverse lookup When a note on one record references another (for example, a shipment note that mentions a piece of equipment), the referenced record's detail page can show a **Related Notes** section listing the notes that mention it. This is useful for answering questions like: * "Are there any notes about this car?" — see notes on the equipment *and* notes on shipments, waybills, and work orders that mentioned it * "What's been said about this customer?" — pull together every cross-entity reference in one place The section caps at the most recent five related notes per record to keep the page focused. *** ## Equipment notes — coexistence with the legacy field Equipment is a special case because the original single-field equipment notes (used by automation, switch requests, and the EDI/API layer) is still in use. The threaded Notes experience runs alongside it. | Surface | Behavior | | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | **Notes button on Car Detail** | Opens the threaded Notes drawer (new system) | | **Inventory grid Notes column** | Shows the legacy single-field notes for in-grid editing, with a separate column for thread previews | | **Automation, switch requests, APIs** | Continue to read and write the legacy `notes` field — no workflow changes required | | **Bridge sync** | When the legacy field is updated by automation or APIs, a corresponding entry is mirrored into the thread so the timeline stays complete | In other words: existing automation keeps working exactly as before, while the threaded Notes system gives your team a richer place to capture context. The legacy single-field equipment notes is still the source of truth for switch requests and automation effects. Don't remove `#sw(...)` or other automation tokens from that field — they're how the system tracks switching state. See [Inventory](/user-docs/arms/ops/inventory#equipment-notes) for more on the legacy equipment notes field. *** ## Permissions Notes use Cedar's standard role-based permissions, configured in the Admin Portal. There are seven permissions, bundled into three [feature sets](/user-docs/iam/feature-sets) that show up as columns in the Admin v2 IAM matrix following the standard `view` / `operate` / `manage` split. | Permission | Grants | | ----------------------- | ---------------------------------------------------------------------------------- | | `linda.notes.list` | Read note threads on any entity for your carrier (also gates the in-drawer search) | | `linda.notes.search` | Use the `@` typeahead while composing a note to look up other records to reference | | `linda.notes.create` | Add a note | | `linda.notes.edit` | Edit your own notes | | `linda.notes.delete` | Delete your own notes | | `linda.notes.editAny` | Edit any user's notes | | `linda.notes.deleteAny` | Delete any user's notes | ### Feature sets * **Notes — View**  ·  `linda.notes.list` + `linda.notes.search`. Read threads, run the in-drawer search, and use the `@` typeahead anywhere references render. * **Notes — Operate**  ·  `linda.notes.create` + `linda.notes.edit` + `linda.notes.delete` + `linda.notes.search`. Author your own notes end-to-end. * **Notes — Manage**  ·  `linda.notes.editAny` + `linda.notes.deleteAny`. Admin override that lets you edit or delete *any* user's notes regardless of authorship. Layer onto any role that should be able to moderate. ### Defaults shipped with each role Cedar wires these feature sets into the standard predefined roles, so most carriers don't need to touch IAM: | Predefined role | View | Operate | Manage | | ---------------------------------------------------- | :--: | :-----: | :----: | | `arms.carrierSuperAdmin` (wildcard `*`) | ✓ | ✓ | ✓ | | `arms.carrierAdmin` | ✓ | ✓ | ✓ | | `arms.carrierOperator` / `carrierNonRevenueOperator` | ✓ | ✓ | | | `arms.shipperAdmin` | ✓ | ✓ | | | `arms.mobileAdmin` | ✓ | ✓ | | | `arms.customerAdmin` / `arms.customerOperator` | ✓ | | | | `arms.drayageDriver` | ✓ | | | | `arms/motorCarrierUser` | ✓ | | | | `arms.historyReporting` | ✓ | | | | `arms.tabroViewer` | ✓ | | | | `arms.groupingViewer` / `arms.groupingTypeViewer` | ✓ | | | | `transload.readonly` / `transload.customerReadonly` | ✓ | | | | `linda.user` | ✓ | | | | `linda.notesApi` (server-to-server) | ✓ | ✓ | ✓ | Override these via [Roles](/user-docs/admin/roles) in the Admin Portal — for example, layering **Notes — Manage** onto a non-admin moderator, granting **Notes — Operate** to a customer-facing role that should leave notes against its own scoped entities, or removing **Notes — View** from a role you'd rather not have reading notes at all. Notes never cross carriers. A user authenticated to Carrier A cannot read, write, or even discover notes belonging to Carrier B, even on entities (like a shared shipment) that both carriers can see. *** ## AI agent context Notes are visible to Cedar's AI agents when answering questions about a record. If you ask "what's going on with shipment X?" or "summarize this car's recent activity," the agent reads the note thread alongside structured data and cites the author and timestamp of any note it draws from. This makes Notes a natural place to leave context you want surfaced when teammates (or you, later) ask Cedar AI for help. *** ## Common workflows Open the shipment, click the Notes tab on the activity panel, and write a brief summary: the current state, anything pending, and who's expected to take the next action. Use `@` to reference the equipment, customer, or waybill so the next person can jump directly to the relevant records. The next shift can use AI Summary to catch up across long threads. Open the equipment in Inventory, click Notes, and drag the damage photos into the composer. Mention the related waybill or shipment with `@` so the photos and context show up in Related Notes on those records too. On the customer's detail page, add a note describing the question and the timeline. Mention the specific shipment or invoice with `@` so the question surfaces from those records via Related Notes. When the question resolves, edit the note (or add a follow-up reply in the thread) — the "(edited)" indicator preserves the history. Open Notes on any affected entity and use the search box. Try typing the equipment number, the customer name, or a keyword like "demurrage" or "rejected." Results show snippet highlights and link to the originating record. On a list page (Shipments, Inventory, Waybills) hover over a row's notes count, then click the sparkle icon for an AI summary popover — no need to open the full drawer. *** ## Related pages Notes appear as a tab on the shipment activity panel. Equipment notes coexist with the threaded notes drawer. Notes drawer on the waybill detail page. Configure who can view, create, edit, and delete notes. Programmatic API for building integrations on top of Notes. # Stale Inventory Cleanup Source: https://docs.cedarai.com/user-docs/arms/stale-inventory-cleanup Automated cleanup system for ghost railcar records ## What This System Does When railcars arrive at your facility, they're marked as "INBOUND" in the system. Sometimes these inbound records are created but the physical railcar never actually arrives - maybe the shipment was cancelled, rerouted, or there was a data entry error. Without cleanup, these "ghost" railcars would stay in your system forever, cluttering reports and making it harder to see your actual inventory. This automated cleanup system identifies and removes these ghost records based on how long they've been inactive. *** ## How We Determine What's "Stale" A piece of equipment is considered **stale** when it has been sitting in an INBOUND state with no recent activity. Activity includes: When billing paperwork is updated When the equipment is added to a train or consist If a railcar hasn't had either of these activities for a certain number of days, it's probably not actually at your facility. ## Configurable Settings These settings can be adjusted in **Settings > Profile > Rail** to control how the cleanup works. ### System Control **Setting name:** `Enable Stale Inventory Cleanup` **What it controls:** Turns the entire stale inventory cleanup system on or off. When disabled, stale equipment will remain in the system indefinitely. This may clutter your inventory reports. **Options:** * ✅ **Enabled** - System runs on schedule * 🛑 **Disabled** - System is paused ### Default Settings These defaults apply to all carriers unless you set up carrier-specific overrides below. **Setting name:** `default_stale_days` **What it controls:** How many days of inactivity before equipment is considered stale. If set to 30 days, any equipment that hasn't been updated or added to a train in the last 30 days will be flagged for deletion. **Business consideration:** * ⬆️ **Higher number** = More conservative, fewer deletions, but more clutter * ⬇️ **Lower number** = More aggressive cleanup, but risk of deleting legitimate equipment **Setting name:** `default_daily_velocity` **What it controls:** The maximum number of stale equipment that can be automatically deleted per carrier in a single day. If set to 50, and 200 pieces of equipment are flagged as stale for Union Pacific, only 50 will be deleted today. The remaining 150 will trigger alerts for manual review. This is a **safety mechanism**. If there's a system error or data issue that incorrectly flags many items as stale, this limit prevents mass deletion disasters. **Business consideration:** * ⬆️ **Higher number** = Faster cleanup, but higher risk if something goes wrong * ⬇️ **Lower number** = Safer, but cleanup takes longer for large volumes ### Carrier-Specific Overrides Override default settings for individual carriers. Only configure carriers that need different settings. **Setting name:** `Stale Inventory Cleanup Overrides` **What it controls:** Custom settings for your carrier that override the defaults. **How it works:** When you configure these settings, they apply to your current carrier (identified by your carrier code). Each carrier can have their own custom thresholds and limits that override the system defaults. **You can optionally set:** * Custom stale threshold (in days) - overrides `default_stale_days` * Custom daily deletion limit - overrides `default_daily_velocity` **Why this exists:** Different carriers have different operating patterns: * 🚂 **Short-line railroads** might need longer grace periods (45+ days) * 🏭 **High-volume Class II carriers** might want faster cleanup (15 days) * 🔒 **Carriers with complex operations** might need lower velocity limits for safety If you don't set carrier-specific overrides, the default settings will be used for your carrier. ## Safety Mechanisms The system has multiple safeguards to prevent accidental data loss. Only a limited number of deletions happen per day, per carrier. Any deletions beyond this threshold are: * ✋ **Not performed** - equipment stays in system * 📝 **Logged** - warnings written to system logs * 📊 **Tracked** - metrics recorded for investigation Equipment in **active transload operations** will **NEVER** be deleted, regardless of age. **What's a transload?** Transferring cargo from one railcar to another (or to a truck). These operations can take time, so equipment must remain in the system even if it looks inactive. Only **INBOUND** equipment is eligible for cleanup. **Protected states:** * 🚂 OUTBOUND - leaving your facility * 🟢 ONLINE - in active use * 🗑️ Already deleted ## What Actually Gets Deleted For a piece of equipment to be deleted, **ALL** of these conditions must be true: Equipment must be in an inbound state No activity (waybill updates or consist assignments) for longer than the stale threshold Equipment is not already marked as deleted Not part of an active transload operation Carrier hasn't exceeded its daily deletion limit If any of these conditions is false, the equipment stays in the system. ## Monitoring & Alerts The system tracks key metrics for monitoring: Tracks how many items were successfully deleted per carrier per run. Tracks how many items were flagged as stale but NOT deleted because they exceeded the daily velocity limit. **If you see high over-velocity numbers:** This could indicate: * 📋 A legitimate backlog that needs attention * ⚠️ A data quality issue causing false positives * 🔧 System problems incorrectly flagging equipment ## Example Scenario **Settings:** * 📅 Default stale threshold: 30 days * 🎯 Default daily velocity: 50 deletions **Situation:** Union Pacific has 200 railcars that haven't been updated in 35 days. All 200 are flagged as stale (35 days > 30 day threshold) Only 50 are actually deleted (velocity limit) The remaining 150 stay in the system A warning is logged about the 150 over-velocity items System metrics are recorded: * ✅ deletions = 50 * ⚠️ overVelocity = 150 Operations team should investigate why 150+ railcars are stale. **Possible causes:** * 📊 Data quality issue? * 🔧 Process problem? * 📦 Real backlog? ## Recommendations for Configuration **Configuration:** ```yaml theme={null} default_stale_days: 45 default_daily_velocity: 25 ``` **Best for:** * Getting started with the system * Organizations with less confidence in data quality * Risk-averse environments **Pros:** * ✅ Minimizes risk of accidental deletions * ✅ More time to catch data entry errors **Cons:** * ⚠️ Slower cleanup of stale records * ⚠️ More clutter in reports **Configuration:** ```yaml theme={null} default_stale_days: 30 default_daily_velocity: 50 ``` ⭐ **This is our recommended starting point** **Best for:** * Most operations * Organizations with good data quality * Standard processing times **Pros:** * ✅ Good balance of safety and efficiency * ✅ Reasonable cleanup speed * ✅ Adequate protection against errors **Configuration:** ```yaml theme={null} default_stale_days: 15 default_daily_velocity: 150 ``` ⚠️ **Advanced users only** **Best for:** * High-volume operations * Organizations with excellent data quality * Fast processing environments **Pros:** * ⚡ Fast cleanup of stale records * ⚡ Minimal clutter **Cons:** * ⚠️ Higher risk if data issues occur * ⚠️ Requires close monitoring initially * ⚠️ Less time to catch mistakes ## Questions to Consider When Configuring * ⚡ **Fast (1-5 days)** → Lower stale\_days acceptable * 🐌 **Slow (2-4 weeks)** → Higher stale\_days needed * ✅ **Very accurate** → Can use higher velocity * ⚠️ **Occasional errors** → Keep velocity conservative * 🧹 **Prefer clean reports** → Lower stale\_days, higher velocity * 🛡️ **Very risk-averse** → Higher stale\_days, lower velocity * ✅ **Yes** → Set up carrier-specific overrides * ❌ **No** → Use defaults for everyone ## Getting Help If you notice unexpected behavior, follow these steps: Review system metrics for unusual patterns Check system logs for warnings about over-velocity Confirm your configuration values in **Settings > Profile > Rail** Reach out to the development team with specific carrier codes and date ranges *** **Quick Summary:** The Stale Inventory Cleanup system automatically removes "ghost" railcar records that have been inactive for too long, with built-in safety mechanisms to prevent accidental data loss. Configure it in **Settings > Profile > Rail** based on your operation's needs. # Switch Billing Source: https://docs.cedarai.com/user-docs/arms/switch-billing Automated billing for terminal switching services ## What is Switch Billing? **Switch billing** is how railroads charge for terminal switching services - the movement of railcars within a yard or terminal area, typically at the origin or destination of a shipment. Moving cars from a shipper's facility to the outbound train. Transferring cars between railroads within a terminal. Moving cars from an inbound train to the consignee's facility. Switch carriers are often short-line railroads or terminal companies that provide local service within industrial areas where line-haul carriers don't operate directly. *** ## Why Automated Switch Billing? Manual switch billing creates problems: - **Missed billing** when switches aren't tracked - **Delayed payments** from late invoice generation - **Disputes** when documentation is incomplete Cedar automates the entire process - from identifying switch carriers in routes to generating and transmitting switch bills. *** ## How Cedar Handles Switch Billing Cedar automatically identifies switch carriers in your waybill routes based on their role codes. For each switch carrier, Cedar generates the appropriate billing document with the correct content. Switch bills are sent electronically to each switch carrier. Cedar tracks acknowledgments to confirm receipt of each switch bill. *** ## Key Features Cedar identifies switch carriers from waybill routes automatically - no manual flagging required. Configure payment terms and routing options to match your switching arrangements. *** ## Integration with Other Features Switch billing works alongside Cedar's other EDI automation features: Send waybills to line-haul carriers and switch bills to switch carriers in coordinated workflows. Routes with both haulage and switch carriers are handled correctly - each carrier gets the right message. *** ## Getting Started Switch billing is configured through Cedar's workflow automation. Contact your Cedar implementation team to enable switch billing for your operations. Determine which switch carriers you work with regularly. Set up automation rules for switch bill generation and transmission. Configure appropriate payment methods for your switch billing arrangements. Turn on automated switch billing. *** ## Questions? For questions about switch billing configuration or to enable additional features, contact your Cedar account team or email **[support@cedarai.com](mailto:support@cedarai.com)**. # Car Actually Placed Webhook Source: https://docs.cedarai.com/user-docs/arms/webhooks/car-actually-placed Event payload sent when a car is placed at a station or track ## Event Overview The **Car Actually Placed** webhook fires when a railcar is physically placed at a station or track in your network. It delivers equipment details, the placement location, loaded/empty status, and the associated work order (if any). This webhook is triggered through ARMS workflow automation. Configure it in your workflow rules to notify external systems when cars arrive at specific locations. *** ## Payload Schema ```json theme={null} { "event_type": "car_actually_placed", "event_timestamp": "2026-03-05T14:30:00+00:00", "work_order_id": "12345", "linked_resources": { "equipment": [ { "resource_id": 123, "car_number": "GCGO 12345" } ], "event_station": { "resource_id": 456, "grouping_type": "station" } }, "attributes": { "is_loaded": true }, "actor": { "resource_type": "User", "resource_id": 12345, "display_name": "ops@customer.com" } } ``` *** ## Field Reference ### Top-level Fields | Field | Type | Required | Description | | ------------------ | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `event_type` | string | Yes | Always `"car_actually_placed"` for this event. | | `event_timestamp` | string (ISO 8601) | No | When the event occurred. `null` if unavailable. | | `work_order_id` | string | No | ID of the associated work order. `null` if the event has no work order. | | `linked_resources` | object | Yes | Equipment and station involved in the event. | | `attributes` | object | Yes | Event-specific attributes. | | `actor` | object or null | Yes | Who caused the triggering event. `null` for system-initiated events. See [Shared Payload Fields -> actor](/user-docs/arms/webhooks/overview#actor). | ### linked\_resources.equipment An array of equipment items being placed. Always an array, even for a single car. | Field | Type | Description | | ------------- | -------------- | ------------------------------------------ | | `resource_id` | integer | Internal equipment identifier. | | `car_number` | string or null | Railroad car number (e.g. `"GCGO 12345"`). | ### linked\_resources.event\_station The station or track where the equipment is being placed. `null` if no station is associated. | Field | Type | Description | | --------------- | ------- | ----------------------------------------------- | | `resource_id` | integer | Internal station identifier. | | `grouping_type` | string | Type of location (e.g. `"station"`, `"track"`). | ### attributes | Field | Type | Description | | ----------- | ------- | ---------------------------------------------- | | `is_loaded` | boolean | `true` if the car is loaded, `false` if empty. | *** ## Example HTTP Request This is the full HTTP request your endpoint receives: ```http theme={null} POST /your-webhook-endpoint HTTP/1.1 Content-Type: application/json X-Webhook-Timestamp: 1709651400 X-Webhook-Signature: X-Webhook-KeyId: cedar-webhooks-2026 X-Webhook-Id: 550e8400-e29b-41d4-a716-446655440000 {"actor":{"display_name":"ops@customer.com","resource_id":12345,"resource_type":"User"},"attributes":{"is_loaded":true},"event_timestamp":"2026-03-05T14:30:00+00:00","event_type":"car_actually_placed","linked_resources":{"equipment":[{"car_number":"GCGO 12345","resource_id":123}],"event_station":{"grouping_type":"station","resource_id":456}},"work_order_id":"12345"} ``` The JSON body is **canonically serialized** (sorted keys, no extra whitespace) so the signature can be verified deterministically. See the [Webhook Overview](/user-docs/arms/webhooks/overview#signature-verification) for verification instructions. *** ## Setting Up This Webhook In ARMS, create or edit a workflow rule that triggers on car placement events. Add the **Car Actually Placed Webhook** effect to the workflow. Provide your endpoint URL. Build an HTTPS endpoint that receives the POST, verifies the signature, and processes the event. Trigger a test event and confirm your endpoint receives and verifies the payload correctly. *** ## Related Signing, verification, public key, and shared HTTP headers. # Workflow Effect Webhooks Source: https://docs.cedarai.com/user-docs/arms/webhooks/overview Real-time event notifications delivered as signed HTTP POST requests ## Overview Cedar's workflow automation can send real-time event notifications to your systems via **webhooks**. When a configured event occurs (such as a car being placed at a station), Cedar POSTs a signed JSON payload to your endpoint. Webhooks let you integrate Cedar events into your own systems -- ERP platforms, notification services, or any HTTP endpoint that can receive JSON. *** ## How It Works ```mermaid theme={null} flowchart LR Event[Workflow Event] --> Effect[Webhook Effect] Effect --> Sign[Sign Payload] Sign --> POST[HTTP POST] POST --> Endpoint[Your Endpoint] Endpoint --> Verify[Verify Signature] ``` A workflow event fires in ARMS (e.g. car placed at a station). Cedar constructs a JSON payload with event details, equipment information, and timestamps. The payload is signed with Ed25519 and POSTed to your configured webhook URL over HTTP/2 (with automatic fallback to HTTP/1.1). Your endpoint verifies the signature using Cedar's public key, then processes the event. *** ## Configuration Each webhook effect requires one input when you set up the workflow in ARMS: | Input | Description | | --------------- | ------------------------------------------------------ | | **Webhook URL** | The HTTPS endpoint where Cedar sends the POST request. | Always use HTTPS endpoints in production. *** ## HTTP Headers Every webhook request includes these headers: | Header | Description | Example | | --------------------- | ---------------------------------------------- | ------------------------ | | `Content-Type` | Always `application/json` | `application/json` | | `X-Webhook-Timestamp` | Unix epoch (seconds) when the request was sent | `1709651400` | | `X-Webhook-Signature` | Base64-encoded Ed25519 signature | `a3F0eGp...` | | `X-Webhook-KeyId` | Identifier for the signing key used | `cedar-webhooks-2026` | | `X-Webhook-Id` | UUID v4 for deduplication | `550e8400-e29b-41d4-...` | *** ## Signature Verification Cedar signs every webhook payload with **Ed25519** so you can verify that requests genuinely came from Cedar and haven't been tampered with. ### Public Key **Use this public key to verify webhook signatures:** ``` MCowBQYDK2VwAyEAuePoYCHOJvZJzlnsxfEv3mtssVKxkDAZsDHUE9Z3TW8= ``` Store this public key in your application configuration. It does not change between environments. ### How Signing Works The signature covers a combination of the timestamp, key ID, and the request body: ``` signing_input = TIMESTAMP + "." + KEY_ID + "." + CANONICAL_JSON_BODY ``` Where: * **TIMESTAMP** is the value of the `X-Webhook-Timestamp` header (string) * **KEY\_ID** is the value of the `X-Webhook-KeyId` header (string) * **CANONICAL\_JSON\_BODY** is the raw request body bytes (JSON with sorted keys and no extra whitespace) The signature is the Ed25519 signature of `signing_input`, base64-encoded in the `X-Webhook-Signature` header. *** ## Security Best Practices Always verify the `X-Webhook-Signature` before processing the payload. This confirms the request came from Cedar and hasn't been modified in transit. Compare `X-Webhook-Timestamp` against the current time. Reject requests older than 5 minutes to prevent replay attacks. Network retries can cause duplicate deliveries. Store processed `X-Webhook-Id` values and skip duplicates. Return a `2xx` response within 30 seconds. If processing takes longer, acknowledge the request immediately and process asynchronously. *** ## Shared Payload Fields Every webhook payload includes the following top-level fields in addition to the event-specific ones documented on each webhook's page. ### actor Identifies the user or system actor that caused the event to fire. Useful for auditing, attribution, and downstream filtering. ```json theme={null} "actor": { "resource_type": "User", "resource_id": 12345, "display_name": "ops@customer.com" } ``` | Field | Type | Description | | --------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `resource_type` | string | The kind of actor. See the table below for known values. | | `resource_id` | integer or string | The actor's internal identifier. Type depends on `resource_type` -- typically integer for users and carriers, string for X12 messages. | | `display_name` | string | Human-readable label for the actor. Best-effort; falls back to a stable synthetic label when no name is available. | Known `resource_type` values: | `resource_type` | When emitted | `display_name` source | | -------------------- | -------------------------------------------------------------------------- | -------------------------------------------- | | `User` | A user triggered the event directly (e.g. placing a car in the UI). | `display_name`, falling back to `email`. | | `WorkflowTrigger` | Another workflow effect fired this event transitively. | Workflow trigger name. | | `WorkflowInvocation` | A specific workflow invocation produced the event (cascading invocations). | Workflow invocation name. | | `Carrier` | An automated carrier-level process (not a human) initiated the event. | Carrier name, falling back to carrier code. | | `X12Message` | An inbound EDI (X12) message drove the state change that fired the event. | `X12Message<{resource_id}>` synthetic label. | `actor` is `null` for cron-scheduled workflows or other system-initiated events that have no identifiable actor. The `actor` key is always present in the payload, so your integration can rely on it being set (possibly to `null`). *** ## Retry Behavior Cedar automatically retries webhook deliveries when transient failures occur. Retries happen in two phases: inline retries during the initial delivery, and deferred retries scheduled over the next 24 hours. ### Inline retries | Condition | Behavior | | -------------------------------- | -------------------------------------------------- | | **Server errors (5xx)** | Retried up to 5 total attempts | | **Timeouts & network errors** | Retried up to 5 total attempts | | **HTTP 408 and 429** | Retried up to 5 total attempts | | **Other client errors (4xx)** | Not retried inline -- fix the issue and redeploy | | **TLS / SSL certificate errors** | Not retried -- the endpoint certificate is invalid | Inline retries use exponential backoff (1--10 seconds between attempts). The first attempt uses a 30-second timeout; retries use a shorter 5-second timeout. If HTTP/2 negotiation fails with a protocol error, Cedar automatically downgrades to HTTP/1.1 on the next attempt. ### Deferred retries If all inline attempts fail, Cedar schedules deferred retries on an hourly cadence: * Retried once per hour for up to **24 hours** or **8 attempts**, whichever comes first. * Each deferred attempt is re-signed with a **fresh `X-Webhook-Timestamp`** (because receivers reject stale signatures) but **keeps the same `X-Webhook-Id`** so your endpoint can deduplicate. * After the retry window closes, the delivery is marked **abandoned** and no further attempts are made. The same `X-Webhook-Id` is sent on every inline and deferred retry attempt. Store processed IDs on your side to deduplicate safely. *** ## Available Webhook Effects Fires when a car is placed at a station or track. Includes equipment details, station, and loaded/empty status. Fires when a train arrives at a station. Includes equipment list, station, loaded/empty status, and train number. Fires when a train consist is defined. Includes wagon list, departure/arrival stations with names, and train ID. Fires when a train departs from a station or customer location. Includes equipment list, station, customer/serving location, loaded/empty status, and train number. *** ## Questions? For questions about webhook configuration or integration, contact your Cedar account team or email **[support@cedarai.com](mailto:support@cedarai.com)**. # Train Arrival Webhook Source: https://docs.cedarai.com/user-docs/arms/webhooks/train-arrival Event payload sent when a train arrives at a station ## Event Overview The **Train Arrival** webhook fires when a train arrives at a station in your network. It delivers equipment details, the arrival station, loaded/empty status, the train number, and the associated work order (if any). This webhook is triggered through ARMS workflow automation. Configure it in your workflow rules to notify external systems when trains arrive at specific locations. *** ## Payload Schema ```json theme={null} { "event_type": "TrainArrival", "event_timestamp": "2026-03-10T08:15:00+00:00", "work_order_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "linked_resources": { "equipment": [ { "resource_id": 100001, "car_number": "TTGX 995823" }, { "resource_id": 100002, "car_number": "BNSF 726451" } ], "event_station": { "resource_id": 500, "grouping_type": "station" } }, "attributes": { "is_loaded": true, "train_number": "T-4521" }, "actor": { "resource_type": "User", "resource_id": 12345, "display_name": "ops@customer.com" } } ``` *** ## Field Reference ### Top-level Fields | Field | Type | Required | Description | | ------------------ | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `event_type` | string | Yes | Always `"TrainArrival"` for this event. | | `event_timestamp` | string (ISO 8601) | No | When the train arrived. `null` if unavailable. | | `work_order_id` | string | No | ID of the associated work order. `null` if the event has no work order. | | `linked_resources` | object | Yes | Equipment and station involved in the event. | | `attributes` | object | Yes | Event-specific attributes. | | `actor` | object or null | Yes | Who caused the triggering event. `null` for system-initiated events. See [Shared Payload Fields -> actor](/user-docs/arms/webhooks/overview#actor). | ### linked\_resources.equipment An array of equipment items on the arriving train. Always an array, even for a single car. | Field | Type | Description | | ------------- | -------------- | ------------------------------------------- | | `resource_id` | integer | Internal equipment identifier. | | `car_number` | string or null | Railroad car number (e.g. `"TTGX 995823"`). | ### linked\_resources.event\_station The station where the train arrived. `null` if no station is associated. | Field | Type | Description | | --------------- | ------- | ----------------------------------------------- | | `resource_id` | integer | Internal station identifier. | | `grouping_type` | string | Type of location (e.g. `"station"`, `"track"`). | ### attributes | Field | Type | Description | | -------------- | -------------- | ----------------------------------------------------------------- | | `is_loaded` | boolean | `true` if the cars are loaded, `false` if empty. | | `train_number` | string or null | Train identifier (e.g. `"T-4521"`). `null` if no train ID is set. | *** ## Example HTTP Request This is the full HTTP request your endpoint receives: ```http theme={null} POST /your-webhook-endpoint HTTP/1.1 Content-Type: application/json X-Webhook-Timestamp: 1709651400 X-Webhook-Signature: X-Webhook-KeyId: cedar-webhooks-2026 X-Webhook-Id: 550e8400-e29b-41d4-a716-446655440000 {"actor":{"display_name":"ops@customer.com","resource_id":12345,"resource_type":"User"},"attributes":{"is_loaded":true,"train_number":"T-4521"},"event_timestamp":"2026-03-10T08:15:00+00:00","event_type":"TrainArrival","linked_resources":{"equipment":[{"car_number":"TTGX 995823","resource_id":100001},{"car_number":"BNSF 726451","resource_id":100002}],"event_station":{"grouping_type":"station","resource_id":500}},"work_order_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"} ``` The JSON body is **canonically serialized** (sorted keys, no extra whitespace) so the signature can be verified deterministically. See the [Webhook Overview](/user-docs/arms/webhooks/overview#signature-verification) for verification instructions. *** ## Differences from Car Actually Placed | Aspect | Car Actually Placed | Train Arrival | | --------------- | -------------------------------- | -------------------------- | | `event_type` | `"car_actually_placed"` | `"TrainArrival"` | | `train_number` | Not included | Included in `attributes` | | Equipment scope | Single car typically | Multiple cars on the train | | Trigger | Car physically placed at a track | Train arrives at a station | *** ## Setting Up This Webhook In ARMS, create or edit a workflow rule that triggers on train arrival events. Add the **Train Arrival Webhook** effect to the workflow. Provide your endpoint URL. Build an HTTPS endpoint that receives the POST, verifies the signature, and processes the event. Trigger a test event and confirm your endpoint receives and verifies the payload correctly. *** ## Related Signing, verification, public key, and shared HTTP headers. Webhook for individual car placement events. Webhook for train departure events, including customer/serving location. The `linked_resources.customer_location` and `linked_resources.serving_location` fields are not currently included in the Train Arrival payload, even though the underlying event carries them. They are included in the [Train Departure](/user-docs/arms/webhooks/train-departure) payload. # Train Departure Webhook Source: https://docs.cedarai.com/user-docs/arms/webhooks/train-departure Event payload sent when a train departs from a station ## Event Overview The **Train Departure** webhook fires when a train departs from a station, customer location, or serving location in your network. It delivers equipment details, the departure station, customer and serving location (when applicable), loaded/empty status, the train number, and the associated work order (if any). This webhook supports the "early departure" scenario where a train leaves directly from a customer location rather than the main yard. In that case, `customer_location` and `serving_location` are populated so your integration can distinguish between a normal yard departure and a customer-site departure. This webhook is triggered through ARMS workflow automation. Configure it in your workflow rules to notify external systems when trains depart from specific locations. *** ## Payload Schema ```json theme={null} { "event_type": "TrainDeparture", "event_timestamp": "2026-06-17T09:30:00+00:00", "work_order_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "linked_resources": { "equipment": [ { "resource_id": 100001, "car_number": "GCGO 995823", "is_loaded": true }, { "resource_id": 100002, "car_number": "GCGO 726451", "is_loaded": false } ], "event_station": { "resource_id": 1001, "name": "Göteborg Hamn", "grouping_type": "station" }, "customer_location": { "resource_type": "CustomerLocation", "resource_id": 7777, "name": "Volvo Torslanda", "customer_identification_numbers": ["VOL-001"], "general_ledger_number": "GL-12345" }, "serving_location": { "resource_id": 5050, "name": "Torslanda Plant", "grouping_type": "customer_location" } }, "attributes": { "is_loaded": null, "train_number": "T-8800" }, "actor": { "resource_type": "User", "resource_id": 12345, "display_name": "ops@customer.com" } } ``` *** ## Field Reference ### Top-level Fields | Field | Type | Required | Description | | ------------------ | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `event_type` | string | Yes | Always `"TrainDeparture"` for this event. | | `event_timestamp` | string (ISO 8601) | No | When the train departed. `null` if unavailable. | | `work_order_id` | string | No | ID of the associated work order. `null` if the event has no work order. | | `linked_resources` | object | Yes | Equipment, station, and locations involved in the event. | | `attributes` | object | Yes | Event-specific attributes. | | `actor` | object or null | Yes | Who caused the triggering event. `null` for system-initiated events. See [Shared Payload Fields -> actor](/user-docs/arms/webhooks/overview#actor). | ### linked\_resources.equipment An array of equipment items on the departing train. Each item includes per-car loaded/empty status. Always an array, even for a single car. | Field | Type | Description | | ------------- | --------------- | ------------------------------------------------------------------- | | `resource_id` | integer | Internal equipment identifier. | | `car_number` | string or null | Railroad car number (e.g. `"GCGO 995823"`). | | `is_loaded` | boolean or null | `true` if this car was loaded, `false` if empty. `null` if unknown. | ### linked\_resources.event\_station The station where the train departed from. `null` if no station could be resolved. | Field | Type | Description | | --------------- | ------- | ----------------------------------------------- | | `resource_id` | integer | Internal station identifier. | | `name` | string | Human-readable station name. | | `grouping_type` | string | Type of location (e.g. `"station"`, `"track"`). | ### linked\_resources.customer\_location The customer location associated with the departure, if any. The entire object is `null` for departures not associated with a customer location (normal yard departures). | Field | Type | Description | | --------------------------------- | ---------------- | ------------------------------------------------------------------------------ | | `resource_type` | string | Always `"CustomerLocation"` when present. | | `resource_id` | integer | Internal customer location identifier. | | `name` | string | Human-readable customer location name. | | `customer_identification_numbers` | array of strings | Carrier-side identifiers for this customer (may be an empty array). | | `general_ledger_number` | string or null | General ledger number associated with this customer. `null` if not configured. | ### linked\_resources.serving\_location The serving location associated with the departure, if any. The entire object is `null` when the departure is not tied to a serving location. | Field | Type | Description | | --------------- | ------- | ---------------------------------------------- | | `resource_id` | integer | Internal serving location identifier. | | `name` | string | Human-readable serving location name. | | `grouping_type` | string | Type of location (e.g. `"customer_location"`). | ### attributes | Field | Type | Description | | -------------- | --------------- | ------------------------------------------------------------------------------------- | | `is_loaded` | boolean or null | `true` if cars were loaded, `false` if empty. `null` when status is mixed or unknown. | | `train_number` | string or null | Train identifier (e.g. `"T-8800"`). `null` if no train ID is set. | *** ## Example HTTP Request This is the full HTTP request your endpoint receives: ```http theme={null} POST /your-webhook-endpoint HTTP/1.1 Content-Type: application/json X-Webhook-Timestamp: 1718614200 X-Webhook-Signature: X-Webhook-KeyId: cedar-webhooks-2026 X-Webhook-Id: 550e8400-e29b-41d4-a716-446655440000 {"actor":{"display_name":"ops@customer.com","resource_id":12345,"resource_type":"User"},"attributes":{"is_loaded":null,"train_number":"T-8800"},"event_timestamp":"2026-06-17T09:30:00+00:00","event_type":"TrainDeparture","linked_resources":{"customer_location":{"customer_identification_numbers":["VOL-001"],"general_ledger_number":"GL-12345","name":"Volvo Torslanda","resource_id":7777,"resource_type":"CustomerLocation"},"equipment":[{"car_number":"GCGO 995823","is_loaded":true,"resource_id":100001},{"car_number":"GCGO 726451","is_loaded":false,"resource_id":100002}],"event_station":{"grouping_type":"station","name":"G\u00f6teborg Hamn","resource_id":1001},"serving_location":{"grouping_type":"customer_location","name":"Torslanda Plant","resource_id":5050}},"work_order_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"} ``` The JSON body is **canonically serialized** (sorted keys, no extra whitespace) so the signature can be verified deterministically. See the [Webhook Overview](/user-docs/arms/webhooks/overview#signature-verification) for verification instructions. *** ## Differences from Train Arrival | Aspect | Train Arrival | Train Departure | | ------------------------ | ------------------------------------- | ------------------------------------------------- | | `event_type` | `"TrainArrival"` | `"TrainDeparture"` | | `customer_location` | Not included in payload | Included (with `name`, identifiers, GL number) | | `serving_location` | Not included in payload | Included (with `name`, `grouping_type`) | | `linked_resources.track` | Included (arrival track) | Not included | | `is_final_location` | Included in attributes (arrival-only) | Not included | | Per-car `is_loaded` | Not included per equipment item | Included per equipment item | | Trigger | Train arrives at a station | Train departs from a station or customer location | The Train Arrival webhook does not currently include `customer_location` or `serving_location`, even though the underlying event carries them. This asymmetry is intentional -- if your integration needs location context on both arrival and departure, use the Train Departure webhook for location-aware routing. *** ## Setting Up This Webhook In ARMS, create or edit a workflow rule that triggers on train departure events. Add the **Train Departure Webhook** effect to the workflow. Provide your endpoint URL. Build an HTTPS endpoint that receives the POST, verifies the signature, and processes the event. Trigger a test event and confirm your endpoint receives and verifies the payload correctly. *** ## Related Signing, verification, public key, and shared HTTP headers. Webhook for train arrival events at stations. # Train Set Webhook Source: https://docs.cedarai.com/user-docs/arms/webhooks/train-set Event payload sent when a train consist is defined with wagons and route stations ## Event Overview The **Train Set** webhook fires when a train consist is defined in ARMS -- typically when wagons are assigned to a train with departure and arrival stations. It delivers the wagon list, station details (including names), train identifier, and the associated work order (if any). This webhook is triggered through ARMS workflow automation. Configure it in your workflow rules to notify external systems when a train consist is set up. *** ## Payload Schema ```json theme={null} { "event_type": "train_set", "event_timestamp": "2026-03-09T14:30:00+00:00", "work_order_id": "12345", "linked_resources": { "equipment": [ { "resource_id": 2001, "car_number": "GCGO 11111" }, { "resource_id": 2002, "car_number": "GCGO 22222" }, { "resource_id": 2003, "car_number": "GCGO 33333" } ], "departure_station": { "resource_id": 6001, "name": "Hallsberg", "grouping_type": "station" }, "arrival_station": { "resource_id": 6002, "name": "Gothenburg", "grouping_type": "station" } }, "attributes": { "train_id": "T-9876" }, "actor": { "resource_type": "User", "resource_id": 12345, "display_name": "ops@customer.com" } } ``` *** ## Field Reference ### Top-level Fields | Field | Type | Required | Description | | ------------------ | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `event_type` | string | Yes | Always `"train_set"` for this event. | | `event_timestamp` | string (ISO 8601) | No | When the event occurred. `null` if unavailable. | | `work_order_id` | string | No | ID of the associated work order. `null` if the event has no work order. | | `linked_resources` | object | Yes | Equipment, departure station, and arrival station for the train. | | `attributes` | object | Yes | Event-specific attributes (train identifier). | | `actor` | object or null | Yes | Who caused the triggering event. `null` for system-initiated events. See [Shared Payload Fields -> actor](/user-docs/arms/webhooks/overview#actor). | ### linked\_resources.equipment An array of wagons assigned to the train. Always an array, even for a single wagon. | Field | Type | Description | | ------------- | -------------- | ------------------------------------------------ | | `resource_id` | integer | Internal equipment identifier. | | `car_number` | string or null | Railroad car/wagon number (e.g. `"GCGO 11111"`). | ### linked\_resources.departure\_station The station where the train departs from. `null` if no departure station is associated. | Field | Type | Description | | --------------- | ------- | ----------------------------------------------- | | `resource_id` | integer | Internal station identifier. | | `name` | string | Human-readable station name. | | `grouping_type` | string | Type of location (e.g. `"station"`, `"track"`). | ### linked\_resources.arrival\_station The station where the train arrives. `null` if no arrival station is associated. | Field | Type | Description | | --------------- | ------- | ----------------------------------------------- | | `resource_id` | integer | Internal station identifier. | | `name` | string | Human-readable station name. | | `grouping_type` | string | Type of location (e.g. `"station"`, `"track"`). | ### attributes | Field | Type | Description | | ---------- | ------ | --------------------------------------------- | | `train_id` | string | Train identifier (e.g. train number or code). | *** ## Example HTTP Request This is the full HTTP request your endpoint receives: ```http theme={null} POST /your-webhook-endpoint HTTP/1.1 Content-Type: application/json X-Webhook-Timestamp: 1709651400 X-Webhook-Signature: X-Webhook-KeyId: cedar-webhooks-2026 X-Webhook-Id: 550e8400-e29b-41d4-a716-446655440000 {"actor":{"display_name":"ops@customer.com","resource_id":12345,"resource_type":"User"},"attributes":{"train_id":"T-9876"},"event_timestamp":"2026-03-09T14:30:00+00:00","event_type":"train_set","linked_resources":{"arrival_station":{"grouping_type":"station","name":"Gothenburg","resource_id":6002},"departure_station":{"grouping_type":"station","name":"Hallsberg","resource_id":6001},"equipment":[{"car_number":"GCGO 11111","resource_id":2001},{"car_number":"GCGO 22222","resource_id":2002},{"car_number":"GCGO 33333","resource_id":2003}]},"work_order_id":"12345"} ``` The JSON body is **canonically serialized** (sorted keys, no extra whitespace) so the signature can be verified deterministically. See the [Webhook Overview](/user-docs/arms/webhooks/overview#signature-verification) for verification instructions. *** ## Setting Up This Webhook In ARMS, create or edit a workflow rule that triggers on train set events. Add the **Train Set Webhook** effect to the workflow. Provide your endpoint URL. Wire the departure station, arrival station, equipment (wagons), and train ID from the trigger event to the effect inputs. Build an HTTPS endpoint that receives the POST, verifies the signature, and processes the event. Trigger a test event and confirm your endpoint receives and verifies the payload correctly. *** ## Related Signing, verification, public key, and shared HTTP headers. Fires when a car is placed at a station or track. Fires when a train departs from a station or customer location. # IAM Concepts Source: https://docs.cedarai.com/user-docs/iam/concepts Users, groups, resources, permissions, roles, and conditions. This page explains the **conceptual foundation** of IAM. To manage these concepts in practice, use the [Admin Portal](/user-docs/admin/overview). ## Identities Email-based ARMS accounts. Access is granted through roles on resources across ARMS products (e.g., inventory, transload, intermodal, mobile). | | Username | Identifier | | ------- | -------- | ---------------------------------------------------------------- | | | Mike | user:[mike@cedx.rail](mailto:mike@cedx.rail) | | | Kacey | user:[kecey@cedx.rail](mailto:kecey@cedx.rail) | | | Heather | user:[heather@monstersugar.net](mailto:heather@monstersugar.net) | | | Bob | user:[bob@monstersugar.net](mailto:bob@monstersugar.net) | Organize users and assign access at scale across multiple ARMS modules. | | Group | Identifier | Description | | ------- | ------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------ | | | CEDX Admin | group:cedxadmin | Has access to everything in the ARMS system that belongs to CEDX | | | CEDX User | group:cedxuser | Conditionally allowed to access some parts of the system | | | CEDX Customer Admin | group:cedxcustomeradmin | Can access customer tracks and certain groups, load and unload cars on customer tracks, and print paperworks | | | CEDX Customer User | group:cedxcustomeruser | Can only print paperworks | These are example resources used in this guide. Replace with your own organization’s resources (e.g., sites, terminals, customers, or operators). CEDX Railroad Sugar Factory ## Resources Equipment, groups, waybills, sites, terminals, operators, workflows, and more. Permissions can be granted at an organization/site/operator level, at a sub‑area (e.g., terminal or group/track), or at an individual resource level. ### Resource hierarchy and inheritance Permissions granted at a higher‑level resource are inherited by child resources. * Organization / Operator / Site → applies to all sub‑resources below * Terminal / Group / Track → applies to resources in that sub‑area only * Specific resource → applies only to that one resource ## Permissions and roles * Permissions: `service.resource.verb` (e.g., `inventorymanagement.equipment.list`) * Roles: collections of permissions * Predefined roles (curated) * [Feature sets](/user-docs/iam/feature-sets) — the columns of the Admin Portal IAM matrix; Cedar keeps each one current as features grow, so roles built on them don't drift * Custom roles (tailored — best built by checking feature-set columns rather than picking individual permissions) ## How IAM works Policies attach to resources and bind members to roles, with optional conditions. On access, ARMS evaluates the target resource’s policy to allow or deny—consistently across all ARMS modules. Policy = Bindings of `{ role, members, optional condition }`. Conditions use a simplified CEL expression syntax. IAM diagram ## Conditions (optional) Scope access by attributes. Examples: ```json theme={null} { "description": "Only BNSF cars", "expression": "resource.equipmentInitial == 'BNSF'" } ``` ```json theme={null} { "description": "Tracks A or B", "expression": "resource.track in ['A','B']" } ``` ## Manage these concepts in the Admin Portal Create and manage user accounts Organize users into groups View and create roles with permissions Connect groups to roles and scopes See the [Admin Portal Glossary](/user-docs/admin/glossary) for a quick reference of all terms. # Customer Portal and IAM Source: https://docs.cedarai.com/user-docs/iam/customer-portal How to configure customer-facing access with Cedar.AI IAM policies, roles, and groups. ## Customer Portal with IAM The Customer Portal is powered by IAM configuration. Share specific resources with customer users and control what they can see and do using roles and policies. ### Example policy: Track access and ordering Attach this policy to Track A and Track B to allow customer admins to view, load, empty, rebill, and order equipment. Viewers can only view and print paperwork. ```json theme={null} { "bindings": [ { "role": "roles/inventory.equipmentCustomerAdmin", "members": ["group:cedxcustomeradmin"] }, { "role": "roles/inventory.equipmentViewer", "members": ["group:cedxcustomeruser"] } ] } ``` ```json theme={null} { "bindings": [{ "role": "roles/inventory.equipmentOrderer", "members": ["group:cedxcustomeradmin"] }] } ``` ### Roles and permissions * `roles/inventory.equipmentCustomerAdmin`: list, get, load, empty, rebill, order, grouping list/get * `roles/inventory.equipmentViewer`: list, get, grouping list/get * `roles/inventory.equipmentOrderer`: list, get, order, grouping list/get ## UX patterns * Hide and block access to pages when minimum required permissions are missing * Conditionally render buttons and controls based on permissions * Backend filters data per IAM; UI should gracefully handle hidden details ## Related pages Invite and manage customer users Create groups for customer access Grant customer groups access to resources View available customer roles # Customer Users Source: https://docs.cedarai.com/user-docs/iam/customer-users How to invite, upgrade, and support customers using IAM. ## What is a customer user? A customer user is a standard ARMS user associated with their own organization who is granted access to a subset of your resources (e.g., sites, terminals, tracks, workflows) via IAM policies. ## Create a new customer user Assign to a user group in your road during the invite. They complete signup via the emailed code. Start with limited access to a small set of pages/resources. They can now act on resources allowed by your IAM policy. ## Upgrade a customer user to a normal user Default customer role is removed; default user role is applied. They can act on their own organization’s resources and any shared resources from inviting roads. ## Customer with multiple organizations Add the existing customer to additional user groups from other organizations (e.g., partner sites or operators). They will gain access to those shared resources per policy. ## Manage customer users in the Admin Portal View and manage all users including customers Add customers to groups Grant customer groups access Configure customer-facing access # Feature Sets Source: https://docs.cedarai.com/user-docs/iam/feature-sets Curated columns in the Admin Portal IAM matrix that grant a whole product feature in one click — and stay current as Cedar evolves. A **feature set** is one of the columns you see when you open the IAM matrix on the [Roles](/user-docs/admin/roles) page. Each column represents a single product feature at a specific access level — for example **Notes — View** or **Inventory waybills — Operate**. Checking the box on a row grants every permission that role needs to use that feature. ## Why feature sets exist (the maintainability story) The biggest reason to use feature sets — and the one most teams underestimate — is that **Cedar curates them, so you don't have to**. When a feature gains a new capability — a new filter, a new bulk action, a new export option, an extra typeahead lookup — Cedar updates the feature set behind the scenes. Every role that has that column checked picks up the new capability automatically on the next deploy. Your admins do nothing. Compare that to the alternative — a [custom role](/user-docs/admin/roles#create-a-custom-role) hand-picked from the raw permission list: | Approach | What you maintain | Risk over time | | ------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | | **Custom role from individual permissions** | Every individual permission, forever | High — when Cedar adds a permission to support a feature upgrade, your role silently misses it until someone notices something is broken. | | **Custom role composed from feature set columns** | Just the list of features you want enabled | Low — Cedar keeps each column current. Your role inherits the upgrades automatically. | If you remember nothing else from this page: **prefer feature-set columns over hand-picked permissions whenever the option exists**. It's the single biggest lever you have to keep IAM low-maintenance as the product grows. ## What you see in the Admin Portal The IAM matrix on the Roles page is a grid: * **Rows** are the roles available in your carrier (built-in roles like `arms.carrierAdmin`, plus any custom roles you've created). * **Columns** are feature sets. Headers read like **Notes — View**, **Notes — Operate**, **Notes — Manage**, **Inventory waybills — View**, **Reporting — Manage**, and so on. * **Cells** are checkboxes. A check means "this role can do this feature, at this level." Granting a whole feature is one click. Revoking it is one click. There's nothing else to configure — no individual-permission picker, no manual list of capabilities to keep in sync. ## The three access levels Most features ship three columns. A role can carry any subset of them; what you check depends on what that role's users should be able to do. | Column suffix | Who it's for | What it lets them do | | ------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **— View** | Anyone who should see the feature | Read everything in the feature, run searches, use typeaheads and filters. Can't make changes. | | **— Operate** | Day-to-day users who own their own work | Create, edit, and delete *their own* work in the feature. Implies everything in **View** — you don't need to check both unless you want to be explicit. | | **— Manage** | Admins, moderators, and feature owners | Act on *other people's* work in the feature (edit or delete any author's record), and change feature-level settings. Layer this on only when that role should have moderation or configuration authority. | Not every feature uses every level. A read-only data surface like AEI may only ship a **View** column. A configuration-only feature like automation rules may ship only **Manage**. The matrix shows you exactly what's available for each feature in your carrier. ## A worked example: Notes Notes ships three columns: * **Notes — View**  ·  Read note threads, run the in-drawer search, and use the `@` typeahead anywhere references render. * **Notes — Operate**  ·  Write your own notes; edit and delete what you wrote. * **Notes — Manage**  ·  Moderate the whole carrier — edit or delete any user's note regardless of who wrote it. Cedar pre-checks these for every built-in role with sensible defaults: `arms.carrierAdmin` gets all three; `arms.carrierOperator` gets View and Operate; `arms.customerOperator` gets just View. See [Notes permissions](/user-docs/arms/ops/notes#permissions) for the complete per-role default table. When Notes ships a new capability later — say, a "pin a note to the top of the thread" action — Cedar adds the underlying permission to **Notes — Operate**. Every role with that column already checked picks up "pin" the next time the admin service redeploys. You don't change anything in the matrix. ## Defaults Cedar ships You usually don't need to touch the matrix at all. Cedar pre-checks the right columns on every built-in role so a fresh carrier has the intended feature coverage out of the box. You only need to open the matrix when you want to: * **Customize coverage** — for example, grant **Notes — Manage** to a non-admin moderator role, or remove **Notes — View** from a role you'd rather not have reading notes. * **Compose a custom role** — pick the feature sets you want this role to inherit instead of hand-picking individual permissions. * **Audit** — see at a glance who has access to what feature. ## Building a custom role with feature sets When you create a [custom role](/user-docs/admin/roles#create-a-custom-role), don't open the raw permission picker unless you need a permission no feature set covers. Instead: From the Roles page, click **New role** and give it a clear name and description. Find your role's row in the matrix and check every feature column the role should be able to use. Use the column search to jump to a specific feature. Save the role, then create a [binding](/user-docs/admin/bindings) to grant it to a user group at the right scope. Future you will thank present you when Cedar adds new capabilities to those features and your custom role keeps working without any matrix updates. Removing a feature column from a built-in role takes effect carrier-wide on save. If you're trimming defaults, make sure the affected user groups still have the access they need (or get a heads-up first). ## A few practical notes * **Column names follow `Feature — Level`** so they sort and group naturally in the matrix. All `Notes —` columns sit together, all `Inventory waybills —` columns sit together, and so on. * **Some role names in your Roles list start with `fs.`** (for example `fs.linda.notes.view`). Those are the feature sets themselves, surfaced as roles for transparency. You don't normally interact with them directly — you interact with the matrix columns instead. * **Bindings still attach to roles, not to feature sets directly.** The matrix is just a faster, lower-maintenance way to decide what each role can do. ## Related The page where the IAM matrix lives — manage built-in and custom roles Connect roles to user groups at the right scope How roles fit into the broader IAM model A complete worked example, including per-role defaults # IAM Overview Source: https://docs.cedarai.com/user-docs/iam/overview Understand Cedar.AI Identity & Access Management (IAM): users, groups, roles, permissions, and policies. ## What is IAM? Identity & Access Management (IAM) in Cedar.AI helps you define who (identity) has what access (role) to which resources (scope). It implements least-privilege access with flexible, policy-based controls similar to Google Cloud, Azure, and AWS. Members (users or groups) are linked to roles (collections of permissions) on resources. **Ready to get started?** Use the [Admin Portal](/user-docs/admin/overview) to manage users, groups, roles, and bindings through a friendly interface. ## Identities Users and groups define who can be granted access. See Concepts for full identity tables and example resources. ## How IAM works High level: members get roles on resources. On access, ARMS checks whether the role includes the required permission and grants or denies. See Concepts for the full flow and diagram. ### IAM flow (example) ```mermaid theme={null} flowchart TD subgraph Identities U[User] G[Group] end subgraph Authorization R[Role] PERM[Permissions] end RES[(Resource)] REQ[[Access request]] U -->|member of| G G -->|assigned| R R -->|applies to| RES R -->|includes| PERM REQ --> RES REQ -. check role & permissions .-> R R -->|grant / deny| REQ ``` ### Resource examples and hierarchy Resources can be top‑level (organization, site, operator) or sub‑resources (stations, terminals, warehouses, tracks, workflows, equipment). Roles can be assigned at any level to scope access broadly or precisely. * Top‑level: organization, site, operator (railroad, transload, intermodal) * Sub‑resources: station, yard/track group, warehouse, terminal, workflow, equipment/asset ```mermaid theme={null} graph TD ORG[Organization / Site] OP["Operator (Railroad / Transload / Intermodal)"] ST(Station) YD(Yard / Track Group) WH(Warehouse) TM(Terminal) WF(Workflow) EQ((Equipment / Asset)) ORG --> OP OP --> ST OP --> TM OP --> WH ST --> YD YD --> EQ TM --> EQ OP --> WF U(User Group) R1[[Role: Inventory Viewer]] R2[[Role: Terminal Editor]] R3[[Role: Warehouse Viewer]] U --> R1 U --> R2 U --> R3 R1 -. assign to .-> OP R2 -. assign to .-> TM R3 -. assign to .-> WH classDef identity fill:#E0F2FE,stroke:#0284C7,stroke-width:1px,color:#0C4A6E; classDef role fill:#F5F3FF,stroke:#7C3AED,stroke-width:1px,color:#4C1D95; classDef resource fill:#ECFDF5,stroke:#059669,stroke-width:1px,color:#065F46; class U identity; class R1,R2,R3 role; class ORG,OP,ST,YD,WH,TM,WF,EQ resource; ``` ## Resources, permissions, roles Overview: resources are protected by permissions grouped into roles. See Concepts for definitions and examples. ## Resource hierarchy and inheritance Summary: access granted at a top level (for example, organization, site, or operator) flows down to sub-resources (for example, terminals, groups/tracks, workflows, or individual assets). Grant at a lower level for precision. See Concepts for details. ## Roles: predefined and custom Use predefined roles for common tasks, or define custom roles. See Policies & Roles for guidance. ## Permissions and conditions Permissions typically map to API operations; conditions narrow access. See Concepts for examples. ## Frontend integration High-level UX patterns: page gating, component gating, and data filtering. See Frontend Integration for guidance. ## Learn more ### Conceptual guides The problem it solves and why it matters Identities, resources, permissions, roles, conditions Define who can do what on which resource Grant a whole product feature in one matrix click; Cedar keeps it current Configure customer-facing access with IAM ### Admin Portal (practical guides) Get started with the Admin Portal interface Manage individual user accounts Organize users into teams View and create permission sets Grant access by connecting groups to roles Quick reference for all IAM terms # Policies & Roles Source: https://docs.cedarai.com/user-docs/iam/policies-and-roles Define who can do what on which resource with policies and roles. This page explains the **conceptual model** of policies and roles. To create and manage roles in practice, use the [Admin Portal Roles page](/user-docs/admin/roles). ## What is a policy? Policies attach to resources and bind members to roles, with optional conditions. ```json theme={null} { "bindings": [ { "role": "roles/inventory.equipmentAdmin", "members": ["group:cedxadmins"] }, { "role": "roles/inventory.equipmentViewer", "members": ["user:nancy@cedx.rail", "user:steven@cedx.rail"], "condition": { "description": "Only can view BNSF cars", "expression": "resource.equipmentInitial == 'BNSF'" } } ] } ``` IAM policy ## Roles * Predefined roles (examples): * `roles/inventory.equipmentViewer` * `roles/inventory.equipmentAdmin` * `roles/inventory.equipmentOrderer` * [Feature sets](/user-docs/iam/feature-sets): the columns of the Admin Portal IAM matrix. Each one grants a whole product feature in a single click, and Cedar keeps them current as features evolve, so your roles don't drift. * Custom roles: build a role tailored to your org. Prefer composing it from feature-set columns — that way Cedar's ongoing curation flows through automatically. ## Inheritance Grant at an organization/site/operator level → inherited by terminals, groups/tracks, and resources beneath. Grant at a terminal/group/track or a specific resource for fine‑grained control. A role can also inherit from another role: it picks up every ability of its parents. Cedar uses this so [feature sets](/user-docs/iam/feature-sets) flow into predefined roles, which means new capabilities Cedar adds to a feature show up in your roles automatically. ## Manage in the Admin Portal View built-in roles and create custom roles The columns of the IAM matrix — Cedar curates them so your roles stay current Connect groups to roles (this is how policies are created) Organize users to assign roles at scale # Why IAM: Problem & Purpose Source: https://docs.cedarai.com/user-docs/iam/problem-and-purpose Why Cedar.AI added IAM: flexibility for large organizations and customer access. ## Overview Larger operations and their customers—across rail, transload, intermodal, mobile, and more—need flexible permission structures for internal teams and external customers. A single operator‑centric model is too rigid at scale. ## Problem statement In an operator‑centric model, users typically see everything within one operator. For multi‑site or multi‑operator operations—or complex organizations—users need scoped access (by terminals, tracks/groups, workflows) and in some cases cross‑organization visibility. Example: because two operator codes exist, inventory appears separately and cannot be scoped cleanly without IAM. ## Purpose IAM provides a user‑defined, flexible way to manage access using identities (users, groups), roles (permissions), and policies (bindings with optional conditions). It also enables a customer‑facing Portal through configuration rather than a separate system. ## Get started Understand the building blocks Manage IAM through the UI # Concept UI Source: https://docs.cedarai.com/user-docs/iam/ui-design Role and binding designers for IAM. Role designer Binding designer # Introduction Source: https://docs.cedarai.com/user-docs/index Official Cedar.AI docs for AI‑powered transportation management systems: ARMS APIs, SSO, and product guides across ARMS, Transload, Intermodal, Mobile, and Optiswitch. Welcome to the Cedar.AI documentation. Find guides for integrating with our platform, managing users, and configuring your account. ## Documentation Endpoints, schemas, and request examples Manage users, roles, and access control Okta, Microsoft Azure AD, and SCIM setup Users, groups, roles, and permissions QuickBooks, Sage, NetSuite, JD Edwards Coming soon Coming soon ## About Cedar.AI Cedar builds AI‑powered transportation management systems for railroads, industrial parks, warehouses, intermodal and transload operators, and shippers. We combine deep rail expertise with modern software, with teams in Seattle, Atlanta, and Stockholm. ## Solutions Full-featured inventory and revenue platform for railroads. Track palletized and bulk rail freight with automated billing and scanning. An easy-to-use Terminal Operating System for intermodal and container yards. Mobile solution for the boots on the ground. Offline-ready. Real-time operations and planning tool for flat-yard classification. ## Talk to us See how Cedar can help your operation. 1-800-711-0790 # Gradual rollout Source: https://docs.cedarai.com/user-docs/sso/gradual-rollout Enable SSO safely with an option to fall back to Cedar identity during rollout. Switching to Single Sign-On (SSO) doesn’t have to be all‑or‑nothing. Gradual rollout lets you turn on SSO for your organization while keeping a safe fallback to Cedar identity for select users. ## What is gradual rollout? * By default, when SSO is enabled for your organization (domain/tenant), users sign in with SSO. * With gradual rollout, you can allow specific users to continue using Cedar identity temporarily while you complete your SSO rollout. This is ideal for large teams, staged rollouts, or when you want a safety net while testing SSO with a subset of users. ## How it works (at a glance) Users are directed to sign in with your configured identity provider (e.g., Okta, Microsoft, Google). SSO is on, and selected users can still sign in with Cedar identity during the transition. ## What your users see * When gradual rollout is enabled, affected users will see a friendly option to use Cedar identity if SSO isn’t working for them yet. * Everyone else signs in with SSO as usual. ## When to use it * You’re piloting SSO with a smaller group first * You have mixed user bases (contractors, external partners) and need time to migrate * You want a straightforward fallback plan during cutover ## Rolling back a single user If a user can’t sign in with SSO during rollout, an administrator can quickly switch them back to Cedar identity while you investigate. This change is reversible, and the rest of your users remain on SSO. Contact your Cedar support representative if you’d like help enabling gradual rollout or planning a phased migration. ## FAQs Yes. Gradual rollout is supported for Google, Okta, and Microsoft (Azure AD). No. Your organization remains protected. Gradual rollout only allows a subset of users to sign in with Cedar identity while SSO is being phased in. Your Cedar representative can turn it on for your tenant/domain and guide you through a staged rollout. # Microsoft Source: https://docs.cedarai.com/user-docs/sso/microsoft Configure Microsoft (Azure AD) SSO for Cedar.AI with IdP- and SP-initiated flows. ## Overview After registering your organization, all users will transition to the new login method. Notify users in advance to ensure a smooth changeover. Sign in to ARMS, go to Settings, then select Sign-in options. Enter your Cedar tenant code (e.g., [https://accounts.cedarai.com/login?tenant=ABCD](https://accounts.cedarai.com/login?tenant=ABCD)). Select Microsoft as the provider, click Log in with Microsoft, and authenticate with an org-linked user. Microsoft configuration ### Gradual rollout If you'd like to phase in SSO while keeping a fallback to Cedar identity for select users, enable gradual rollout. See [Gradual rollout](/user-docs/sso/gradual-rollout) for details. ### Tips & potential issues * Users who need access must belong to the same Azure AD tenant as the initial authenticating user. * Users must still be assigned to a Cedar user group with sufficient permissions. Need help? Email [support@cedarai.com](mailto:support@cedarai.com). # ARMS Mobile Source: https://docs.cedarai.com/user-docs/sso/mobile How to log in to ARMS Mobile using Microsoft, Google, and Okta SSO. **Purpose:** A comprehensive guide for accessing ARMS Mobile using SSO with Microsoft, Google, and Okta. Enter your email address. Enter email address The system determines whether to use standard ARMS login or SSO and automatically launches the SSO webview. Enter your email and password in the provided fields. * Microsoft: Follow the prompts (may include MFA depending on your settings). * Google: Follow the prompts (may include MFA). * Okta: Follow the prompts (may include MFA). After logging out, your email and selected SSO provider are remembered for faster next logins. Remembered email and provider For subsequent sessions, repeat credentials and SSO steps. Your session remains active until you choose to log out. To switch emails, clear the field and enter a new one. This guide may be updated as the ARMS Mobile authentication system evolves. # Okta Source: https://docs.cedarai.com/user-docs/sso/okta Configure Okta SSO for Cedar.AI with IdP- and SP-initiated flows. ## Overview Before starting, register your Okta organization URL with Cedar.AI. Once registered, your users will transition to the new login method—notify users ahead of time. Sign in to ARMS, go to Settings, then select Sign-in options. Enter your Cedar tenant code. With code ABCD, you can use [https://accounts.cedarai.com/login?tenant=ABCD](https://accounts.cedarai.com/login?tenant=ABCD). Select Okta as the provider, then enter your organization URL, app client ID, and app client secret. Click Save. Okta configuration ### Features we support * IdP-initiated SSO * SP-initiated SSO ### Gradual rollout If you'd like to phase in SSO while keeping a fallback to Cedar identity for select users, enable gradual rollout. See [Gradual rollout](/user-docs/sso/gradual-rollout) for details. ### Tips and troubleshooting * Ensure the org URL format is correct, e.g., companyname.okta.com. * Add the Cedar.AI integration to your Okta org and assign users who need access. * Users must still be assigned to a Cedar user group with sufficient permissions. Need help? Email [support@cedarai.com](mailto:support@cedarai.com). # Overview Source: https://docs.cedarai.com/user-docs/sso/overview Overview of Cedar.AI SSO with Google, Okta, and Microsoft Azure AD, including IdP- and SP-initiated flows. [Cedar.AI](https://cedar.ai/)'s Single Sign-On (SSO) system streamlines authentication with major identity providers: Google, Okta, and Microsoft Azure AD. Select your identity provider to get started. Both IdP-initiated and SP-initiated SSO are supported. Configure Okta SSO for Cedar.AI Configure Microsoft (Azure AD) SSO ARMS Mobile login procedure ### Supported SSO methods * **Google**: Works out of the box for Google users. * **Microsoft (Azure AD)**: First org user logs in once to capture the tenant ID. See the [Microsoft guide](/user-docs/sso/microsoft). * **Okta**: Provide your org Okta URL (e.g., `companyname.okta.com`). See the [Okta guide](/user-docs/sso/okta). ### Initiation flows Start sign-in from your Identity Provider (Okta, Microsoft, or Google). Start sign-in from Cedar.AI. Supports tenant shortcuts for deep links. ### Gradual rollout (optional) Turn on SSO with a safety net. In gradual rollout, SSO becomes the default, and selected users can temporarily sign in with Cedar identity during the transition. See the dedicated page for details and best practices. Learn how to phase in SSO safely while keeping a fallback for specific users. ### Need help? We're here to help with SSO setup and troubleshooting. # Azure SCIM Source: https://docs.cedarai.com/user-docs/sso/scim/azure Sync users and groups from Microsoft Entra ID (Azure AD) using SCIM. # Sync users and groups from Microsoft Entra ID using SCIM Cedar.AI supports System for Cross-domain Identity Management (SCIM) to automatically provision and de-provision users and groups from Microsoft Entra ID (formerly Azure Active Directory). This allows you to manage user access centrally within your identity provider. SCIM requires enrollment in Admin v2. You'll create a SCIM connection in the Cedar.AI Admin Portal, then use the generated client credentials in Azure provisioning. ## Prerequisites You must be able to log in to the [Cedar.AI Admin Portal](https://admin.cedarai.com) and [create a SCIM mapping](/user-docs/admin/scim) to get client credentials. You need permissions to create Enterprise Applications in your Microsoft Entra ID tenant. Before starting, create a SCIM mapping in the [Admin Portal](/user-docs/admin/scim) to get your **Client ID** and **Client Secret**. ## Configuration Steps 1. Obtain your Microsoft Entra ID (Azure AD) Tenant ID. 2. In the Cedar.AI Admin Portal, go to AdvancedSCIM. 3. Click New mapping. 4. Enter the Entra Tenant ID and associate it with an Organization or a Carrier. 5. Click Create. 6. From the newly created SCIM connection, copy the Client ID and Client Secret (you'll use these in Azure provisioning). 1. Log in to the [Microsoft Entra Admin Center](https://entra.microsoft.com/). 2. Navigate to Identity > Applications > Enterprise applications. 3. Click New application. 4. Click Create your own application. 5. Enter a name for your application (e.g., "Cedar.AI SCIM"). 6. Select Integrate any other application you don't find in the gallery (Non-gallery). 7. Click Create. 1. In your newly created application, go to the Provisioning blade in the left menu. 2. Click Get started. 3. Set the Provisioning Mode to Automatic. Cedar.AI uses the OAuth 2.0 Client Credentials grant flow for SCIM authentication. Expand the Admin Credentials section and enter the values below. | Field | Value | | -------------- | ----------------------------------------------------------------------------------------------------------------------------- | | Tenant URL | `https://api-k.arms-staging.cedarai.com/scim//` | | Token Endpoint | [https://auth.accounts-staging.cedarai.com/oauth2/token](https://auth.accounts-staging.cedarai.com/oauth2/token) | | Field | Value | | -------------- | ------------------------------------------------------------------------------------------------------------- | | Tenant URL | `https://api-k.arms.cedarai.com/scim//` | | Token Endpoint | [https://auth.accounts.cedarai.com/oauth2/token](https://auth.accounts.cedarai.com/oauth2/token) | Replace `` with your specific Azure Tenant ID. Use the same environment for your Tenant URL and Token Endpoint, and use the Client ID/Secret you generated in the Admin Portal SCIM connection. Authentication Method: Ensure Azure provisioning is set to use OAuth 2.0 Client Credentials Grant (if available in your connector options) or follow the workflow prompted by Azure. You will need: * Client Identifier: (from the Admin Portal SCIM connection) * Client Secret: (from the Admin Portal SCIM connection) If the standard Azure "Non-gallery" SCIM connector only requests a "Secret Token", you may need to generate a long-lived bearer token using the client credentials or contact Cedar.AI support for the appropriate configuration pattern for your tenant. 1. Click Test Connection to ensure Azure can communicate with the Cedar.AI SCIM endpoint. 2. Once the test passes, click Save. Azure AD only provisions users and groups that are explicitly assigned to the application. 1. Go to the Users and groups blade for your application. 2. Click Add user/group. 3. Select the users and groups you want to sync to Cedar.AI. * Groups: Assigning a group provisions the group itself and its direct members. Nested groups are not supported by the standard SCIM connector (flattening may be required). * Users: Users must be assigned directly or through a group to be provisioned. 4. Click Assign. 1. Under Mappings, review the user and group attribute mappings to ensure they align with your requirements. 2. Go back to the Provisioning overview. 3. Set the Provisioning Status to On. 4. Click Save. Azure AD will start an initial synchronization cycle, followed by periodic incremental cycles (typically every 40 minutes). You can monitor progress in the Provisioning logs. ## Important Considerations By default, Azure AD provisions only assigned users and groups. Ensure "Sync only assigned users and groups" is selected in the Provisioning settings unless you intend to sync your entire directory. When a user is unassigned from the application or disabled in Azure AD, a SCIM disable (soft delete) request is sent to Cedar.AI. The user will lose access immediately. Renaming a group in Azure AD will update the group name in Cedar.AI. Removing a user from a group in Azure AD will remove them from the corresponding group in Cedar.AI. ## Related Pages Create and manage SCIM mappings Technical protocol details View provisioned users Manage provisioned groups # SCIM Overview Source: https://docs.cedarai.com/user-docs/sso/scim/overview Manage user provisioning and de-provisioning with SCIM. # System for Cross-domain Identity Management (SCIM) This page covers the **technical SCIM protocol details**. To create SCIM mappings in the Cedar Admin Portal, see [SCIM in the Admin Portal](/user-docs/admin/scim). ```mermaid theme={null} flowchart LR A[Identity Provider] -->|Push Users/Groups| B(Cedar.AI SCIM API) B -->|Provision| C[(Cedar.AI Users)] B -->|Sync Members| D[(Cedar.AI User Groups)] style A fill:#f9f,stroke:#333,stroke-width:2px,color:#000 style B fill:#bbf,stroke:#333,stroke-width:2px,color:#000 style C fill:#bfb,stroke:#333,stroke-width:2px,color:#000 style D fill:#fbf,stroke:#333,stroke-width:2px,color:#000 ``` SCIM (System for Cross-domain Identity Management) is an open standard that allows for the automation of user provisioning. By configuring SCIM, your identity provider (IdP) can automatically create, update, and deactivate users and groups in Cedar.AI, ensuring your user directory stays in sync with your organization's central identity source. **SCIM requires enrollment in Admin v2.** ## Supported Features Cedar.AI supports the following SCIM 2.0 operations: * **ServiceProviderConfig**: Retrieve compliance and supported feature sets. * **ResourceTypes**: Discover supported resource schemas (Users, Groups). * **Users**: * **Create**: Provision new users. * **Read**: Retrieve user details or list users with filtering (e.g., by `userName`, `email`). * **Update**: Modify user attributes (e.g., `displayName`). Supports `replace` and `add` patch operations. * **Delete**: Deactivate users (soft delete). * **Groups**: * **Create**: Create new groups. * **Read**: Retrieve group details or list groups with filtering (e.g., by `displayName`). * **Update**: Rename groups or update memberships (add/remove members). * **Delete**: Remove groups. ## Getting Started Go to the [Admin Portal SCIM page](/user-docs/admin/scim) and create a mapping. You'll get the **Client ID** and **Client Secret** needed for your identity provider. Use the guides below to set up SCIM in your identity provider using the credentials from the Admin Portal. After setup, monitor the [Users page](/user-docs/admin/users) in the Admin Portal to verify provisioning is working. ## Configuration Guides Select your identity provider to view specific configuration instructions: Configure SCIM with Azure AD Create and manage SCIM mappings # Train ID template Source: https://docs.cedarai.com/user-docs/train_job/id How Train ID templating works and which variables are supported. ### What this is Use a simple template to automatically build your Train IDs. Type your pattern and put any “fill-in” parts inside double braces like `{{ THIS }}`. When the job runs, we replace those parts with real values from the job and date/time. ### How to write a template * Write placeholders like `{{ JOB_NAME }}` or `{{ YYYY }}`. * If we can’t find a value for a placeholder, we leave it as-is (you’ll see `{{ UNKNOWN }}` in the result). ### Common variables Date and time (based on the job’s scheduled date/time): | Placeholder | Meaning | Example | | ----------- | ------------------------------ | ----------- | | `HH` | Hour (24‑hour, zero‑padded) | `05` | | `D` | Day of month (no leading zero) | `7` | | `DD` | Day of month (zero‑padded) | `07` | | `M` | Month number (no leading zero) | `9` | | `MM` | Month number (zero‑padded) | `09` | | `MMM` | Abbreviated month name | `Sep` | | `MMMM` | Full month name | `September` | | `YY` | Two‑digit year | `25` | | `YYYY` | Four‑digit year | `2025` | From the job: | Placeholder | Meaning | When it appears | Example | | ---------------- | ------------------------ | -------------------------------- | ---------- | | `JOB_NAME` | The job’s name | Always | `DayShift` | | `BLUEPRINT_NAME` | The job’s blueprint name | Only if the job uses a blueprint | `MainYard` | ### Custom train attributes You can reference your own train attributes (and other job fields) by name. Just put the name in braces, for example `{{ DepartureTime }}` or `{{ departure_time }}`. * If the attribute is a dropdown/choice, we insert the selected option’s text. * For everything else, we insert the attribute’s value as text. ### Copy‑paste examples * Make a daily ID with the job name and hour: * Template: `Train-{{ JOB_NAME }}-{{ YYYY }}{{ MM }}{{ DD }}-{{ HH }}` * Example result: `Train-DayShift-20250907-05` * Use month name plus your own field: * Template: `{{ MMM }} {{ YYYY }} - Line {{ line }}` * Example result: `Sep 2025 - Line S1` ### Troubleshooting * A placeholder didn’t change? Check the spelling. Different styles like `JobName`, `job_name`, or `job name` are okay, but the words must match the field’s name. * Not using a blueprint? `{{ BLUEPRINT_NAME }}` won’t be filled.