Table of Contents
Custom Shipping Code Postmen Integration
The following page details integrating Postmen into your Foxy store for fetching shipping rates from any of their supported providers, using the Custom Shipping Code functionality available for Foxy stores.
Requirements
- A Foxy store on version 2.0
- At least one category configured with a delivery type of “Shipped using live shipping rates”
- An active Postmen account
Installation
Below is the custom shipping code you'll use to connect to Postmen, and below that is the steps to install it on your store.
// Set to the API key of your Postmen account let api_key = 'YOUR-POSTMEN-API-KEY'; // Set to false to use test shipper accounts let is_production = true; // Shipper accounts let shipper_accounts = [ { 'id': 'SHIPPER-ACCOUNT-ID-1' }, { 'id': 'SHIPPER-ACCOUNT-ID-2' } ]; // Weight units for the store ('lb' or 'kg') let weight_unit = 'lb'; // Length units for the store ('in' or 'cm') let length_unit = 'in'; // Parcel dimensions let parcel_width = 20, parcel_height = 10, parcel_depth = 10; const shipment = cart['_embedded']['fx:shipment']; let payload = { 'async': false, 'shipper_accounts': shipper_accounts, 'shipment': { 'parcels': [ { 'box_type': 'custom', 'weight': { 'value': shipment['total_weight'], 'unit': weight_unit }, 'dimension': { 'width': parcel_width, 'height': parcel_height, 'depth': parcel_depth, 'unit': length_unit }, 'items': [ // Populated below ] } ], 'ship_from': { 'state': shipment['origin_region'], 'postal_code': shipment['origin_postal_code'], 'country': country_to_3(shipment['origin_country']), }, 'ship_to': { // Populated below 'country': country_to_3(shipment['country']), 'type': shipment['is_residential'] ? 'residential' : 'business' } }, 'is_document': false }; // Ship to address if (shipment['first_name']) { payload.shipment.ship_to['contact_name'] = shipment['first_name'] + " " + shipment['last_name']; } if (shipment['address1']) { payload.shipment.ship_to['street1'] = shipment['address1']; } if (shipment['city']) { payload.shipment.ship_to['city'] = shipment['city']; } if (shipment['region']) { payload.shipment.ship_to['state'] = shipment['region']; } if (shipment['postal_code']) { payload.shipment.ship_to['postal_code'] = shipment['postal_code']; } // Items for (let p in cart['_embedded']['fx:items']) { let item = cart['_embedded']['fx:items'][p]; let item_details = { 'description': item.name, 'quantity': item.quantity, 'price': { 'amount': item.price, 'currency': cart.currency_code }, 'weight': { 'value': item.weight, 'unit': weight_unit } } if (item.sku) { item_details['sku'] = item.code } payload.shipment.parcels[0].items.push(item_details); } try { const endpoint = is_production ? 'https://production-api.postmen.com/v3' : 'https://sandbox-api.postmen.com/v3' const response = await fetch(endpoint + '/rates', { method: 'POST', body: JSON.stringify(payload), headers: { "postmen-api-key": api_key, "Content-Type": "application/json" } }); const data = await response.json(); if (data.meta.code != 200) { console.log(data.meta) } for (let r = 0; r < data.data.rates.length; r++) { const rate = data.data.rates[r]; if (rate.service_name) { rates.add(10000+r, rate.total_charge.amount, '', rate.service_name); } else if (rate.error_message) { console.log(rate.error_message); } } } catch(err) { console.log(err); } function country_to_3(country) { const iso3166_3 = { AF: 'AFG', AX: 'ALA', AL: 'ALB', DZ: 'DZA', AS: 'ASM', AD: 'AND', AO: 'AGO', AI: 'AIA', AQ: 'ATA', AG: 'ATG', AR: 'ARG', AM: 'ARM', AW: 'ABW', AU: 'AUS', AT: 'AUT', AZ: 'AZE', BS: 'BHS', BH: 'BHR', BD: 'BGD', BB: 'BRB', BY: 'BLR', BE: 'BEL', BZ: 'BLZ', BJ: 'BEN', BM: 'BMU', BT: 'BTN', BO: 'BOL', BA: 'BIH', BW: 'BWA', BV: 'BVT', BR: 'BRA', VG: 'VGB', IO: 'IOT', BN: 'BRN', BG: 'BGR', BF: 'BFA', BI: 'BDI', KH: 'KHM', CM: 'CMR', CA: 'CAN', CV: 'CPV', KY: 'CYM', CF: 'CAF', TD: 'TCD', CL: 'CHL', CN: 'CHN', HK: 'HKG', MO: 'MAC', CX: 'CXR', CC: 'CCK', CO: 'COL', KM: 'COM', CG: 'COG', CD: 'COD', CK: 'COK', CR: 'CRI', CI: 'CIV', HR: 'HRV', CU: 'CUB', CY: 'CYP', CZ: 'CZE', DK: 'DNK', DJ: 'DJI', DM: 'DMA', DO: 'DOM', EC: 'ECU', EG: 'EGY', SV: 'SLV', GQ: 'GNQ', ER: 'ERI', EE: 'EST', ET: 'ETH', FK: 'FLK', FO: 'FRO', FJ: 'FJI', FI: 'FIN', FR: 'FRA', GF: 'GUF', PF: 'PYF', TF: 'ATF', GA: 'GAB', GM: 'GMB', GE: 'GEO', DE: 'DEU', GH: 'GHA', GI: 'GIB', GR: 'GRC', GL: 'GRL', GD: 'GRD', GP: 'GLP', GU: 'GUM', GT: 'GTM', GG: 'GGY', GN: 'GIN', GW: 'GNB', GY: 'GUY', HT: 'HTI', HM: 'HMD', VA: 'VAT', HN: 'HND', HU: 'HUN', IS: 'ISL', IN: 'IND', ID: 'IDN', IR: 'IRN', IQ: 'IRQ', IE: 'IRL', IM: 'IMN', IL: 'ISR', IT: 'ITA', JM: 'JAM', JP: 'JPN', JE: 'JEY', JO: 'JOR', KZ: 'KAZ', KE: 'KEN', KI: 'KIR', KP: 'PRK', KR: 'KOR', KW: 'KWT', KG: 'KGZ', LA: 'LAO', LV: 'LVA', LB: 'LBN', LS: 'LSO', LR: 'LBR', LY: 'LBY', LI: 'LIE', LT: 'LTU', LU: 'LUX', MK: 'MKD', MG: 'MDG', MW: 'MWI', MY: 'MYS', MV: 'MDV', ML: 'MLI', MT: 'MLT', MH: 'MHL', MQ: 'MTQ', MR: 'MRT', MU: 'MUS', YT: 'MYT', MX: 'MEX', FM: 'FSM', MD: 'MDA', MC: 'MCO', MN: 'MNG', ME: 'MNE', MS: 'MSR', MA: 'MAR', MZ: 'MOZ', MM: 'MMR', NA: 'NAM', NR: 'NRU', NP: 'NPL', NL: 'NLD', AN: 'ANT', NC: 'NCL', NZ: 'NZL', NI: 'NIC', NE: 'NER', NG: 'NGA', NU: 'NIU', NF: 'NFK', MP: 'MNP', NO: 'NOR', OM: 'OMN', PK: 'PAK', PW: 'PLW', PS: 'PSE', PA: 'PAN', PG: 'PNG', PY: 'PRY', PE: 'PER', PH: 'PHL', PN: 'PCN', PL: 'POL', PT: 'PRT', PR: 'PRI', QA: 'QAT', RE: 'REU', RO: 'ROU', RU: 'RUS', RW: 'RWA', BL: 'BLM', SH: 'SHN', KN: 'KNA', LC: 'LCA', MF: 'MAF', PM: 'SPM', VC: 'VCT', WS: 'WSM', SM: 'SMR', ST: 'STP', SA: 'SAU', SN: 'SEN', RS: 'SRB', SC: 'SYC', SL: 'SLE', SG: 'SGP', SK: 'SVK', SI: 'SVN', SB: 'SLB', SO: 'SOM', ZA: 'ZAF', GS: 'SGS', SS: 'SSD', ES: 'ESP', LK: 'LKA', SD: 'SDN', SR: 'SUR', SJ: 'SJM', SZ: 'SWZ', SE: 'SWE', CH: 'CHE', SY: 'SYR', TW: 'TWN', TJ: 'TJK', TZ: 'TZA', TH: 'THA', TL: 'TLS', TG: 'TGO', TK: 'TKL', TO: 'TON', TT: 'TTO', TN: 'TUN', TR: 'TUR', TM: 'TKM', TC: 'TCA', TV: 'TUV', UG: 'UGA', UA: 'UKR', AE: 'ARE', GB: 'GBR', US: 'USA', UM: 'UMI', UY: 'URY', UZ: 'UZB', VU: 'VUT', VE: 'VEN', VN: 'VNM', VI: 'VIR', WF: 'WLF', EH: 'ESH', YE: 'YEM', ZM: 'ZMB', ZW: 'ZWE', XK: 'XKX' }; return iso3166_3[country]; }
Steps
- Log in to your store's Foxy administration
- Head to the “Shipping” page
- Scroll down until you see the “Custom Shipping Code” option, and check the option for “use custom code”.
- In the code editor that appears, copy and paste the code shown above. Don't save it just yet.
- In a new tab, log in to your Postmen account
- Go to API keys section
- Within the “Tokens” section, click the “Add new api key” button and complete the form
- Copy the API key generated to your clipboard from either the Production or Testing tabs (depending which type you created), and in the code you pasted into your Foxy admin above on this line:
let api_key = 'YOUR-POSTMEN-API-KEY';
Replace theYOUR-POSTMEN-API-KEY
text with your copied API key - Update this line to
false
instead oftrue
if you are using a Testing API key:let is_production = true;
- Update the
shipper_accounts
array to list out all of the shipper accounts you want to request rates from. Shipper accounts are created within Postmen in the Shipper Accounts section. Ensure you get from Production or Testing to match your API key type. - Configure the remainder of the configuration options for weight/length units and package size
- Click the “Update” button to save your new settings
- Wait ~10-15 seconds and refresh the page (the custom shipping code feature is a separate system, so takes a moment to initialize, you should see your custom code again after refreshing if it was successful)
- You're done! Now you can test it out!
To test our the new rates after saving, you can simply add a product to your cart that belongs to a live rate shippable category. On the cart or checkout, after entering a shipping address, you should see your rates returning from your Postmen account.
Taking It Further
This integration is fairly basic - it just returns all rates from Postmen, and passes it some default values. You can review the Postmen documentation on rate requests with their API here to customise the integration above further as needed.
You can also customise the rates returned, to only output specific rates or work with them further using our custom shipping code API documented here.