Skip to content

Shipping Carrier

First-Pass Node Dossier

This page is an evidence-backed node dossier generated from the domain hierarchy and node questionnaire.

What It Is

ShippingCarrier is the record that represents a physical or virtual shipping carrier such as a courier, freight company, or pickup provider.

It holds the identity and contact information for a carrier and acts as the anchor for the carrier services that link it to shipping brokers.

Parent hierarchy:

  • Fulfillment & Shipping
  • Shipping Configuration And Eligibility
  • Shipping Carrier

Related nodes in the same cluster:

  • ShippingBroker — the integration driver that resolves live rate and service lookups from a third-party shipping API
  • ShippingCarrierService — the junction that pairs one carrier with one broker service code and shipping type

Primary implementation paths:

  • packages/framework/src/Models/ShippingCarrier.php
  • packages/framework/src/Models/ShippingBroker.php
  • packages/framework/src/Models/ShippingCarrierService.php
  • packages/framework/src/Services/Shipping/ShippingCarrierService.php
  • packages/framework/src/Services/Shipping/ShippingBrokerService.php
  • packages/framework/src/Http/Controllers/Api/Admin/ShippingCarriersController.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers

What Users Can Do With It

Direct capabilities

Operators can:

  • list, search, create, and update shipping carriers through the packaged admin settings page at Settings > Shipping Carriers
  • create and update carriers through the admin API
  • manage the carrier services attached to a carrier (broker + service code + shipping type) through the edit dialog
  • add and remove notification email addresses for a carrier

Indirect capabilities

Other parts of the platform use ShippingCarrier through its associated services:

  • ShippingBrokerService queries carrier services to resolve applicable brokers for a given shipping type and carrier name
  • FulfillmentRequest can store a selected shipping_carrier_service_id alongside shipping_preferences when a shipment is planned through a broker integration

Things users cannot do directly

ShippingBroker records are not managed through the packaged admin UI. They are seeded by ShippingBrokerSeeder and configured through the pyle.shipping.broker_drivers config key. Operators only interact with brokers indirectly when adding carrier services inside the carrier edit dialog.

Where It Is Managed

ChannelRoleNotes
Admin settings pageDirectPackaged Livewire page at Settings > Shipping Carriers
Admin APIDirectCRUD endpoints under /admin/api/shipping_carriers
Carrier edit dialogParent-ownedServices (broker + service code) are managed inside the carrier edit dialog
FulfillmentRequestIndirectCarrier service ID and shipping preferences are stored on a fulfillment request when broker integration is used

Sources:

  • packages/admin/routes/web.php
  • packages/framework/routes/admin.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/Page.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/DataTable.php

Channel-Level Field Coverage

Admin settings page and API create

The ShippingCarrierService::create() action validates and accepts:

  • name — required, unique across all carriers
  • code — auto-generated from name as a slug if not provided; unique
  • shipping_type — optional; must be a valid ShippingType enum value
  • account_number — optional carrier account reference
  • image_url — optional logo URL
  • carrier_will_call — boolean; whether the carrier requires a call before pickup
  • call_window — object with hours and minutes fields; the expected call window when carrier_will_call is true
  • phone_number — optional contact phone
  • contact_name — optional primary contact name
  • contact_email — optional primary contact email
  • emails — array of additional notification email addresses

Sources:

  • packages/framework/src/Services/Shipping/ShippingCarrierService.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/DataTable/CreateDialog.php

Admin API update

The update action accepts the same fields as create. name and code are validated for uniqueness excluding the current record.

Admin API carrier services endpoint

GET /admin/api/shipping_carrier_services accepts:

  • shipping_carrier_name — required; matched by exact carrier name
  • shipping_type_name — optional; filtered by shipping type

Returns the ShippingCarrierService records for the matched carrier via ShippingCarrierServiceResource.

Admin API methods endpoint

GET /admin/api/shipping_carriers/methods returns the list of ShippingMethod enum values and labels. This is a supporting reference endpoint used by integrations that need to present shipping method choices.

Sources:

  • packages/framework/src/Http/Controllers/Api/Admin/ShippingCarriersController.php

Carrier services inside the edit dialog

When editing a carrier, operators can:

  • add a new service by selecting a broker, entering a service name and service code, and choosing a shipping type
  • update an existing service's broker, service name, service code, or shipping type
  • delete a service

The createService() action uses updateOrCreate keyed on (shipping_carrier_id, shipping_broker_id, service_code) to avoid duplicate entries.

Sources:

  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/DataTable/EditDialog.php
  • packages/framework/src/Services/Shipping/ShippingCarrierService.php

Configuration And Data Model

ShippingCarrier

Key characteristics:

  • soft-deletable
  • UUID-keyed
  • searchable through the PyleSearchable trait (database engine); indexed on name and code
  • emails cast to array
  • call_window cast to array
  • shipping_type cast to ShippingType enum

Relationships:

  • shippingCarrierServices() — hasMany ShippingCarrierService
  • shippingRates() — hasMany ShippingRate

Source:

  • packages/framework/src/Models/ShippingCarrier.php

ShippingBroker

Key characteristics:

  • soft-deletable
  • UUID-keyed
  • active cast to boolean
  • resolves its integration driver class from config("pyle.shipping.broker_drivers.{$this->api_type}")
  • falls back to NullShippingBrokerDriver when no driver is configured for the api_type

The broker driver contract supports getServices(), supports(), getViewName(), and getExtraFields(). NullShippingBrokerDriver returns empty or null for all methods.

The pyle.shipping.broker_drivers config key in packages/framework/config/config.php provides the driver map. Host applications register their own broker drivers through this config.

Seeded brokers include gofor, trinet, freightcom, and manual.

Relationships:

  • shippingCarrierServices() — hasMany ShippingCarrierService

Sources:

  • packages/framework/src/Models/ShippingBroker.php
  • packages/framework/src/Support/Shipping/NullShippingBrokerDriver.php
  • packages/framework/config/config.php
  • packages/framework/database/seeders/MandatorySeeders/ShippingBrokerSeeder.php

ShippingCarrierService

Key characteristics:

  • soft-deletable
  • junction between one ShippingCarrier and one ShippingBroker
  • shipping_type cast to ShippingType enum

Fields:

  • service_name — human-readable label for the service
  • service_code — the code used by the broker API to identify this service
  • shipping_type — the type of shipment this service covers
  • shipping_broker_id — the broker providing this service
  • shipping_carrier_id — the carrier that delivers through this service

Relationships:

  • shippingBroker() — belongsTo ShippingBroker
  • shippingCarrier() — belongsTo ShippingCarrier
  • shippingRates() — hasMany ShippingRate

Source:

  • packages/framework/src/Models/ShippingCarrierService.php

Relationships

  • ShippingCarrier owns many ShippingCarrierService records
  • ShippingBroker owns many ShippingCarrierService records
  • ShippingCarrierService bridges one carrier to one broker
  • FulfillmentRequest can reference a ShippingCarrierService through shipping_carrier_service_id
  • ShippableShippingCarrierService is a polymorphic pivot that associates any shippable model with a ShippingCarrierService

Sources:

  • packages/framework/src/Models/FulfillmentRequest.php
  • packages/framework/src/Models/ShippableShippingCarrierService.php

Rules And Downstream Effects

Carrier name and code uniqueness

name must be unique across all carriers. code must also be unique. If code is omitted on create, it is derived from the name using a slug transformation.

Service code uniqueness within a carrier-broker pair

(shipping_carrier_id, shipping_broker_id, service_code) is a unique combination. The createService() action uses updateOrCreate on this key. The updateService() action explicitly checks for conflicts before updating.

Broker driver fallback

When ShippingBroker::driver() is called and the api_type has no configured driver class, the call falls back to NullShippingBrokerDriver. This means getServices() returns an empty collection rather than raising an error.

Shipping preferences on fulfillment requests

ShippingPreference is a Fastest / Cheapest enum. It is stored in the shipping_preferences field on FulfillmentRequest to express how broker-driven shipment selection should behave when multiple services are available.

Source:

  • packages/framework/src/Enums/ShippingPreference.php

Integrations And Automation

Broker driver dispatch

ShippingBrokerService wraps driver calls behind a service layer:

  • getServices(broker, carrier) — delegates to the broker driver to retrieve live service options
  • getCarrierServices(broker, type, carrierName, serviceIds) — queries the ShippingCarrierService table directly
  • supports(broker, type, carrierName) — checks whether any matching service exists in the database
  • resolveApplicableBrokers(type, carrierName) — returns active brokers that have carrier services matching the given type and carrier name

Source:

  • packages/framework/src/Services/Shipping/ShippingBrokerService.php

FulfillmentRequest shipping carrier service

When a fulfillment request is processed through a broker integration, the selected ShippingCarrierService ID and shipping_preferences are persisted on the FulfillmentRequest. This preserves the carrier and broker selection for downstream fulfillment and audit flows.

Sources:

  • packages/framework/database/migrations/2026_02_10_215102_add_shipping_carrier_service_id_and_preferences_to_fulfillment_requests.php
  • packages/framework/src/Models/FulfillmentRequest.php

Where It Appears To End Users

ShippingCarrier is a first-class settings record visible to admin operators at Settings > Shipping Carriers.

Operators see:

  • a searchable table of all carriers
  • create and edit dialogs with all carrier fields
  • a service sub-table inside the edit dialog showing attached broker services

Shoppers do not interact with carriers or brokers directly. The carrier-and-service layer is internal configuration that downstream broker integrations use to determine which service to request and which carrier to dispatch.

Current Documentation Takeaways

  1. ShippingCarrier is the operator-managed record. ShippingBroker is a system-managed integration driver that is seeded and configured, not created in the admin UI.
  2. ShippingCarrierService is the bridge between a carrier and a broker. It is the record that fulfillment broker integrations use to resolve a service code during shipment.
  3. The broker driver system uses a config map (pyle.shipping.broker_drivers) to resolve the correct driver class for each api_type. Host applications that integrate a new shipping API must register their driver there.

Open Questions

  • The ShippableShippingCarrierService polymorphic pivot exists in the database but no Livewire or API surface for it was found in this pass. Its full usage may be in host-application broker workflows.
  • ShippingRate is referenced by both ShippingCarrier and ShippingCarrierService but is not part of the packaged framework in this pass.

Sources:

  • packages/framework/src/Models/ShippingCarrier.php
  • packages/framework/src/Models/ShippingBroker.php
  • packages/framework/src/Models/ShippingCarrierService.php
  • packages/framework/src/Models/ShippableShippingCarrierService.php
  • packages/framework/src/Models/FulfillmentRequest.php
  • packages/framework/src/Services/Shipping/ShippingCarrierService.php
  • packages/framework/src/Services/Shipping/ShippingBrokerService.php
  • packages/framework/src/Http/Controllers/Api/Admin/ShippingCarriersController.php
  • packages/framework/src/Enums/ShippingPreference.php
  • packages/framework/src/Support/Shipping/NullShippingBrokerDriver.php
  • packages/framework/config/config.php
  • packages/framework/database/seeders/MandatorySeeders/ShippingBrokerSeeder.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/Page.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/DataTable.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/DataTable/CreateDialog.php
  • packages/admin/src/Livewire/Admin/Settings/ShippingCarriers/DataTable/EditDialog.php
  • packages/admin/routes/web.php
  • packages/framework/routes/admin.php