---
title: "[Experimental] Book a shipment using a previous quote ID"
method: POST
path: "/freights/book"
tags: ["Freight"]
---

# \[Experimental\] Book a shipment using a previous quote ID

`POST /freights/book`

## Request

- Base URL: `https://stg.wearewarp.com/api/v1`
- URL: `https://stg.wearewarp.com/api/v1/freights/book`
- Auth: API key in header `apikey`

Provide all the details required for delivery, linked with id of selected quote option (`quoteId` = `options[].id` of POST /freights/freight-quote). The quote option must not be expired and must not have been booked already.<br/><br/>**The booking must match the quote exactly**: pickup/delivery zipcodes, every item's height, length, width, sizeUnit, totalWeight, weightUnit and quantity, and the service lists - otherwise the request is rejected with 400 `invalid_field_data` and a message such as `Pickup Zipcode 90001 does not match with quoting request 90058.`, `Drop-off zipcode ... does not match with quoting request ...`, `Number of items 2 does not match with number of items in quoting request 1.`, `List of items do not match with list of Items in quoting request.` or `additionalServices does not match with quoting request.` (also `pickupInfo.serviceOptions` / `deliveryInfo.serviceOptions`).<br/><br/>**PARCEL quotes:** send the items in `IN` and `lbs` on both the quote and the booking. The quote stores parcel items converted to inches/pounds and the booking compares the raw values, so any other unit is reported as a mismatch.<br/><br/>**Validation notes:** `pickupInfo.contactPhone` and `deliveryInfo.contactPhone` are required. `timeWindow.from` / `timeWindow.to` (and `appointmentInfo`) must be ISO 8601 date-times **in the future** and `from` must not be later than `to`. `items[].height` must be <= 85.<br/><br/>If the customer balance is not enough to cover this booking, the order is still created but it is put on hold until the payment is completed. In that case the response also includes **message** and **paymentLink** - open that link to add funds and complete the payment.<br/><br/>If *Pay by card for API bookings* is turned on in the customer portal (Settings > API Access), that booking is charged to the selected saved card instead (total + card processing fee) and the response includes **payment** `{ method, amount_charged, card_fee, last4 }`. A card that cannot be charged returns HTTP 402 with **code** `CHARGE_FAILED` or `PAYMENT_ACTION_REQUIRED` and no order is created; HTTP 409 `BOOKING_IN_PROGRESS` means another request for the same quote is in progress. Insurance (`insuranceQuoteId`) is not available on a booking paid by saved card (HTTP 400 `CARD_INSURANCE_NOT_SUPPORTED`).

## Request body

- FreightBookingShipment
  - `quoteId` string, required: The `options[].id` of the chosen option from POST /freights/freight-quote. Must not be expired or already booked; the booking payload must match the quote exactly.
  - `pickupInfo` BookingStopInfo, required
    - `locationName` string
    - `contactName` string
    - `contactPhone` string, required
    - `phoneExtension` string
    - `contactEmail` string
    - `address` Address, required
      - `street2` string
      - `street` string, required
      - `city` string, required
      - `state` string, required
      - `zipcode` string, required
    - `requiresAppointment` boolean
    - `appointmentInfo` TimeWindow
      - `from` string, date-time, required: Starting time of the window in ISO format
      - `to` string, date-time, required: Ending time of the window in ISO format
    - `timeWindow` TimeWindow, required
      - `from` string, date-time, required: Starting time of the window in ISO format
      - `to` string, date-time, required: Ending time of the window in ISO format
    - `serviceOptions` string[]
    - `instructions` string
    - `refNums` string[]
  - `deliveryInfo` BookingStopInfo, required
    - `locationName` string
    - `contactName` string
    - `contactPhone` string, required
    - `phoneExtension` string
    - `contactEmail` string
    - `address` Address, required
      - `street2` string
      - `street` string, required
      - `city` string, required
      - `state` string, required
      - `zipcode` string, required
    - `requiresAppointment` boolean
    - `appointmentInfo` TimeWindow
      - `from` string, date-time, required: Starting time of the window in ISO format
      - `to` string, date-time, required: Ending time of the window in ISO format
    - `timeWindow` TimeWindow, required
      - `from` string, date-time, required: Starting time of the window in ISO format
      - `to` string, date-time, required: Ending time of the window in ISO format
    - `serviceOptions` string[]
    - `instructions` string
    - `refNums` string[]
  - `additionalServices` string[]
  - `items` BookShipmentItem[], required
    - `name` string
    - `height` number, required: Maximum 108 on POST /freights/booking; maximum 85 on POST /freights/freight-quote, /freights/book and the multi-stops endpoints (checked on the raw value, whatever the sizeUnit).
    - `length` number, required
    - `width` number, required
    - `sizeUnit` 'IN' | 'FT', required
    - `totalWeight` number, required
    - `weightUnit` 'lbs' | 'kgs', required
    - `quantity` integer, required
    - `packaging` string: Packaging unit of the line item (e.g. Pallet). Defaults to Pallet.
    - `temperature_limit` object: Temperature-controlled (reefer) freight is NOT supported yet by the quote endpoints: POST /freights/quote rejects any non-zero min/max and POST /freights/freight-quote rejects the field entirely with 400 `Reefer Shipment is not supported yet!`. Omit this field unless instructed otherwise by WARP.
      - `min` number: Minimum temperature.
      - `max` number: Maximum temperature.
    - `stackable` boolean
    - `notes` string
    - `freightClass` string: NMFC freight class of the line item (e.g. 70).
    - `barcodes` string[]
  - `insuranceQuoteId` string: Optional. The insuranceQuoteId returned in the insurance block of the quote endpoint. Provide it to purchase insurance for this shipment.

## Response `200`

successful creation

- BookingResult
  - `message` string: Only present when the customer balance is not enough to cover this booking. In that case paymentLink is also included.
  - `trackingNumber` string: Tracking number of the created shipment - accepted by POST /freights/tracking.
  - `proNumber` string: The display number (code) of the created order.
  - `orderId` string
  - `shipmentIds` string[]: Display numbers (codes) of the created shipments - not ULIDs. Use them as shipmentNumber / shipmentId on the other endpoints (both accept the code).
  - `insuranceStatus` 'booked' | 'failed': Only present when insuranceQuoteId was provided. "booked" if insurance was booked insurance successfully, "failed" if it could not be booked insurance
  - `paymentLink` string, uri: Only present when the customer balance is not enough to cover this booking. The order is still created, but it is on hold until the payment is completed. Open this link to add funds and complete the payment.

## Other responses

- `400`: Bad Request - the request payload is missing fields or contains invalid data.
- `401`: Unauthorized - the apikey header is missing or does not match any active API key.
- `403`: Forbidden - the customer account is suspended. The body carries `message` only, without `code`.
- `429`: Too Many Requests - the quoting rate limit of the API key was exceeded (only POST /freights/quote, /freights/freight-quote and /freights/quote/multi-stops are rate limited; limits apply per UTC hour and per UTC day). The `Retry-After` header holds the number of seconds until the window resets.
- `500`: Internal Server Error - an unknown error has occurred.

---

[API](https://skmtc.dev/wearewarp/apis/warp-api-documentation.md) · [All operations](https://skmtc.dev/wearewarp/apis/warp-api-documentation/llms.txt) · [OpenAPI document](https://skmtc.dev/wearewarp/apis/warp-api-documentation/revisions/01526741bb48?raw)
