Class: Webhooks::V1::FreightquoteController
- Inherits:
-
BaseController
- Object
- ActionController::API
- BaseController
- Webhooks::V1::FreightquoteController
- Includes:
- ActionController::HttpAuthentication::Basic::ControllerMethods
- Defined in:
- app/controllers/webhooks/v1/freightquote_controller.rb
Overview
Webhook endpoint for CH Robinson Navisphere Events callbacks
(Freightquote LTL bookings).
Authentication:
CHR offers Basic Auth, OAuth 1.0/2.0, API key, or No Auth (per the
Navisphere swagger). We use HTTP Basic Auth embedded in the webhook
URL — same pattern as Webhooks::V1::ShipengineController. Credentials
come from Heatwave::Configuration.fetch(:freightquote, :webhook_*);
if they're blank the endpoint runs open (test/dev convenience), matching
ShipEngine's fallback.
Payload shape (one event per request — eventResponse schema):
{
"customer": "C8317882",
"eventTime": "2026-05-20T17:02:34.847Z",
"customerReferenceNumber": "787078",
"billToReferenceNumber": "787078",
"event": { "eventType": "LOAD CANCELLED", "loadNumber": 553933067, ... },
"time": "2026-05-20T17:02:36.798Z"
}
Instance Method Summary collapse
-
#create ⇒ Object
POST /webhooks/v1/freightquote.
Instance Method Details
#create ⇒ Object
POST /webhooks/v1/freightquote
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'app/controllers/webhooks/v1/freightquote_controller.rb', line 35 def create payload = json_payload if payload.blank? || payload['event'].blank? Rails.logger.warn '[Freightquote Webhook] Empty or malformed payload received' return head :bad_request end attrs = FreightEvent.parse_payload(payload) if attrs[:event_type].blank? || attrs[:event_time].blank? Rails.logger.warn '[Freightquote Webhook] Missing required eventType/eventTime' return head :bad_request end delivery = resolve_delivery(attrs[:customer_reference_number]) external_id = FreightEvent.idempotency_key_for( event_type: attrs[:event_type], event_time: attrs[:event_time], load_number: attrs[:load_number], order_number: attrs[:order_number] ) webhook_log = WebhookLog.ingest!( provider: 'freightquote', category: category_for(attrs[:event_type]), resource_type: 'Delivery', resource_id: delivery&.id, external_id: external_id, data: payload, notes: "FQ #{attrs[:event_type]} delivery=#{delivery&.id || '?'} load=#{attrs[:load_number] || '?'} order=#{attrs[:order_number] || '?'}" ) WebhookProcessorWorker.perform_async(webhook_log.id) head :ok end |