{"openapi":"3.1.0","info":{"title":"Oway Shipper API","description":"Shipper integration API for requesting quotes, creating shipments, tracking, and retrieving documents.","contact":{"name":"Oway Support","email":"support@oway.io"},"version":"1.2.0"},"externalDocs":{"description":"Oway API Developer Portal","url":"https://oway.readme.io"},"servers":[{"url":"https://api.oway.io","description":"Production"},{"url":"https://api.sandbox.oway.io","description":"Sandbox Environment"}],"security":[{"bearerAuth":[],"apiKey":[]}],"tags":[{"name":"Shipper API","description":"Shipper integration endpoints for quotes and shipments.\n\n**Authentication & Authorization Required:**\n\nAll endpoints require BOTH credentials:\n1. **Bearer Token** (`authorization: Bearer {token}`) - Proves identity, requires `shipper` scope\n2. **API Key** (`x-oway-api-key: oway_sk_...`) - Determines which company's resources you can access\n\nThe API key is tied to your shipper company and automatically scopes all operations to that company's data.\nSee the Authentication section above for details on obtaining credentials.\n"},{"name":"Shipper API","description":"Appointment metadata endpoints. Capture structured appointment data per stop on appointment-required shipments.\n\nAuthentication & Authorization: same Bearer + API key requirements as the rest of the Shipper API."},{"name":"Shipper API","description":"Upload supporting documents (packing slip, customer BOL) for an appointment."}],"paths":{"/v1/shipper/shipment/{orderNumber}/confirm":{"put":{"tags":["Shipper API"],"summary":"Confirm a shipment by order number","description":"Confirms an existing shipment using its order number (PRO number).\nMoves the shipment from INITIALIZED to CONFIRMED state.\n\n**Prerequisites:**\n- The order must be in INITIALIZED state\n- The order must have an associated quote\n\n**Validation Requirements:**\n\nThe following fields are validated during confirmation. If any are missing or invalid,\nthe shipment will remain in INITIALIZED state.\n\n*Address Fields (required on BOTH pickup and delivery addresses):*\n- `name` - Location/company name\n- `address1` - Street address\n- `zipCode` - ZIP code\n- `contactPerson` - Contact name\n- `phoneNumber` - Contact phone (E.164 format, e.g., \"+15551234567\")\n- `openTime` - Opening time in HH:mm format (defaults to \"10:00\")\n- `closeTime` - Closing time in HH:mm format (defaults to \"16:00\")\n\n*Order Fields:*\n- `description` - Must not be empty\n- `totalPalletCount` - At least 1, up to the current per-order maximum\n- `totalPoundsWeight` - At least 1, within the current per-pallet weight cap\n\n*Order Component Fields (per component):*\n- `palletCount` - Must be at least 1\n- `poundsWeight` - At least 1, within the current per-pallet weight cap\n- `palletDimensions` - Length, width and height in inches, each at least 1 and\n  within the current maximums. These limits are configurable and change over\n  time, so they are not restated here: a pallet that exceeds them is rejected\n  with a 422 whose violation message states the maximum that applied. A pallet\n  larger than the standard footprint is still accepted and priced as oversized,\n  and a stop that requires a liftgate applies a tighter maximum.\n\n*Component Totals:*\n- Sum of component `palletCount` must equal order `totalPalletCount`\n- Sum of component `poundsWeight` must equal order `totalPoundsWeight`\n","operationId":"confirmShipment","parameters":[{"name":"orderNumber","in":"path","description":"Order number (5-character alphanumeric code, commonly called PRO number)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"}],"responses":{"200":{"description":"Shipment confirmed successfully. Verify the response contains `orderStatus: CONFIRMED` to ensure confirmation succeeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Invalid request: orderNumber is required, order is not in INITIALIZED state, or is missing a quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or shipment does not belong to your company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Shipment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/cancel":{"put":{"tags":["Shipper API"],"summary":"Cancel a shipment by order number","description":"Cancels an existing shipment using its order number (PRO number). Shipments can only be cancelled when they are in a cancellable state (e.g., before pickup).","operationId":"cancelShipment","parameters":[{"name":"orderNumber","in":"path","description":"Order number (5-character alphanumeric code, commonly called PRO number)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"}],"responses":{"200":{"description":"Shipment cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Invalid request: orderNumber is required, or order cannot be cancelled in its current state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or shipment does not belong to your company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Shipment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/appointment/{stop}":{"get":{"tags":["Shipper API"],"summary":"Read merged appointment requirement for a stop","description":"Returns the effective AppointmentRequirement for one stop, computed as the merge of the place-level default and the order-level override using a \"more-strict wins\" rule. The `_merged` diagnostic block in the response shows per-field provenance (PLACE | ORDER | PLACE_AND_ORDER | NONE).","operationId":"getAppointment","parameters":[{"name":"orderNumber","in":"path","description":"Order number (PRO)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"},{"name":"stop","in":"path","description":"pickup | delivery","required":true,"schema":{"type":"string","enum":["PICKUP","DELIVERY"]}}],"responses":{"200":{"description":"Merged appointment requirement. Fields are null when neither place nor order has data for that field; `_merged` is always present and shows source of each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRequirementResponse"}}}},"404":{"description":"Order does not exist or does not belong to your company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}},"put":{"tags":["Shipper API"],"summary":"Upsert appointment requirement for a stop","description":"Idempotent upsert of the order-level AppointmentRequirement for one stop (pickup or delivery). The full provided requirement replaces any prior value. Returns the merged effective requirement (place-level default + this order-level override) with a per-field provenance diagnostic.\n\nMutability: writes are accepted until the order reaches ACCEPTED. Writes against ACCEPTED+ orders return 409 order_accepted_appointment_locked.","operationId":"upsertAppointment","parameters":[{"name":"orderNumber","in":"path","description":"Order number (PRO)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"},{"name":"stop","in":"path","description":"pickup | delivery","required":true,"schema":{"type":"string","enum":["PICKUP","DELIVERY"]}},{"name":"confirmChangeAfterAcceptance","in":"query","description":"Set to true to override the post-acceptance mutability lock. Required together with the X-Oway-Change-Reason header.","required":false,"schema":{"type":"boolean","default":false}},{"name":"X-Oway-Change-Reason","in":"header","description":"Required when confirmChangeAfterAcceptance=true. Surfaces verbatim in the carrier-change notification email.","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRequirementRequest"}}},"required":true},"responses":{"200":{"description":"Appointment requirement upserted; body is the merged effective requirement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRequirementResponse"}}}},"400":{"description":"Validation failure. Response body's `violations[]` lists field paths and reasons.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Order does not exist or does not belong to your company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"409":{"description":"Order has reached ACCEPTED; appointment data is locked. Contact help@oway.io for changes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment":{"post":{"tags":["Shipper API"],"summary":"Create a new shipment","description":"Creates a new shipment order. Optionally reference a previously generated quote. The shipment must be confirmed after creation.\n\n**Note:** The `companyId` is automatically extracted from your API key.\nYou do not need to provide this value in the request body.\n\nFor M2M (machine-to-machine) integrations, no user context is required.\n","operationId":"createShipment","parameters":[{"name":"Idempotency-Key","in":"header","description":"Optional idempotency key. Retrying the same request with the same key within 24h returns the original response without creating a second shipment. Reusing the key with a different body returns 409 idempotency_key_conflict.","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateShipmentRequest"}}},"required":true},"responses":{"200":{"description":"Shipment created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Invalid request: validation error, quote mismatch, or expired quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, user not in company, or quote not owned by company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"422":{"description":"Unprocessable Entity. `reason` carries the coverage denial code, unmodified. Possible reasons:\n\n- **Location Not Serviceable** (`reason: no_aggregate_coverage`, `no_eligible_carriers`, or the legacy `no_coverage`): no carrier is known to serve this lane yet.\n- **Below Pallet Minimum** (`reason: min_pallets`): the shipment is under the pallet minimum configured for your account.\n- **Lane Not Available For Your Account** (`reason: coverage_denied`, `origin_policy_denied`, or `destination_policy_denied`): a coverage rule on your account excludes this lane or one of its endpoints. Contact your Oway representative for details.\n- **Above Your Coverage Level** (`reason: max_tier_capped`): carriers serve this lane, but it does not yet meet the level of proven coverage your account is set to accept. Contact your Oway representative to review that setting.\n- **Outside Service Area** (`reason: outside_service_area`): a pickup or delivery point is outside an area Oway serves.\n- **Excluded Toll Region** (`reason: excluded_toll_region`): the lane crosses a region excluded for your account.\n- **Request Not Permitted** (`reason: account_restriction`): the requested truck type or accessorial is not enabled for your account. Contact your Oway representative to update your available options.\n- **Daily Trip Limit Reached** (`reason: daily_trip_limit`): your account has reached its maximum shipments for the requested pickup date. You can still place orders for other dates.\n- **Pallet Shape Not Shippable** (`reason: pallet_invalid`): one or more pallets exceed Oway's dimension or weight limits; per-field details are in `violations`.\n- **Pricing Unavailable** (`reason: pricing_unavailable`): the lane could not be priced. Contact your Oway representative for assistance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/appointment/{stop}/document/{documentType}":{"post":{"tags":["Shipper API"],"summary":"Upload a supporting document for an appointment","description":"Multipart upload of a supporting document for one stop on an order. Allowed content types: application/pdf, image/jpeg, image/png. Images are wrapped to single-page PDF on upload. Max size 10 MB. Replaces any existing document of the same (stop, type).\n\ndocumentType must be one of: PACKING_SLIP, CUSTOMER_BOL. APPOINTMENT_DOCUMENT is system-only and returns 400 if attempted.\n\nMutability: writes against an order past ACCEPTED return 409 order_accepted_appointment_locked.","operationId":"uploadDocument","parameters":[{"name":"orderNumber","in":"path","description":"Order number (PRO)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"},{"name":"stop","in":"path","description":"pickup | delivery","required":true,"schema":{"type":"string","enum":["PICKUP","DELIVERY"]}},{"name":"documentType","in":"path","description":"Document type: PACKING_SLIP or CUSTOMER_BOL","required":true,"schema":{"type":"string","enum":["PACKING_SLIP","CUSTOMER_BOL","APPOINTMENT_DOCUMENT"]}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Document uploaded; body is the persisted document metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDocumentResponse"}}}},"400":{"description":"Bad request. Includes attempts to upload APPOINTMENT_DOCUMENT (reason: appointment_document_not_user_uploadable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Order does not exist or does not belong to your company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"409":{"description":"Order is past ACCEPTED; appointment data is locked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"413":{"description":"File exceeds the 10 MB upload limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"415":{"description":"Unsupported content type. Allowed: application/pdf, image/jpeg, image/png.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}},"delete":{"tags":["Shipper API"],"summary":"Delete a supporting document for an appointment","description":"Idempotent delete. Returns 204 whether or not the document existed.","operationId":"deleteDocument","parameters":[{"name":"orderNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"stop","in":"path","required":true,"schema":{"type":"string","enum":["PICKUP","DELIVERY"]}},{"name":"documentType","in":"path","required":true,"schema":{"type":"string","enum":["PACKING_SLIP","CUSTOMER_BOL","APPOINTMENT_DOCUMENT"]}}],"responses":{"204":{"description":"Deleted (or no-op when absent)."},"404":{"description":"Order does not exist or does not belong to your company.","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"409":{"description":"Order is past ACCEPTED; appointment data is locked.","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/quote":{"post":{"tags":["Shipper API"],"summary":"Request a shipping quote","description":"Generates a price quote for a shipment based on origin, destination, and cargo details. The quote is valid for 2 days.\n\n**Note:** The `companyId` is automatically extracted from your API key.\nYou do not need to provide this value in the request body.\n\nFor M2M (machine-to-machine) integrations, no user context is required.\n","operationId":"requestQuote","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}},"required":true},"responses":{"200":{"description":"Quote generated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"400":{"description":"Invalid request: validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or user does not belong to the authorized company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"422":{"description":"Unprocessable Entity. `reason` carries the coverage denial code, unmodified. Possible reasons:\n\n- **Location Not Serviceable** (`reason: no_aggregate_coverage`, `no_eligible_carriers`, or the legacy `no_coverage`): no carrier is known to serve this lane yet.\n- **Below Pallet Minimum** (`reason: min_pallets`): the shipment is under the pallet minimum configured for your account.\n- **Lane Not Available For Your Account** (`reason: coverage_denied`, `origin_policy_denied`, or `destination_policy_denied`): a coverage rule on your account excludes this lane or one of its endpoints. Contact your Oway representative for details.\n- **Above Your Coverage Level** (`reason: max_tier_capped`): carriers serve this lane, but it does not yet meet the level of proven coverage your account is set to accept. Contact your Oway representative to review that setting.\n- **Outside Service Area** (`reason: outside_service_area`): a pickup or delivery point is outside an area Oway serves.\n- **Excluded Toll Region** (`reason: excluded_toll_region`): the lane crosses a region excluded for your account.\n- **Request Not Permitted** (`reason: account_restriction`): the requested truck type or accessorial is not enabled for your account. Contact your Oway representative to update your available options.\n- **Daily Trip Limit Reached** (`reason: daily_trip_limit`): your account has reached its maximum shipments for the requested pickup date. You can still place orders for other dates.\n- **Pallet Shape Not Shippable** (`reason: pallet_invalid`): one or more pallets exceed Oway's dimension or weight limits; per-field details are in `violations`.\n- **Pricing Unavailable** (`reason: pricing_unavailable`): the lane could not be priced. Contact your Oway representative for assistance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}":{"get":{"tags":["Shipper API"],"summary":"Get a shipment by order number","description":"Retrieves a shipment by its order number (PRO number). The order number is a 5-character alphanumeric code (e.g., ZKYQ5) that uniquely identifies the shipment.","operationId":"getShipment","parameters":[{"name":"orderNumber","in":"path","description":"Order number (5-character alphanumeric code, commonly called PRO number)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"}],"responses":{"200":{"description":"Shipment retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment"}}}},"400":{"description":"Invalid request: orderNumber is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or shipment does not belong to your company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Shipment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/tracking":{"get":{"tags":["Shipper API"],"summary":"Track a shipment by order number","description":"Retrieves tracking information for a shipment by its order number (PRO number). Returns status and estimated/actual pickup and delivery dates. Pass `include=location` to embed the live position estimate (route-interpolated, refined by recent vehicle positions, with an uncertainty radius) in the response. It is omitted by default so status polling does not pay the position-computation cost.","operationId":"trackShipment","parameters":[{"name":"orderNumber","in":"path","description":"Order number (5-character alphanumeric code, commonly called PRO number)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"},{"name":"include","in":"query","description":"Comma-separated optional sections to include. Currently supports 'location' to embed the live shipment position estimate (route-interpolated, refined by recent vehicle positions, with an uncertainty radius). Omitted by default so status polling does not pay the position-computation cost.","required":false,"schema":{"type":"string"},"example":"location"}],"responses":{"200":{"description":"Tracking information retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tracking"}}}},"400":{"description":"Invalid request: orderNumber is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or shipment does not belong to your company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Shipment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/invoice":{"get":{"tags":["Shipper API"],"summary":"Get itemized invoice for a delivered shipment","description":"Retrieves the itemized invoice for a delivered shipment.\nThe invoice includes all charges (base freight, accessorials) and line items.\n\n**Note:** This endpoint is only available for shipments in DELIVERED state.\nInvoices are finalized when a shipment is delivered.\n","operationId":"getInvoice","parameters":[{"name":"orderNumber","in":"path","description":"Order number (5-character alphanumeric code, commonly called PRO number)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"}],"responses":{"200":{"description":"Invoice retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"400":{"description":"Invalid request: orderNumber is required, or shipment is not in DELIVERED state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or shipment does not belong to your company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Shipment not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/document/{documentType}":{"get":{"tags":["Shipper API"],"summary":"Get a shipment document by order number","description":"Retrieves a download link for a shipment document using the order number (PRO number). Supported document types: BILL_OF_LADING, INVOICE, SHIPPING_LABEL, POD.","operationId":"getDocument","parameters":[{"name":"orderNumber","in":"path","description":"Order number (5-character alphanumeric code, commonly called PRO number)","required":true,"schema":{"type":"string"},"example":"ZKYQ5"},{"name":"documentType","in":"path","description":"Type of document to retrieve","required":true,"schema":{"type":"string","enum":["BILL_OF_LADING","INVOICE","SHIPPING_LABEL","POD"]}}],"responses":{"200":{"description":"Document URL retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponse"}}}},"400":{"description":"Invalid request: orderNumber and documentType are required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing/invalid API key, or shipment does not belong to your company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Shipment or document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/shipment/{orderNumber}/appointment/{stop}/pdf":{"get":{"tags":["Shipper API"],"summary":"Read generated appointment PDF","description":"Returns the generated appointment PDF snapshot for one stop. The PDF is built at carrier acceptance (cover sheet + merged supporting documents) and re-generated on subsequent shipper-driven updates. Returns 404 before generation has occurred.","operationId":"getAppointmentPdf","parameters":[{"name":"orderNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"stop","in":"path","required":true,"schema":{"type":"string","enum":["PICKUP","DELIVERY"]}}],"responses":{"200":{"description":"Returns the application/pdf bytes for this stop.","content":{"application/pdf":{}}},"404":{"description":"PDF has not been generated for this order/stop yet (reason `appointment_pdf_not_generated`), or the order does not exist (reason `order_not_found`).","content":{"application/pdf":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/quotes/by-reference":{"get":{"tags":["Shipper API"],"summary":"Get a quote by your own customer reference","description":"Returns the newest quote your company holds under a customer reference: your own identifier for a load, such as the load number on a daily manifest.\n\nRead this before tendering a load whose tender cannot carry an Oway quote ID. `matchable` is true when the quote will back the booking as it stands: open, inside its 48-hour window, and carrying a price you can be charged.\n\nA load whose quote is missing, expired, or no longer matches the freight is still worth tendering. We re-price it and book at the new price rather than refusing it, and flag the difference for our operations team.\n\n**Note:** The reference is scoped to the company behind your API key. A reference another company uses for a different load is never returned to you.\n","operationId":"getQuoteByReference","parameters":[{"name":"reference","in":"query","description":"Your own identifier for the load, as sent on the quote request","required":true,"schema":{"type":"string"},"example":2835391}],"responses":{"200":{"description":"Quote found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteByReferenceResponse"}}}},"400":{"description":"Invalid request: reference is missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing, invalid, or expired API key (authorization failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Your company holds no quote under that reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/v1/shipper/quote/{quoteId}":{"get":{"tags":["Shipper API"],"summary":"Get a quote by ID","description":"Retrieves an existing quote by its unique identifier. Quotes are valid for 2 days from creation.","operationId":"getQuote","parameters":[{"name":"quoteId","in":"path","description":"Unique quote ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Quote retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"400":{"description":"Invalid request: quote ID format is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"401":{"description":"Unauthorized: missing or invalid Bearer token (authentication failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"403":{"description":"Forbidden: missing, invalid, or expired API key (authorization failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Quote not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}}},"components":{"schemas":{"Shipment":{"type":"object","description":"Shipment/Order details","properties":{"id":{"type":"string","description":"Unique identifier for the order","example":"67b6c5fcfbf1be6b24127646"},"companyId":{"type":"string","description":"Company ID that owns this order","example":"67c0dfa95bff090747660465"},"userId":{"type":"string","description":"User ID who created this order","example":"679410f5b074882a64b9ea7f"},"orderNumber":{"type":"string","description":"Human-readable PRO number for the shipment (5-character alphanumeric)","example":"ZKYQ5"},"orderStatus":{"type":"string","description":"Current status of the order","enum":["INITIALIZED","CONFIRMED","ACCEPTED","ASSIGNED","PICKED_UP","IN_TRANSIT","DELIVERED","CANCELLED","REJECTED"],"example":"CONFIRMED","enumDescriptions":{"CANCELLED":"Shipment cancelled","DELIVERED":"Shipment delivered to destination","ACCEPTED":"Carrier has accepted the shipment","INITIALIZED":"Shipment created but not yet confirmed for pickup","CONFIRMED":"Shipment confirmed and awaiting carrier assignment","IN_TRANSIT":"Freight in transit (alias for PICKED_UP)","ASSIGNED":"Driver assigned and scheduled for pickup","PICKED_UP":"Freight picked up and in transit","REJECTED":"Shipment will not be carried — either declined by the shipper or dropped after no coverage was secured in time"}},"totalPriceInCents":{"type":"integer","format":"int64","description":"Total price of the order in cents (USD)","example":125000},"createdAt":{"type":"string","format":"date-time","description":"Time when the order was created (ISO 8601 format)","example":"2025-02-20T17:31:10.430Z"},"updatedAt":{"type":"string","format":"date-time","description":"Time when the order was last updated (ISO 8601 format)","example":"2025-02-27T22:51:49.865Z"}}},"ProblemDetail":{"type":"object","description":"RFC 9457 Problem Details error response","properties":{"type":{"type":"string","description":"A URI reference that identifies the problem type","example":"https://api.oway.io/errors/location-not-serviceable"},"title":{"type":"string","description":"A short, human-readable summary of the problem type","example":"Bad Request"},"status":{"type":"integer","format":"int32","description":"The HTTP status code","example":400},"detail":{"type":"string","description":"A human-readable explanation specific to this occurrence of the problem","example":"pickupAddress.zipCode must be a 5-digit ZIP code"},"reason":{"type":"string","description":"A machine-readable reason code for programmatic handling","example":"pickup_not_covered"},"violations":{"type":"array","description":"Per-field validation failures when a request is rejected for one or more invalid fields. Present only on validation-style errors.","items":{"$ref":"#/components/schemas/Violation"}}}},"Violation":{"type":"object","description":"A single field-level validation failure.","properties":{"field":{"type":"string","description":"Field path that failed validation","example":"orderComponents[0].dimensions"},"entity":{"type":"string","description":"Entity the failing field belongs to (e.g. pickupAddress, deliveryAddress, appointment). Lets clients disambiguate otherwise-identical field paths across stops. Nullable for violations that have no entity context.","example":"deliveryAddress"},"reason":{"type":"string","description":"Human-readable reason the field is invalid. Any dimension or weight ceiling quoted in the message is configuration-driven, so treat the figures in the example as indicative rather than as a fixed part of the contract. The example is one rejection rather than every one: it shows a shipment that requested no liftgate. A shipment whose pickup or delivery requires a liftgate is measured against a different, generally tighter, set of dimension ceilings, and its message quotes whichever figures applied.","example":"Component dimensions of 110x48x40 are invalid (pallets must be less than 96x96x108, and greater than 1x1x1)"}}},"AppointmentContact":{"type":"object","description":"A single contact for the appointment. At least one of email or phone must be present.","properties":{"name":{"type":"string","description":"Contact name","example":"Maria Lopez","maxLength":200,"minLength":0},"email":{"type":"string","format":"email","description":"Email address","example":"maria@aqua.com","maxLength":320,"minLength":0},"phone":{"type":"string","description":"Phone in E.164 format","example":"+15555550101","maxLength":32,"minLength":0},"role":{"type":"string","description":"Role of the contact at the facility","example":"Warehouse Manager","maxLength":100,"minLength":0}},"required":["name"]},"AppointmentRequirementRequest":{"type":"object","description":"Structured appointment metadata for a single stop on an order. Sent on PUT /v1/shipper/shipment/{orderNumber}/appointment/{stop} or via the appointments block on POST /v1/shipper/shipment.","properties":{"channel":{"type":"string","description":"How the appointment is scheduled","enum":["PHONE","EMAIL","PORTAL"],"example":"PORTAL"},"portalUrl":{"type":"string","description":"Portal URL where the carrier will book the appointment. Required when channel == PORTAL, must be omitted otherwise.","example":"https://retaillink.example.com/scheduling","maxLength":512,"minLength":0},"contacts":{"type":"array","description":"Contacts the carrier can use to schedule the appointment","items":{"$ref":"#/components/schemas/AppointmentContact"},"maxItems":20,"minItems":0},"instructions":{"type":"string","description":"Free-text instructions shown to the carrier. Max 2000 chars.","example":"Driver must check in at gate B. Lift gate required. Schedule via portal at least 24 hours in advance.","maxLength":2000,"minLength":0},"referenceNumbers":{"type":"array","description":"Reference numbers (PO, customer pickup #, etc.) the carrier will be asked for. Max 10 entries, each max 64 chars.","example":["81CRR","DOCK-12"],"items":{"type":"string","maxLength":64,"minLength":0},"maxItems":10,"minItems":0},"leadTimeHours":{"type":"integer","format":"int32","description":"Minimum advance notice (in hours) the receiver requires. 0–168.","example":24,"maximum":168,"minimum":0}},"required":["channel"]},"AppointmentRequirementResponse":{"type":"object","description":"The effective (merged) appointment requirement for one stop, with per-field provenance in the _merged diagnostic.","properties":{"channel":{"type":"string","description":"Channel for booking the appointment","enum":["PHONE","EMAIL","PORTAL"]},"portalUrl":{"type":"string","description":"Portal URL when channel is PORTAL"},"contacts":{"type":"array","description":"Contacts the carrier can use","items":{"$ref":"#/components/schemas/AppointmentContact"}},"instructions":{"type":"string","description":"Free-text instructions"},"referenceNumbers":{"type":"array","description":"Reference numbers","items":{"type":"string"}},"leadTimeHours":{"type":"integer","format":"int32","description":"Minimum advance notice in hours"},"appointmentRequired":{"type":"boolean","description":"Whether the merged effective appointmentRequired is true (OR of place-level and order-level booleans)."},"_merged":{"$ref":"#/components/schemas/MergedDiagnostic","description":"Per-field provenance. Tells the caller whether each field came from the place-level default, the order-level override, both, or neither."}}},"MergedDiagnostic":{"type":"object","description":"Per-field provenance for the merged appointment requirement. Tells the caller whether each field came from the place-level default, the order-level override, both, or neither.","properties":{"fields":{"type":"object","additionalProperties":{"type":"string","enum":["PLACE","ORDER","PLACE_AND_ORDER","NONE","ADDRESS_FALLBACK"]},"description":"Map of field name -> source. Field names: channel, portalUrl, contacts, instructions, referenceNumbers, leadTimeHours. Values: PLACE | ORDER | PLACE_AND_ORDER | NONE."}}},"Address":{"type":"object","description":"Address information for pickup or delivery locations","properties":{"name":{"type":"string","description":"Name of the location or business","example":"Fairgrounds Distribution Center"},"address1":{"type":"string","description":"Primary street address","example":"1531 Junipero Avenue"},"address2":{"type":"string","description":"Secondary address line (suite, unit, etc.)","example":"Dock 5"},"city":{"type":"string","description":"City name","example":"Long Beach"},"state":{"type":"string","description":"Two-letter subdivision code. A request must name a US state, territory or DC; a response may name the subdivision of another country, which country names.","example":"CA","pattern":"[A-Z]{2}"},"zipCode":{"type":"string","description":"5-digit ZIP code. The placeholders 00000 and 99999 are rejected: neither is an assignable USPS code, and both are what a caller sends when a numeric ZIP field defaults to zero or saturates.","example":"90804","pattern":"^\\d{5}$"},"country":{"type":"string","default":"US","description":"Two-letter ISO 3166-1 alpha-2 country code, case-insensitive and normalized to upper case. Defaults to US when omitted. Oway currently serves the US and its territories, so US, PR, GU, VI, AS and MP are accepted and any other recognized code is rejected with 400 rather than quoted. A territory may also be addressed the way a carrier would, as country US with the territory in state.","example":"US","pattern":"^[A-Za-z]{2}$"},"phoneNumber":{"type":"string","description":"Contact phone number in E.164 format","example":"+18087857650","pattern":"^\\+[1-9]\\d{1,14}$"},"contactPerson":{"type":"string","description":"Name of the contact person at this location","example":"Mike Johnson"},"phoneExtension":{"type":"string","description":"Phone extension, dialled after the main number","example":"204","pattern":"^\\d{1,10}$"},"email":{"type":"string","format":"email","description":"Contact email for this location","example":"dock@example.com","maxLength":320,"minLength":0},"openTime":{"type":"string","description":"Opening time for the location in 24-hour format (HH:mm). Defaults to 10:00 if not provided.","example":"10:00","pattern":"^([01]?[0-9]|2[0-3]):[0-5][0-9]$"},"closeTime":{"type":"string","description":"Closing time for the location in 24-hour format (HH:mm). Defaults to 16:00 if not provided.","example":"16:00","pattern":"^([01]?[0-9]|2[0-3]):[0-5][0-9]$"},"notes":{"type":"string","description":"Additional notes or instructions for the driver","example":"Dock 3, enter from back of building"},"liftgateRequired":{"type":"boolean","description":"Whether a liftgate is required at this location","example":false},"limitedAccess":{"type":"boolean","description":"Whether this is a limited access location (residential, construction site, etc.)","example":false},"appointmentRequired":{"type":"boolean","description":"Whether an appointment is required for pickup/delivery","example":true},"callAheadRequired":{"type":"boolean","description":"Whether a call-ahead notification is required before pickup/delivery. When true, the carrier will call the contact person before arriving at the location.","example":true},"lumperRequired":{"type":"boolean","description":"Whether third-party lumper labor loads/unloads at this location (common at large distribution centers where drivers may not handle freight). Informational for quoting: the lumper fee is not priced into the quote and is billed after delivery as a separate charge with proof of payment.","example":false},"insideRequired":{"type":"boolean","description":"Whether the driver must bring freight inside the facility rather than to the dock or curb. Adds a flat inside-service fee to the quote.","example":false}},"required":["address1","city","contactPerson","name","phoneNumber","state","zipCode"]},"AppointmentsBlock":{"type":"object","description":"Optional inline-on-create block on POST /v1/shipper/shipment. Each entry is the AppointmentRequirementRequest for the corresponding stop, applied only if that address has appointmentRequired=true.","properties":{"pickup":{"$ref":"#/components/schemas/AppointmentRequirementRequest","description":"Appointment requirement for the pickup stop"},"delivery":{"$ref":"#/components/schemas/AppointmentRequirementRequest","description":"Appointment requirement for the delivery stop"}}},"CreateShipmentRequest":{"type":"object","description":"Request to create a new shipment","properties":{"quoteId":{"type":"string","description":"Optional ID of a previously generated quote.","example":"507f1f77bcf86cd799439013"},"pickupAddress":{"$ref":"#/components/schemas/Address","description":"Pickup location address"},"deliveryAddress":{"$ref":"#/components/schemas/Address","description":"Delivery location address"},"orderComponents":{"type":"array","description":"List of cargo components in the shipment","items":{"$ref":"#/components/schemas/OrderComponent"}},"description":{"type":"string","description":"Description of the shipment contents","example":"Electronics - fragile"},"poNumber":{"type":"string","description":"Purchase order number for reference","example":"PO-2024-12345"},"refNumber":{"type":"string","description":"Your reference number for this shipment (typically your Bill of Lading number). Prints on partner-branded BOLs alongside the Oway order number.","example":"BOL-2026-04129"},"instructions":{"type":"string","description":"Free-text instructions to render on the shipment's documents. Matches the instructions field on appointment requirements.","example":"Call receiving before arrival; dock 4 only.","maxLength":2000,"minLength":0},"referenceNumbers":{"type":"array","description":"Reference numbers (PO, customer pickup #, etc.) to render on the shipment's documents, beyond poNumber and refNumber.","example":["SO-45821","CUST-REF-7781"],"items":{"type":"string","maxLength":128,"minLength":0},"maxItems":10,"minItems":0},"requiredPickupDate":{"type":"string","format":"date-time","description":"Required pickup date (ISO 8601 format)","example":"2024-12-24T08:00:00Z"},"requiredDeliveryBy":{"type":"string","format":"date-time","description":"Required delivery by date (ISO 8601 format)","example":"2024-12-26T17:00:00Z"},"appointments":{"$ref":"#/components/schemas/AppointmentsBlock","description":"Optional inline appointment metadata per stop. May only be set for stops whose address has appointmentRequired=true. Each entry has the same shape as PUT /v1/shipper/shipment/{orderNumber}/appointment/{stop}."},"shipperDispatch":{"$ref":"#/components/schemas/ShipperDispatch","description":"Optional operational dispatch contact for this order. Distinct from the shipper company itself; useful when the desk handling questions about the load is different from the company account holder."}},"required":["deliveryAddress","description","orderComponents","pickupAddress"]},"Dimensions":{"type":"object","description":"Pallet dimensions in inches. All fields optional: if any are omitted the entire dimensions object is treated as missing and the API default of 40 x 48 x 60 in. (length x width x height) is applied.","properties":{"length":{"type":"integer","format":"int32","description":"Length in inches","example":48},"width":{"type":"integer","format":"int32","description":"Width in inches","example":48},"height":{"type":"integer","format":"int32","description":"Height in inches","example":72}}},"OrderComponent":{"type":"object","description":"A cargo component (pallet group) in a shipment","properties":{"palletCount":{"type":"integer","format":"int32","description":"Number of pallets in this component","example":2},"poundsWeight":{"type":"integer","format":"int32","description":"Weight per pallet in pounds","example":500},"palletDimensions":{"type":"array","deprecated":true,"description":"Pallet dimensions as [height, length, width] in inches. Deprecated: prefer the 'dimensions' object. Optional: if both 'palletDimensions' and 'dimensions' are omitted, the API defaults to 40 x 48 x 60 in. (length x width x height).","example":[72,48,48],"items":{"type":"integer","format":"int32","deprecated":true}},"dimensions":{"$ref":"#/components/schemas/Dimensions","description":"Pallet dimensions in inches. Optional: if both 'palletDimensions' and 'dimensions' are omitted, the API defaults to length=40, width=48, height=60."},"description":{"type":"string","description":"Per-component freight description (e.g. NMFC item name)","example":"Stone NOI"},"nmfcCode":{"type":"string","description":"NMFC commodity code for this component","example":"90500-04"},"freightClass":{"type":"string","description":"LTL freight class declared by the shipper. When supplied it is authoritative; Oway derives a class from density only when this is absent.","example":"100","pattern":"^(50|55|60|65|70|77\\.5|85|92\\.5|100|110|125|150|175|200|250|300|400|500)$"},"packagingType":{"type":"string","description":"Packaging type for this component (e.g. Pallets, Boxes, Crates)","example":"Pallets"},"pieceCount":{"type":"integer","format":"int32","description":"Number of pieces (loose items) in this component, distinct from pallet count","example":0}},"required":["palletCount","poundsWeight"]},"ShipperDispatch":{"type":"object","description":"The operational dispatch contact for this shipment. Distinct from the shipper company itself, this is the desk or person responsible for answering questions about the load. At least one of email or phone must be present.","properties":{"name":{"type":"string","description":"Dispatch contact name","example":"Acme Logistics","maxLength":200,"minLength":0},"email":{"type":"string","format":"email","description":"Dispatch email","example":"dispatch@example.com","maxLength":320,"minLength":0},"phone":{"type":"string","description":"Dispatch phone in E.164 format","example":"+15555550100","maxLength":32,"minLength":0,"pattern":"^\\+[1-9]\\d{1,14}$"},"scac":{"type":"string","description":"Standard Carrier Alpha Code (SCAC), if applicable","example":"ACME","maxLength":4,"minLength":0,"pattern":"^[A-Z]{2,4}$"}},"required":["name"]},"AppointmentDocumentResponse":{"type":"object","description":"Metadata for an uploaded appointment supporting document.","properties":{"id":{"type":"string","description":"Document ID","example":"65f1a2b3c4d5e6f7a8b9c0d1"},"stop":{"type":"string","description":"Stop the document is attached to","enum":["PICKUP","DELIVERY"],"example":"DELIVERY"},"type":{"type":"string","description":"Document type","enum":["PACKING_SLIP","CUSTOMER_BOL","APPOINTMENT_DOCUMENT"],"example":"PACKING_SLIP"},"filename":{"type":"string","description":"Original filename (renamed to .pdf if needed)","example":"packing-slip.pdf"},"sizeBytes":{"type":"integer","format":"int64","description":"Size in bytes after storage (images converted to PDF)","example":1245678},"contentType":{"type":"string","description":"Stored content type (always application/pdf)","example":"application/pdf"},"uploadedAt":{"type":"string","format":"date-time","description":"Upload timestamp"},"uploadedBy":{"type":"string","description":"User ID that performed the upload"}}},"QuoteRequest":{"type":"object","description":"Request to generate a shipping quote. Quotes are valid for 2 days from creation.","properties":{"pickupAddress":{"$ref":"#/components/schemas/Address","description":"Pickup location. Only zipCode is required for quotes."},"deliveryAddress":{"$ref":"#/components/schemas/Address","description":"Delivery location. Only zipCode is required for quotes."},"orderComponents":{"type":"array","description":"List of pallets or freight pieces.","items":{"$ref":"#/components/schemas/OrderComponent"}},"requiredPickupDate":{"type":"string","format":"date-time","description":"Required pickup date (ISO 8601).","example":"2026-04-01T08:00:00Z"},"shipmentMode":{"type":"string","description":"Shipment mode (LTL or FTL).","enum":["ltl","ftl"]}},"required":["deliveryAddress","orderComponents","pickupAddress"]},"QuoteResponse":{"type":"object","description":"Response containing a shipping quote","properties":{"id":{"type":"string","description":"Unique quote identifier","example":"507f1f77bcf86cd799439013"},"quotedPriceInCents":{"type":"integer","format":"int64","description":"Total quoted price in cents (USD)","example":125000},"quoteExpirationTime":{"type":"string","format":"date-time","description":"When this quote expires (ISO 8601 format). Quotes are valid for 2 days.","example":"2024-12-20T15:30:00Z"},"transitDays":{"type":["integer","null"],"format":"int32","description":"Number of business days to deliver the shipment after pickup. Pickup day is excluded; weekends are not counted. May be null when the ETA cannot be computed.","example":2},"estimatedDeliveryDate":{"type":["string","null"],"format":"date-time","description":"Estimated delivery date and time (ISO 8601 format, UTC). May be null when the ETA cannot be computed.","example":"2024-12-22T15:30:00Z"}}},"GpsData":{"type":"object","description":"GPS location data point for a vehicle","properties":{"vehicleId":{"type":"string","description":"Unique identifier for the vehicle","example":"TRUCK-001"},"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the GPS reading (ISO 8601 format). Must not be in the future.","example":"2025-02-20T17:33:15Z"},"latitude":{"type":"number","format":"double","description":"Latitude coordinate","example":33.787363,"maximum":90,"minimum":-90},"longitude":{"type":"number","format":"double","description":"Longitude coordinate","example":-118.163715,"maximum":180,"minimum":-180},"heading":{"type":"integer","format":"int32","description":"Heading in degrees (0-359, where 0 is North)","example":270,"maximum":359,"minimum":0},"speed":{"type":"integer","format":"int32","description":"Speed in km/h","example":65,"minimum":0}},"required":["heading","latitude","longitude","speed","timestamp","vehicleId"]},"ShipmentLocation":{"type":"object","description":"Current estimated shipment position with an uncertainty radius","properties":{"center":{"$ref":"#/components/schemas/GpsData","description":"Estimated center point of the shipment's current position (route-interpolated, refined by recent vehicle positions when available)"},"uncertaintyRadiusKm":{"type":"number","format":"double","description":"Uncertainty radius around the center point, in kilometers","example":4.2},"lastEventTimestamp":{"type":"string","format":"date-time","description":"Timestamp of the last event that updated the location (ISO 8601 format)","example":"2025-02-20T17:33:15Z"},"isSignificantlyDelayed":{"type":"boolean","description":"True when delivery is significantly past the expected window; the location estimate should not be shown","example":false},"delayMessage":{"type":"string","description":"Human-readable message to display when significantly delayed"},"statusDescription":{"type":["string","null"],"description":"Human-readable status sentence combining phase, approximate location, and ETA, e.g. 'IN TRANSIT DIRECT TO RECEIVER - Currently in Flagstaff, AZ - 2 Days 4 Hrs Until Destination'. Present only when a meaningful line can be produced; omitted otherwise."}}},"Tracking":{"type":"object","description":"Shipment tracking information","properties":{"id":{"type":"string","description":"Unique identifier for the order","example":"507f1f77bcf86cd799439011"},"orderNumber":{"type":"string","description":"Human-readable PRO number for the shipment (5-character alphanumeric)","example":"ZKYQ5"},"orderStatus":{"type":["string","null"],"description":"Current status of the order. Null only for an order whose internal state is unset; every live state maps to a value.","enum":["INITIALIZED","CONFIRMED","ACCEPTED","ASSIGNED","PICKED_UP","IN_TRANSIT","DELIVERED","CANCELLED","REJECTED"],"example":"PICKED_UP","enumDescriptions":{"CANCELLED":"Shipment cancelled","DELIVERED":"Shipment delivered to destination","ACCEPTED":"Carrier has accepted the shipment","INITIALIZED":"Shipment created but not yet confirmed for pickup","CONFIRMED":"Shipment confirmed and awaiting carrier assignment","IN_TRANSIT":"Freight in transit (alias for PICKED_UP)","ASSIGNED":"Driver assigned and scheduled for pickup","PICKED_UP":"Freight picked up and in transit","REJECTED":"Shipment will not be carried — either declined by the shipper or dropped after no coverage was secured in time"}},"actualPickupDate":{"type":"string","format":"date-time","description":"Actual pickup date/time (ISO 8601 format)","example":"2024-12-23T10:30:00Z"},"actualDeliveryDate":{"type":"string","format":"date-time","description":"Actual delivery date/time (ISO 8601 format)","example":"2024-12-25T14:00:00Z"},"estimatedPickupDate":{"type":"string","format":"date-time","description":"Estimated pickup date/time (ISO 8601 format)","example":"2024-12-23T09:00:00Z"},"estimatedDeliveryDate":{"type":["string","null"],"format":"date-time","description":"Estimated delivery date/time (ISO 8601 format). Null until a delivery window has been predicted or an appointment booked, which for most orders is at dispatch.","example":"2024-12-25T12:00:00Z"},"location":{"type":"null","$ref":"#/components/schemas/ShipmentLocation","description":"Live position estimate; present only when include=location is requested"}}},"InvoiceCharge":{"type":"object","description":"A charge on an invoice","properties":{"chargeType":{"type":"string","description":"Type of charge","example":"BASE_FREIGHT"},"description":{"type":"string","description":"Human-readable description of the charge","example":"Base Freight"},"amountInCents":{"type":"integer","format":"int64","description":"Amount in cents (USD)","example":100000}}},"InvoiceLineItem":{"type":"object","description":"A line item on an invoice","properties":{"description":{"type":"string","description":"Description of the item","example":"General Freight"},"freightClass":{"type":"string","description":"Freight class","example":"85"},"nmfcCode":{"type":"string","description":"NMFC commodity code for this line, when the shipment supplied one. Null when no NMFC was provided; it never falls back to the freight class, which is a different thing.","example":"90500-04"},"weight":{"type":"integer","format":"int32","description":"Weight in pounds","example":500},"quantity":{"type":"integer","format":"int32","description":"Number of pieces/pallets","example":2},"packageType":{"type":"string","description":"Package type","example":"PLT"}}},"InvoiceResponse":{"type":"object","description":"Itemized invoice for a delivered shipment","properties":{"orderId":{"type":"string","description":"Order ID","example":"67b6c5fcfbf1be6b24127646"},"orderNumber":{"type":"string","description":"Human-readable order number (PRO number)","example":"ZKYQ5"},"invoiceDate":{"type":"string","format":"date-time","description":"Invoice date (typically same as delivery date)","example":"2024-12-20T15:30:00Z"},"shipDate":{"type":"string","format":"date-time","description":"Ship date (when the shipment was picked up)","example":"2024-12-18T09:00:00Z"},"deliveryDate":{"type":"string","format":"date-time","description":"Delivery date (when the shipment was delivered)","example":"2024-12-20T15:30:00Z"},"poNumber":{"type":"string","description":"Purchase order number (if provided)","example":"PO-12345"},"refNumber":{"type":"string","description":"Reference number (BOL number)","example":"BOL-67890"},"lineItems":{"type":"array","description":"Line items representing the shipped goods","items":{"$ref":"#/components/schemas/InvoiceLineItem"}},"charges":{"type":"array","description":"Itemized charges and fees","items":{"$ref":"#/components/schemas/InvoiceCharge"}},"totalChargesInCents":{"type":"integer","format":"int64","description":"Total of all charges in cents (USD)","example":125000},"totalWeight":{"type":"integer","format":"int32","description":"Total weight of the shipment in pounds","example":1500},"totalPieces":{"type":"integer","format":"int32","description":"Total number of pieces/pallets","example":4},"shipper":{"$ref":"#/components/schemas/Address","description":"Shipper (pickup) address and contact information"},"consignee":{"$ref":"#/components/schemas/Address","description":"Consignee (delivery) address and contact information"},"billTo":{"$ref":"#/components/schemas/Address","description":"Bill-to address for the invoice (same as shipper for prepaid shipments)"}}},"DocumentResponse":{"type":"object","description":"Response containing a document download link","properties":{"filename":{"type":"string","description":"Name of the document file","example":"bol-ZKYQ5.pdf"},"fileType":{"type":"string","description":"MIME type of the document","example":"application/pdf"},"downloadLink":{"type":"string","description":"Pre-signed download URL (valid for limited time)","example":"https://s3.amazonaws.com/..."}}},"QuoteByReferenceResponse":{"type":"object","description":"The newest quote your company holds under a given customer reference. Use `matchable` to decide whether to tender against it: true means the quote is open, still inside its validity window, and carries a price you can book at.","properties":{"quoteId":{"type":"string","description":"Oway's quote ID.","example":"QT-8F3K29XA"},"customerReference":{"type":"string","description":"The reference you asked for, as stored on the quote.","example":"2835391"},"status":{"type":"string","description":"Quote status. OPEN is the only status that can back a booking.","example":"OPEN"},"priceCents":{"type":"integer","format":"int64","description":"All-in price in cents. Omitted when the quote carries no price you can book at (for example a lane we could not serve).","example":123400},"validUntil":{"type":"string","format":"date-time","description":"When the quote stops being bookable. 48 hours after it was issued.","example":"2026-09-25T16:05:00Z"},"originZip":{"type":"string","description":"Origin ZIP the quote was priced for.","example":"91730"},"destinationZip":{"type":"string","description":"Destination ZIP the quote was priced for.","example":"95206"},"pallets":{"type":"integer","format":"int32","description":"Pallet positions the quote was priced for.","example":12},"weightLbs":{"type":"number","format":"float","description":"Total weight in pounds the quote was priced for.","example":18400},"expired":{"type":"boolean","description":"True once validUntil has passed.","example":false},"matchable":{"type":"boolean","description":"True when this quote will back a tender as it stands: open, unexpired, and priced. When false, tender anyway if you want the load moved: we re-price it and book at the new price rather than refusing it.","example":true}}}},"securitySchemes":{"apiKey":{"type":"apiKey","description":"**Authorization** - API key that determines which company's resources you can access.\n\nEach API key is tied to a **single company** in Oway. Use the appropriate key type:\n\n| Key Type | Format | Use For |\n|----------|--------|---------|\n| Shipper | `oway_sk_xxx...` | Shipper API (`/v1/shipper/**`) |\n| Carrier | `oway_ck_xxx...` | Carrier API (`/v1/carrier/**`) |\n\nGenerate keys in your Oway portal (Settings → API Keys).\n\n**Required** alongside Bearer token for external API access.","name":"x-oway-api-key","in":"header","x-default":"oway_sk_your_api_key_here"},"bearerAuth":{"type":"http","description":"**Authentication** - Bearer token that proves your identity.\n\nObtain from `/v1/auth/token` endpoint. Tokens are valid for 24 hours.\n\nRequired scopes:\n- `shipper` for Shipper API\n- `carrier` for Carrier API\n- `dev` or `prod` for environment access\n\n**Required** alongside API key for external API access.","scheme":"bearer","bearerFormat":"JWT","x-default":"your_bearer_token_here"}}},"x-readme":{"samples-languages":["go","typescript","java","php","python"],"explorer-enabled":true,"headers":[{"key":"authorization","value":"Bearer your_bearer_token_here"},{"key":"x-oway-api-key","value":"oway_sk_your_api_key_here"}]}}