Hazardous Materials (Dangerous Goods)
RocketShipIt supports shipping hazardous materials (dangerous goods) for carriers that offer it. This includes creating hazmat shipping labels and getting rates that reflect Dangerous Goods surcharges such as lithium battery fees.
Note: Hazardous materials shipping is subject to strict regulations. Ensure you are familiar with the applicable regulations (CFR, IATA, ADR, TDG) for your shipments. RocketShipIt does not validate compliance — it is your responsibility to ensure all hazmat data is accurate.
Supported Carriers#
| Carrier | Rating | Labels |
|---|---|---|
UPS-REST |
Yes | Yes, including Shipper's Declaration paperwork |
FedEx-REST |
Yes | Lithium batteries only, see FedEx below |
DHL-REST and DHL (Express) |
Yes | Yes, see DHL Express below. DHL does not generate the Shipper's Declaration |
| Other DHL variants | No | No |
Key Parameters#
Hazmat data is set at the package level using the hazmat object inside each package. Additionally, the hazmat_regulation_set parameter can be set at the request level as a default for all chemical records.
| Parameter | Description |
|---|---|
hazmat_regulation_set |
Top-level default regulation set: CFR, IATA, ADR, or TDG |
hazmat_signatory_name |
Person or department signing the Dangerous Goods declaration. Setting this makes UPS return the Shipper's Declaration paperwork (see below) |
hazmat_signatory_title |
Title of the signatory |
hazmat_signatory_place |
City of the signatory |
hazmat_signatory_date |
Declaration date in YYYYMMDD format, defaults to today |
hazmat_shipper_declaration |
01 = one declaration for the shipment, 02 = one per package (default) |
hazmat.transport_mode |
Transport method: Ground, CAO (Cargo Aircraft Only), PAX (Passenger Aircraft), Highway |
hazmat.emergency_phone |
24-hour emergency response phone number |
hazmat.emergency_contact |
Emergency contact name |
hazmat.all_packed_in_one |
Set true if all hazmat items are packed in one package |
hazmat.overpack |
Set true if the package is an overpack |
hazmat.q_value |
Q-value for IATA AllPackedInOne (0.1–1.0) |
hazmat.outer_packaging_type |
Outer packaging type description (shipping labels only) |
hazmat.chemical_records |
Array of chemical records (max 3 per package for UPS) |
Chemical Record Fields#
Each entry in chemical_records supports the following fields:
| Parameter | Description |
|---|---|
identifier |
Unique identifier for this chemical record within the package |
regulation_set |
Per-chemical regulation set, overrides hazmat_regulation_set |
regulated_level_code |
FR (fully regulated), LQ (limited quantity), LR (lightly regulated), EQ (excepted quantity) |
id_number |
UN/NA/ID number (e.g., UN3480) |
proper_shipping_name |
DOT proper shipping name |
technical_name |
Technical/chemical name |
class_division_number |
Hazard class (e.g., 9, 3, 4.1) |
sub_risk_class |
Subsidiary risk class |
packaging_group |
Packing group (I, II, or III) |
quantity |
Quantity of the hazardous material |
uom |
Unit of measure (e.g., kg, ml) |
packaging_instruction_code |
Packaging instruction code (e.g., 965) |
packaging_type |
Type of inner packaging |
packaging_type_quantity |
Number of inner packages |
hazard_label |
Hazard label required indicator |
reportable_quantity |
Reportable quantity indicator (e.g., RQ) |
additional_description |
Additional description text |
transport_category |
Transport category |
tunnel_restriction_code |
Tunnel restriction code (e.g., D/E) |
Hazmat Shipping Labels#
To create a hazmat shipping label use the SubmitShipment action with the hazmat object on the package. The outer_packaging_type field is only used for shipping labels, not rating.
{
"carrier": "UPS-REST",
"action": "SubmitShipment",
"params": {
"account_number": "YOUR_ACCOUNT_NUMBER",
"key": "YOUR_UPS_API_KEY",
"service": "03",
"hazmat_regulation_set": "CFR",
"packages": [
{
"weight": 25,
"length": 10,
"width": 10,
"height": 10,
"hazmat": {
"transport_mode": "Ground",
"emergency_phone": "8005551234",
"emergency_contact": "Hazmat Response Team",
"all_packed_in_one": true,
"overpack": true,
"q_value": "0.5",
"outer_packaging_type": "FIBERBOARD BOX",
"chemical_records": [
{
"identifier": "1",
"regulation_set": "CFR",
"regulated_level_code": "FR",
"id_number": "UN3480",
"proper_shipping_name": "Lithium ion batteries",
"technical_name": "Lithium Ion",
"class_division_number": "9",
"sub_risk_class": "4.1",
"packaging_group": "II",
"quantity": "6",
"uom": "kg",
"packaging_instruction_code": "965",
"packaging_type": "Fiberboard Box",
"packaging_type_quantity": "1",
"hazard_label": "Y",
"reportable_quantity": "RQ",
"additional_description": "Limited Quantity",
"transport_category": "0",
"tunnel_restriction_code": "D/E"
}
]
}
}
],
"shipper": "RocketShipIt",
"ship_addr1": "123 Main St",
"ship_city": "Whitehall",
"ship_state": "MT",
"ship_code": "59759",
"ship_phone": "1231231234",
"ship_country": "US",
"to_name": "John Doe",
"to_addr1": "940 Presidio Ave",
"to_addr2": "#103",
"to_state": "CA",
"to_city": "San Francisco",
"to_code": "94115",
"to_country": "US",
"test": true
}
}
Hazmat Rating#
To get rates that include Dangerous Goods surcharges, use the GetAllRates action with the same hazmat object on the package. This is useful for quoting accurate shipping costs for orders containing hazardous materials like lithium batteries.
The request is nearly identical to the label request. The only differences are:
actionisGetAllRatesinstead ofSubmitShipmentouter_packaging_typeis not used for rating
{
"carrier": "UPS-REST",
"action": "GetAllRates",
"params": {
"account_number": "YOUR_ACCOUNT_NUMBER",
"key": "YOUR_UPS_API_KEY",
"service": "03",
"hazmat_regulation_set": "CFR",
"packages": [
{
"weight": 25,
"length": 10,
"width": 10,
"height": 10,
"hazmat": {
"transport_mode": "Ground",
"emergency_phone": "8005551234",
"emergency_contact": "Hazmat Response Team",
"all_packed_in_one": true,
"overpack": true,
"q_value": "0.5",
"chemical_records": [
{
"identifier": "1",
"regulation_set": "CFR",
"regulated_level_code": "FR",
"id_number": "UN3480",
"proper_shipping_name": "Lithium ion batteries",
"technical_name": "Lithium Ion",
"class_division_number": "9",
"sub_risk_class": "4.1",
"packaging_group": "II",
"quantity": "6",
"uom": "kg",
"packaging_instruction_code": "965",
"packaging_type": "Fiberboard Box",
"packaging_type_quantity": "1",
"hazard_label": "Y",
"reportable_quantity": "RQ",
"additional_description": "Limited Quantity",
"transport_category": "0",
"tunnel_restriction_code": "D/E"
}
]
}
}
],
"shipper": "RocketShipIt",
"ship_addr1": "123 Main St",
"ship_city": "Whitehall",
"ship_state": "MT",
"ship_code": "59759",
"ship_phone": "1231231234",
"ship_country": "US",
"to_name": "John Doe",
"to_addr1": "940 Presidio Ave",
"to_addr2": "#103",
"to_state": "CA",
"to_city": "San Francisco",
"to_code": "94115",
"to_country": "US",
"test": true
}
}
The response will include rates with any applicable Dangerous Goods surcharges. You can inspect the rate_detail array on each rate to see itemized charges.
Multiple Chemical Records#
You can include up to 3 chemical records per package for UPS. Each record can have its own regulation_set — if omitted, it falls back to the top-level hazmat_regulation_set.
"chemical_records": [
{
"identifier": "1",
"regulation_set": "CFR",
"regulated_level_code": "FR",
"id_number": "UN3480",
"proper_shipping_name": "Lithium ion batteries",
"class_division_number": "9",
"quantity": "6",
"uom": "kg",
"packaging_instruction_code": "965",
"packaging_type": "Fiberboard Box",
"packaging_type_quantity": "1"
},
{
"identifier": "2",
"regulated_level_code": "LQ",
"id_number": "UN1088",
"proper_shipping_name": "Acetal",
"class_division_number": "3",
"packaging_group": "II",
"quantity": "100",
"uom": "ml",
"packaging_instruction_code": "Y341",
"packaging_type": "Fiberboard Box",
"packaging_type_quantity": "1"
}
]
Note that the second record does not set regulation_set — it will use the value from hazmat_regulation_set at the request level.
Shipper's Declaration Paperwork#
For fully regulated dangerous goods UPS can generate the required Dangerous Goods shipping papers (Shipper's Declaration) along with the label. To receive them, set the signatory parameters at the request level:
"hazmat_signatory_name": "Jane Smith",
"hazmat_signatory_title": "Compliance Manager",
"hazmat_signatory_place": "Whitehall"
The paperwork is returned as one or more PDF documents in the response alongside the label:
"documents": [
{
"code": "dg_paper",
"type": "application/pdf",
"media": "JVBERi0xLjQg..."
}
]
FedEx#
The examples above use UPS-REST. FedEx supports the same package-level
hazmat object, but only for rating. Use GetAllRates with carrier
FedEx-REST to quote Dangerous Goods surcharges:
{
"carrier": "FedEx-REST",
"action": "GetAllRates",
"params": {
"account_number": "YOUR_ACCOUNT_NUMBER",
"key": "YOUR_FEDEX_API_KEY",
"packages": [
{
"weight": 25,
"length": 10,
"width": 10,
"height": 10,
"hazmat": {
"transport_mode": "Ground",
"emergency_phone": "8005551234",
"emergency_contact": "Hazmat Response Team",
"all_packed_in_one": true,
"chemical_records": [
{
"identifier": "1",
"regulated_level_code": "FR",
"id_number": "UN3480",
"proper_shipping_name": "Lithium ion batteries",
"class_division_number": "9",
"packaging_group": "II",
"quantity": "6",
"uom": "kg",
"packaging_instruction_code": "965",
"packaging_type": "Fiberboard Box",
"packaging_type_quantity": "1"
}
]
}
}
],
"ship_city": "Whitehall",
"ship_state": "MT",
"ship_code": "59759",
"ship_country": "US",
"to_state": "CA",
"to_code": "90210",
"to_country": "US",
"test": true
}
}
How FedEx interprets the parameters#
regulated_level_codeselects the FedEx dangerous goods option:FRisHAZARDOUS_MATERIALS,LQisLIMITED_QUANTITIES_COMMODITIES,EQisSMALL_QUANTITY_EXCEPTIONandLRisORM_D. Any other value is treated asHAZARDOUS_MATERIALS.reportable_quantityalso adds theREPORTABLE_QUANTITIESoption. Accepted values areRQ,Y,N,trueandfalse.transport_modeofCAOmarks the package cargo aircraft only.PAXandCAOalso set the aircraft accessibility. Ground and highway modes leave accessibility unset, because it is an air-only concept.packaging_typeandpackaging_type_quantitydescribe the container. FedEx holds these once per container, so the first chemical record that sets them wins for the whole package.- All chemical records for one package are sent as a single FedEx container.
quantitymust be a number andpackaging_type_quantitymust be a whole number. RocketShipIt rejects the request with an error naming the field if they are not.
These fields are accepted for UPS but have no FedEx equivalent, and are ignored
on FedEx requests: q_value, hazard_label, reference_number,
transport_category, tunnel_restriction_code, adr_item_number,
adr_packing_group_letter, local_proper_shipping_name,
local_technical_name, outer_packaging_type, and the per-record
regulation_set (FedEx infers it from the service and destination).
FedEx lithium batteries#
Lithium batteries do not need chemical records on FedEx. Set battery.type on
the package to LITHIUM_ION or LITHIUM_METAL and RocketShipIt sends the
Dangerous Goods special service with the battery option, declared as IATA
Section II. battery.packing_type is CONTAINED_IN_EQUIPMENT by default and
can be set to PACKED_WITH_EQUIPMENT:
"packages": [
{
"weight": 5,
"battery": {
"type": "LITHIUM_ION",
"packing_type": "PACKED_WITH_EQUIPMENT"
}
}
]
The same battery object works for both GetAllRates and SubmitShipment,
and both build the identical FedEx batteryDetails declaration. Rate with the
battery object rather than a hazmat object for lithium batteries so the
quote is booked at the same tier as the label. A hazmat chemical record with
regulated_level_code FR is fully regulated dangerous goods and carries a
much larger surcharge than a Section II battery.
FedEx hazmat labels#
FedEx does not accept chemical records on its Ship API. Its label request takes
only the dangerous goods classification, and expects the commodity data to
already be registered against your FedEx account. So SubmitShipment with a
hazmat object does not produce a hazmat label the way it does for UPS.
Lithium batteries are the exception, through the battery object above.
For any other FedEx hazmat label, use
request customization to add the
dangerousGoodsDetail block your account requires, and talk to your FedEx
account representative about enabling dangerous goods shipping.
DHL Express#
DHL Express (DHL-REST on the MyDHL API and the legacy XML-PI DHL carrier)
declares dangerous goods at the shipment level as a special service code
paired with a DHL "content ID". DHL requires both, so RocketShipIt derives the
pair from the same package-level battery, dry_ice and hazmat objects the
other carriers use. GetAllRates and SubmitShipment build the identical
declaration, so a quote includes the same surcharge the label books.
DHL lithium batteries#
Set battery.type and battery.packing_type on the package exactly as for
FedEx. RocketShipIt picks the DHL Section II service for the packing
instruction:
battery.type |
battery.packing_type |
UN number | DHL service | Content ID |
|---|---|---|---|---|
LITHIUM_ION |
PACKED_WITH_EQUIPMENT |
UN3481, PI966 Section II | HD |
966 |
LITHIUM_ION |
CONTAINED_IN_EQUIPMENT (default) |
UN3481, PI967 Section II | HV |
967 |
LITHIUM_METAL |
PACKED_WITH_EQUIPMENT |
UN3091, PI969 Section II | HM |
969 |
LITHIUM_METAL |
CONTAINED_IN_EQUIPMENT (default) |
UN3091, PI970 Section II | HW |
970 |
| either | STANDALONE |
UN3480 / UN3090, PI965 / PI968 | HE |
911 |
{
"carrier": "DHL-REST",
"action": "GetAllRates",
"params": {
"packages": [
{
"weight": 2,
"length": 10,
"width": 10,
"height": 10,
"battery": {
"type": "LITHIUM_ION",
"packing_type": "PACKED_WITH_EQUIPMENT"
}
}
],
...
}
}
Section II batteries need no Shipper's Declaration. DHL prints the required statement (for example "Lithium ion batteries in compliance with Section II of PI966") on the waybill from the content ID.
Standalone batteries (UN3480 and UN3090) are always fully regulated on DHL.
The 2026 IATA regulations removed Section II from PI965 and PI968, so DHL
books them as Dangerous Goods (HE) and cargo aircraft only (content ID
911). Your DHL account must be approved for dangerous goods, and you must
produce the Shipper's Declaration for Dangerous Goods yourself. DHL's API does
not generate it, unlike UPS. RocketShipIt books the service, and DHL prints
"Dangerous Goods as per associated DGD" on the waybill.
DHL hazmat chemical records#
A hazmat object with chemical_records maps onto DHL by
regulated_level_code:
regulated_level_code |
DHL service | Content ID | Notes |
|---|---|---|---|
FR (default) |
HE Dangerous Goods |
910 passenger aircraft, 911 cargo aircraft only |
911 when hazmat.transport_mode is CAO or the UN number is UN3480 / UN3090. Shipper's Declaration required |
LR |
HD, HV, HM or HW |
966, 967, 969 or 970 |
Section II lithium batteries by packaging_instruction_code. The same result as the battery object |
EQ |
HH Excepted Quantity |
E01 |
id_number is sent as the UN number |
LQ |
HL Limited Quantities ADR |
A01 |
Road only |
Dry ice uses the dry_ice object on the package (or the request), which books
HC with content ID 901 and the total net weight in the request's
weight_unit.
Declarations are de-duplicated across packages, so a shipment of three PI966
packages sends one HD service. The other chemical record fields (proper
shipping name, class, packing group, quantity) are not sent to DHL. DHL reads
them from the Shipper's Declaration.
You can also name a lithium battery code directly in addons
(HD, HV, HM, HW) and RocketShipIt adds the matching content ID. Codes
that need more data, such as HC dry ice and HH excepted quantities, must
come through the dry_ice or hazmat objects.
RocketShipIt returns an error naming the field when a combination cannot be
booked on DHL, for example an unknown battery.type or a lightly regulated
record without a packaging_instruction_code.
International Hazmat#
This section applies to UPS. International dangerous goods shipments use the same hazmat parameters combined with the usual international shipping parameters (customs/commodity data). For air transport set the regulation set to IATA and the transport mode to PAX (passenger aircraft) or CAO (cargo aircraft only):
"hazmat_regulation_set": "IATA",
"packages": [
{
"hazmat": {
"transport_mode": "CAO",
...
}
}
]
Include the signatory parameters above so the Shipper's Declaration required for air transport is returned with the label. Note that your UPS account must be enabled for international Dangerous Goods shipping — contact your UPS account representative if you receive entitlement errors.