Source

dispatch.js

const {
  retrieveDelivery,
  listDeliveries,
  createDelivery,
  purchaseDelivery,
  refundDelivery,
  updateDelivery,
} = require("./modules/deliveries");

const { retrieveLocation } = require("./modules/locations");
const { retrieveProfile } = require("./modules/profile");

const _createNetworkConfig = require("./util/network-config");

/**
 * Creates a new Dispatch class. Once this class is initialized, you can use any of the namespaces with a method to use tge API.
 * @name Dispatch
 * @class
 * @classdesc This is the main class that will be the entry point into dispatch. You can initialize this class with your API Key.
 * @param {string} token - Initialize the class with your API key.
 * @param {string} [env="production"] - Unless you have development keys, leave this blank.
 *
 * @example const dispatch = new Dispatch("key_EHKD5tbatzX59DArnTBjhr46G5n1f4aJkvwPByft")
 *
 */
module.exports = class Dispatch {
  constructor(apikey, env = "production", debug = false) {
    this.apikey = apikey;
    this.env = env;
    this.debug = debug;

    /**
     *
     * @memberof Dispatch
     * @namespace deliveries
     */
    this.deliveries = {
      /**
       * Retrieves a delivery using its ID
       * @memberof Dispatch.deliveries
       * @namespace Dispatch.deliveries.retrieve
       *
       * @method retrieve
       * @param {string} id - The ID of the delivery that you want to retrieve
       * @returns {Promise<Response>} Returns the response object. The Response's [data property]{@link Delivery} will be an array of {@link Delivery} objects.
       *
       * @example const response = await dispatch.deliveries.retrieve("del_fjdsklfju8jisjfdisoiu89j")
       * const delivery = response.data //this will contain the delivery object
       */
      retrieve: function (id) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          retrieveDelivery(id, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },

      /**
       * Get a paginated list of deliveries
       * @memberof Dispatch.deliveries
       * @namespace Dispatch.deliveries.list
       *
       * @method list
       * @param {Object} options - The options that you can use to return results
       * @param {integer} options.limit - The amount of deliveries you want returned. The default is 15, but ranges from 1 to 100
       * @param {integer} options.page - The page you want to deliveries to start at. For example, a limit of 15 with a page value of 3, would return deliveries 30 - 45. The response object for the .list() method will have a pagination property which you can use to determine if there are more values in the database.
       * @param {integer} options.location - Add a location ID the get just results from a specific location
       * @param {integer} options.status - Will filter results based on statuses. Available options are: `all (default)`, `completed`, `outstanding`, `error`. `completed` will respond with any package that has gone through its lifecycle. Most often this is delivered but will include errors suck as `package_lost`. `outstanding` will respond with any package that is not yet completed its lifecycle, not including errors. `error` will respond with every package that has an error.
       * @returns {Promise<Response>} Returns the response object. The Response's [data property]{@link Delivery} will be an array of {@link Delivery} objects.
       *
       * @example const response = await dispatch.deliveries.list()
       * const deliveries = response.data //this will have an array of delivery objects
       *
       * //check if there are more values in the database
       * if (data.pagination.has_more) {
       *    //the delivery objects have a lot of data and setting the pagination to a loop can really hurt performance
       *    //it's advised to just query in pages
       *    //io query for the next page of deliveries you could do something like:
       *
       *    const nextResponse = dispatch.deliveries.list({limit: response.pagination.limit, page: response.pagination.current_page + 1})
       * }
       *
       */
      list: function (options) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          listDeliveries(options, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },

      /**
       * Create a delivery intent. This will give you a list of rates to choose from.
       * @memberof Dispatch.deliveries
       * @namespace Dispatch.deliveries.create
       *
       * @method create
       * @param {Object} sender - The details about there this package is coming from.
       * @param {string} sender.name - The name of the sender. This could be a company name or a person's name.
       * @param {string} sender.email - The email of the sender. For on demand deliveries, this email will be used by the courier to contact the sender in case of any issues.
       * @param {string} [sender.phone] - The phone number of this sender that an on demand courier could use to contact this sender if there is an issue.
       * @param {string} [sender.location_id] - If you already have a location object, you can simply pass the id of the location and we'll use it's address.
       * @param {(string|Object<NewAddress>)} [sender.address] - If you do not have a location_id, you can just send your address and we'll create a location object for you. Your address can just be a full string and we'll parse it on our end, or you can send it as an object.
       * @param {Object} recipient - The details about there this package is coming from.
       * @param {string} recipient.name - The name of the sender. This could be a company name or a person's name.
       * @param {string} recipient.email - The email of the sender. For on demand deliveries, this email will be used by the courier to contact the sender in case of any issues.
       * @param {string} [recipient.phone] - The phone number of this recipient that an on demand courier could use to contact this recipient if there is an issue.
       * @param {(string|Object<NewAddress>)} recipient.address - Your address can just be a full string and we'll parse it on our end, or you can send it as an object
       * @param {Array<Parcel>} parcels - An array of parcels that you want to send.
       * @param {Object} [options] - Additional options to include in your delivery.
       * @param {Array} [options.rate_cards] - An array of rate cards that you want to use for this transaction. These will be used instead of the rate cards you set on your Dispatch Dashboard.
       * @param {Integer} [options.checkout_total=0] - The total cart/checkout value you submitted as an integer (e.g., $15.76 would be represented as 1576). This value is used to determine the free shipping tier that you can set up on the Dispatch dashboard.
       * @param {Integer} [options.metadata] - You can add metadata as key-value pairs to a delivery. To remove a property, pass `null` as the value. If you want to remove all key value pairs, pass an empty object.
       * @param {Boolean} [options.verify_address=true] - If you want Dispatch to verify the sender and recipient addresses
       * @returns {Promise<Response>} Returns the response object. The Response's [data property]{@link Delivery} will be an array of {@link Delivery} objects.
       *
       * @example
       * //This is a basic example for a standard shipment creating without additional options.
       *
       * const sender = {
       *    name: "Dispatch Roasters"
       *    email: roasters@getdispatch.app,
       *    phone: "4844836699",
       *    location_id: "loc_j83498fhweofh4937fh"
       * }
       *
       * const recipient = {
       *    name: "Jamie Jones"
       *    email: jamie.jones@getdispatch.app,
       *    phone: "4844836699",
       *    address: {
       *        address_line1: "500 7th Ave",
       *        city: "New York",
       *        state: "NY"
       *        zipcode: "10018"
       *    }
       * }
       *
       * const parcel = {
       *    length: 10 // inches
       *    width: 10 // inches
       *    height: 10 // inches
       *    weight: 10 // pounds
       *    item_description: "Coffee", //optional
       *    special_handling: "Fragile" //optional
       * }
       *
       * //options are completely optional. You can omit the whole object
       * //or any properties from the object
       * const options = {
       *    checkout_total: 5000, //$50.00
       *    verify_address: false,
       *    metadata: {
       *        my_custom_id: "123456789"
       *    }
       * }
       *
       *
       *
       * const response = await dispatch.deliveries.create(sender, recipient, [parcel], options)
       * const delivery = response.data //this will have the delivery object
       *
       *
       * @example
       * //in this example, we'll create the same shipment but add additional options
       *
       * const sender = {
       *    name: "Dispatch Roasters"
       *    email: roasters@getdispatch.app,
       *    location_id: "loc_j83498fhweofh4937fh"
       * }
       *
       * const recipient = {
       *    name: "Jamie Jones"
       *    email: jamie.jones@getdispatch.app,
       *    address: {
       *        address_line1: "500 7th Ave",
       *        city: "New York",
       *        state: "NY"
       *        zipcode: "10018"
       *    }
       * }
       *
       * const parcel = {
       *    length: 10 // inches
       *    width: 10 // inches
       *    height: 10 // inches
       *    weight: 10 // pounds
       * }
       *
       * //if you wanted to add options, like the checkout_total, you can do so in the fourth argument
       * const options = {
       *
       *    //the checkout total is used to return free shipping options. These settings
       *    //are configured once on the Dispatch dashboard
       *    checkout_total: 10000 //this would be $100.00 since values are stored as integers
       *
       *
       *    //the metadata allowed you to add custom properties to the delivery object
       *    //most often used for an order number or customer number to be able to match
       *    //delivery with your internal database later. The metadata property will be
       *    //available on the delivery object when you retrieve it
       *    metadata: {
       *        customer_id: 123456789,
       *        order_id: 987654321
       *        temp_value: null //passing null will delete the key, if you had one saved before
       *    }
       * }
       *
       *
       * dispatch.deliveries.create(sender, recipient, [parcel], options).then((response) => {
       *    const delivery = response.data
       *    console.log(delivery.metadata)
       *
       *    //handle post delivery creation operations...
       * }).catch((err) => {
       *    console.error(err)
       *
       *    //handle errors...
       * })
       *
       */
      create: function (sender, recipient, parcels, options) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          createDelivery(sender, recipient, parcels, options, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },

      /**
       * Purchased a shipping label
       * @memberof Dispatch.deliveries
       * @namespace Dispatch.deliveries.buy
       *
       * @method buy
       * @param {string} delivery_id - The ID of the delivery for which you want to purchase a rate.
       * @param {string} rate_id - The ID of the rate tha you wish to purchase.
       * @param {Object} [options] - Additional options you want to add while purchasing this rate.
       * @param {string} [options.payment_method] - The ID of the payment method you wish to use. We'll use the default card you have on file otherwise.
       * @param {Integer} [options.metadata] - You can add metadata as key-value pairs to a delivery. To remove a property, pass `null` as the value. If you want to remove all key value pairs, pass an empty object.
       * @returns {Promise<Response>} Returns the response object. The Response's [data property]{@link Delivery} will be an array of {@link Delivery} objects.
       *
       * @example
       *
       * //assuming we already created the delivery, we have access to the rates array, if any were returned
       * //we can pass back the id of the rate that we want to purchase the delivery
       *
       * const delivery = response.data
       * const rate = delivery.rates[0].id //selected the first rate
       * const response = await dispatch.deliveries.buy(delivery.id, rate.id)
       *
       * //if the purchase was successful, the purchased rate will be available on the purchased_rate property
       * const purchasedRate = response.data.purchased_rate
       */
      buy: function (delivery_id, rate_id, options = {}) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          purchaseDelivery(delivery_id, rate_id, options, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },

      /**
       * Refund a shipping label that you have already purchased
       * @memberof Dispatch.deliveries
       * @namespace Dispatch.deliveries.refund
       *
       * @method refund
       * @param {string} delivery_id - The ID of the delivery that you want to refund.
       * @returns {Promise<Response>} Returns the response object.
       *
       * @example
       *
       * //a refund can only be done on a purchased label that has not been used
       * //refunds for on demand couriers need to happen within 5 minutes
       *
       * const response = await dispatch.deliveries.refund("del_28374n8iudshf3nqifub")
       */

      refund: function (delivery_id) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          refundDelivery(delivery_id, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },

      /**
       * Update a delivery
       * @memberof Dispatch.deliveries
       * @namespace Dispatch.deliveries.update
       *
       * @method update
       * @param {string} delivery_id - The ID of the delivery you want to update
       * @param {Object} [update] - An object of the fields you want to update
       * @param {Object} [update.sender] - The details about there this package is coming from.
       * @param {string} [update.sender.name] - The name of the sender. This could be a company name or a person's name.
       * @param {string} [update.sender.email] - The email of the sender. For on demand deliveries, this email will be used by the courier to contact the sender in case of any issues.
       * @param {string} [update.sender.phone] - The phone number of this sender that an on demand courier could use to contact this sender if there is an issue.
       * @param {Object} [update.recipient] - The details about there this package is coming from.
       * @param {string} [update.recipient.name] - The name of the sender. This could be a company name or a person's name.
       * @param {string} [update.recipient.email] - The email of the sender. For on demand deliveries, this email will be used by the courier to contact the sender in case of any issues.
       * @param {string} [update.recipient.phone] - The phone number of this recipient that an on demand courier could use to contact this recipient if there is an issue.
       * @param {Object} [update.options] - Additional options to include in your delivery.
       * @param {Object} [update.options.metadata] - You can add metadata as key-value pairs to a delivery. To remove a property, pass `null` as the value. If you want to remove all key value pairs, pass an empty object.
       * @returns {Promise<Response>} Returns the response object.
       *
       * @example
       *
       * // you can update emails, names, phone numbers, and metadata for the delivery
       * // if you want to update the delivery address you will have to create a new delivery.
       *
       * const update = {
       *    sender: {
       *       name: "Dispatch Brewery",
       *       email: "brewery@getdispatch.app",
       *       phone: "1234567890"
       *    },
       *    recipient: {
       *       phone: "1234567890" //only want to update the phone number for the recipient
       *    },
       *    options: {
       *       // Metadata is optional information that you can attach to a delivery
       *       metadata: {
       *          timestamp: new Date(Date.now()),
       *          updated_by: "Server Admin"
       *       }
       *    }
       * }
       *
       * const response = await dispatch.deliveries.update("del_28374n8iudshf3nqifub", update)
       */
      update: function (delivery_id, update) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          updateDelivery(delivery_id, update, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },
    };

    /**
     *
     * @memberof Dispatch
     * @namespace locations
     */
    this.locations = {
      /**
       * Retrieves a location using its ID
       * @memberof Dispatch.locations
       * @namespace Dispatch.locations.retrieve
       *
       * @method retrieve
       * @param {string} id - The ID of the location that you want to retrieve
       * @returns {Promise<Response>} Returns the response object. The Response's [data property]{@link Location} will be an array of {@link Location} objects.
       *
       * @example const response = await dispatch.locations.retrieve("loc_fjdsklfju8jisjfdisoiu89j")
       * const delivery = response.data //this will contain the location object
       */
      retrieve: function (id) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          retrieveLocation(id, _config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },
    };

    /**
     *
     * @memberof Dispatch
     * @namespace profile
     */
    this.profile = {
      /**
       * Retrieves the sender profile
       * @memberof Dispatch.profile
       * @namespace Dispatch.profile.retrieve
       *
       * @method retrieve
       * @returns {Promise<Response>} Returns the response object. The Response's [data property]{@link Profile} will be an array of {@link Profile} objects.
       *
       * @example const response = await dispatch.profile.retrieve()
       * const profile = response.data //this will contain the profile object
       */
      retrieve: function (id) {
        return new Promise((resolve, reject) => {
          const _config = _createNetworkConfig(apikey, env);
          retrieveProfile(_config)
            .then((data) => {
              resolve(data);
            })
            .catch((err) => {
              console.error(err);
              reject(err);
            });
        });
      },
    };
  }
};

/* -------------------------------------------------------------------------- */
/*                                  TYPE DEFS                                 */
/* -------------------------------------------------------------------------- */

/**
 * The Delivery object. Any of the properties could have null values if the delivery is not purchased.
 * @typedef {Object} Delivery
 * @property {string} id - The delivery ID
 * @property {integer} amount - The price of this rate as an integer with discount applied. (e.g., $15.76 would be represented as 1576).
 * @property {integer} billed_amount - The price of this rate as an integer without discounts applied. (e.g., $15.76 would be represented as 1576). This is the total amount that Dispatch charged your payment information in file.
 * @property {integer} sender_discount - The discount for this rate as an integer that you have specified. (e.g., $15.76 would be represented as 1576). This gets calculated based on your settings on the Dispatch dashboard.
 * @property {Object} branding - Specified the branding for this delivery.
 * @property {integer} branding.email - If an email will be sent by Dispatch, this determines which logo will be on the email.
 * @property {integer} branding.label - Which logo should be placed on the label.
 * @property {Object} courier - The courier object if the delivery is on demand. This will be deprecated in the future as the same data is found in the Provider object that is attached to the Rate.
 * @property {integer} created_at - Epoch time in seconds when this delivery was created.
 * @todo {Object} customs_declaration - Any customs declarations for international shipping.
 * @property {string} estimated_delivery - A human readable string value for the estimated delivery date and time.
 * @property {Object} grace_period -The grace period that an on_demand courier will wait for a delivery. If the sender is not ready, the grace period object explains the fees that will be incurred.
 * @property {integer} grace_period.billed_amount - The amount as an integer that this delivery was billed for in the event of a grace period violation.
 * @property {integer} grace_period.fee - The grace period fee as an integer This it the fee that is charged per minute.
 * @property {integer} grace_period.minutes - The amount of minutes that the grace period is good for.
 * @property {(string|null)} grace_period.payment_status - This specifies the status of the payment that was collected
 * @property {(integer|null)} grace_period.wait_seconds - This is the duration in seconds that the courier waited for the delivery.
 * @todo {Object} insurance - The object representing the insurance.
 * @property {string} intent_status - The status of the delivery intent. An intent can be "created" when rates were generated but not purchased yet, "expired" if the intent was not captured within 15 mins, "captured" which means that the intent was paid for, and "deleted" which is when the intent was removed from the database.
 * @property {string} label_name - The name of the shipping label as saved in the storage bucket. @deprecated This property will be removed.
 * @property {string} label_url - The url from which you can download your label. This URL, can be accessed for 48 hours until it expires. Each time that you retrieve a delivery, a new label url is generated for you.
 * @property {integer} lead_time_hours - The amount of lead time that was required for this delivery before an on_demand courier can pick it up.
 * @property {Array} live_location - The lat and lon coordinates of the the current location of the delivery. Not every courier supports this.
 * @property {Object} metadata - Key-value pairs of data that you have added to the delivery. When creating or purchasing a delivery, metadata can be passed in the options. You should never store sensitive information in key value pairs. Good uses for metadata would be to store an order ID or a customer ID from your database.
 * @property {Boolean} on_demand - If this delivery is for an on_demand courier.
 * @property {Boolean} paid - If this delivery was paid for.
 * @property {Array<Parcel>} parcels - An array of parcel objects, which are the boxes and items that were being transported.
 * @property {Object<Rate>} purchased_rate - The rate that was purchased by the customer.
 * @property {string} qr_code_url - If the label has a QR Code, this will be the url that is encoded on it.
 * @property {Array<Rate>} rates - An array of rates that are returned when the delivery intent was created.
 * @property {Object<Entity>} recipient - The recipient object. This is the person who is getting the package.
 * @property {string} refund_status - The refund status if one was requested. Funds will be credited back to the account after the refund status is approved by the carrier. Dispatch couriers refunds are immediate.
 * @property {Object<Entity>} sender - The object representing the sender, which is the entity that initially sent that package.
 * @property {integer} shipment_date - The time in seconds from Epoch in seconds of the shipment date.
 * @property {string} status - The tracking status for the delivery. For a complete list see the github readme.
 * @property {string} substatus - The tracking substatus for the delivery. This gives much more detail about the package whereabouts. For a complete list see the github readme.
 * @property {boolean} test - If this was a test delivery.
 * @property {boolean} tracking_notifications - Indicates if dispatch will send update emails for the delivery. This value is set on your dashboard {@link https://app.getdispatch.app/settings/company/branding}.
 * @property {string} tracking_number - The tracking number for the delivery.
 * @property {Object<Tracker>} tracking_status - The current tracking status for this delivery.
 * @property {Array<Tracker>} tracking_updates - An array of all of the tracking updates for this delivery including the current one.
 * @property {string} type - The type of delivery this is: "traditional" or "marketplace".
 * @property {integer} updated_at - Epoch time in seconds.
 * @property {integer} value - The declared value of this delivery.
 */

/**
 * The Entity object, which describes a company or person
 * @typedef {Object} Entity
 * @property {string} id - The entity ID
 * @property {Object} address - The address details of this entity.
 * @property {string} address.address_line1
 * @property {string} address.address_line2
 * @property {string} address.city
 * @property {string} address.formatted_address - The combined address string including city, state, and zipcode.
 * @property {string} address.place_name - In most cases this is the same as the city. For U.S. shipment, just ignore this.
 * @property {string} address.state - The full string of the the state such as "California or New York".
 * @property {string} address.state_abbreviation - The abbreviation of the the state such as "CA or "NY".
 * @property {string} address.state_name - @deprecated This is now just called state.
 * @property {string} address.street_name - The name of the street from address_line1.
 * @property {string} address.street_number - The number of the street from address_line1.
 * @property {string} address.street_suffix - Will we the last part of the street name like "St" or "Ln".
 * @property {string} address.textarea - If you will pre-fill an html textarea with the string, this includes the return values for the address to format into multiple lines.
 * @property {string} address.timezone - The tz format for this addresses timezone. {@link https://en.wikipedia.org/wiki/Tz_database}
 * @property {boolean} address.verified - If this address was verified with USPS.
 * @property {string} address.zipcode - The address zipcode. This is the same value as postal_code.
 * @property {string} email - The email address to contact this entity.
 * @property {string} name - The name of this entity.
 * @property {(string|null)} phone - The phone number to contact this entity.
 * @property {(string|null)} logo_url - The source for the logo. The image is a 256 x 256 square png.
 * @property {(string|null)} logo_url_trimmed - This logo is trimmed by us to remove the white space. Best used in emails. One of the sides is 256px, depending on the logo's shape.
 */

/**
 * The Rate object
 * @typedef {Object} Rate
 * @property {integer} amount - The price of this rate as an integer with discount applied. (e.g., $15.76 would be represented as 1576).
 * @property {integer} billed_amount - The price of this rate as an integer without discounts applied. (e.g., $15.76 would be represented as 1576). This is the total amount that Dispatch charged your payment information in file.
 * @property {integer} sender_discount - The discount for this rate as an integer that you have specified. (e.g., $15.76 would be represented as 1576). This gets calculated based on your settings on the Dispatch dashboard.
 * @property {(string|null)} carrier_account - The carrier account / custom rate card that was used to price this rate.
 * @property {integer} checkout_total - The total cart/checkout value you submitted as an integer (e.g., $15.76 would be represented as 1576). This value is used to determine the free shipping tier that you can set up on the Dispatch dashboard.
 * @property {integer} created_at - Epoch time in seconds.
 * @property {string} currency - The currency of this rate card as lowercase ISO 4217 format {@link https://en.wikipedia.org/wiki/ISO_4217}
 * @property {boolean} dispatch - If this rate was originated by dispatch APIs.
 * @property {Object} service_level - Describes how long the delivery will take.
 * @property {(string)} service_level.id - The ID of the service level. Something like "dispatch_same_day".
 * @property {(string)} service_level.name - The human readable name of the service level. Something like "Same Day" or "USPS Overnight".
 * @property {integer} service_level.arrives_by - Epoch time seconds when this delivery is expected to arrive at its destination.
 * @property {integer} service_level.days - The amount of days that this delivery is estimated to take.
 * @property {boolean} service_level.guaranteed - If this delivery is guaranteed by the `arrives_by` time
 * @property {(integer|null)} service_level.pickup_at - Epoch time in seconds when this order will be picked up.
 * @property {(string)} service_level.terms - The human readable string for the delivery date and time. For example: "Today by 9pm".
 * @property {Object} grace_period - The grace period that an on_demand courier will wait for and the fees for going over it.
 * @property {integer} grace_period.billed_amount - The amount that you were charged for going over a courier's grace period.
 * @property {integer|null} grace_period.fee - The amount that you were charged for going over a courier's grace period.
 * @property {integer|null} grace_period.minutes - The amount of minutes that the grace period is good for.
 * @property {integer|null} grace_period.payment_status - The status of your payment.
 * @property {integer|null} grace_period.wait_seconds - The amount of seconds the courier waited for.
 * @property {string} id - the id of this rate. This id will be passed to dispatch to purchase the rate.
 * @property {(Object|null)} invoice - If the rate is generated by an on demand courier from dispatch, this will be a breakdown of the total cost.  Otherwise will be null.
 * @property {integer} invoice.additional_items_fee - The cost for additional items if the order contained multiple packages and the courier changes this fee.
 * @property {integer} invoice.dropoff_fee - The fixed dropoff fee that this courier charges.
 * @property {integer} invoice.dropoff_rate - The rate this courier charges for the distance from pickup location to dropoff location.
 * @property {integer} invoice.local_fee - If there are any local fees that are charged in the pickup or dropoff city.
 * @property {integer} invoice.pickup_fee - The fixed pickup fee that this courier charges.
 * @property {integer} invoice.pickup_rate - The rate this courier charges for the distance from to get to the pickup location.
 * @property {(string|null)} invoice.rate_card - The id of the rate card that was used for this invoice.
 * @property {integer} invoice.subtotal - The total before taxes.
 * @property {integer} invoice.tax - The tax charged for this delivery.
 * @property {integer} invoice.toll - Any tolls that were charged for this delivery.
 * @property {integer} invoice.total - The final total for this invoice. This number is the same as the "amount".
 * @property {integer} lead_time_hours - The amount of hours that are needed in advance before the courier can get the the pickup destination.
 * @property {boolean} on_demand - If this rate is an on demand courier.
 * @property {integer} pickup_at - @deprecated Epoch time in seconds when this order will be picked up. Same as service_level.pickup_at.
 * @property {Object} provider - The provider is the courier or carrier that will be conducting the delivery.
 * @property {string} provider.id - The ID of this provider.
 * @property {string} provider.logo_url - The logo that of this provider.
 * @property {string} provider.name - The name of this provider.
 * @property {string} provider.support_email - The email that can be used to contact this provider.
 * @property {(string|null)} provider.support_phone - The support phone number that can be used to contact this provider.
 * @property {(string|null)} provider.support_url - The url that this provider has for support.
 * @property {boolean} test - If this was a test delivery or not.
 */

/**
 * The Response Object. Every dispatch response will always have the same object that is returned.
 * @typedef {Object} Response
 * @property {string} message - The message that could be displayed to an end user if the response is successful or ends in an error.
 * @property {(Object|Array)} data - The data that was requested if any. If requesting lots of data like deliveries, the data will be formatted an an Array. If you're just pulling one item by an ID like a specific delivery, the response will be an Object.
 * @property {integer} status - The html status code for the response.
 * @property {Array} errors - If there were errors, the array will be filled with the property names that caused the error.
 * @property {(string|null)} error_code - The server error code.
 * @property {(Object|null)} pagination - when pulling multiple object like many deliveries, the pagination will let you know if there are more items that can be pulled from the database.
 * @property {integer} pagination.limit - the limit that was applied to the pagination. The default is 15 and the max is 100.
 * @property {integer} pagination.current_page - The current page this pagination is on. If the limit is 15 and the current_page is 3, you know you're looking at items 30 - 45.
 * @property {integer} pagination.has_more - Lets you know when you can paginate further.
 * @property {integer} pagination.count - The amount of items that were returned.
 */

/**
 * The New Address Object. When creating a new address, you can either send the address as a string value or an object. If you're choosing an object, below are the properties you need to provide.
 * @typedef {Object} NewAddress
 * @property {string} address_line1 - The street address for this delivery.
 * @property {string} [address_line2] - The second line of the street address if needed.
 * @property {string} city - The name of the city.
 * @property {string} state - The state. This can be the full state name like California or an abbreviation like NY.
 * @property {string} zipcode - The zipcode. Technically this is optional but highly recommended you add this because it makes the address parser much more accurate.
 */

/**
 * The Parcel Object. When you create a parcel or retrieve a delivery, you'll always be referencing an array of parcels
 * @typedef {Object} Parcel
 * @property {String} [package_type] - The type of box you're sending the items in. If you are using a box provided by a carrier, you'll only recieve rates from that carrier plus any on-demand couriers, if avaible.
 * @property {integer} length - The length of the parcel in inches.
 * @property {integer} width - The width of the parcel in inches.
 * @property {integer} height - The height of the parcel in inches.
 * @property {integer} weight - The weight of the parcel in pounds.
 * @property {string} [special_handling] - Any special handling instructions that will be placed on the label. Limited to 12 characters. If you add more than 12 characters, we'll just use the first 12 instead of returning an error. The reason for the limit is that this is the most amount of characters that we can fit within the bounds of the current label.
 * @property {string} [item_description] - A description of what you're sending like "Coffee". This can prove useful for basic analytics later on and is a nice touch for the tracking email that can let the recipient know what is in the box.
 * @property {Array<Item>} [items] - you can optionally include items that are in the box. This can be used for one click returns and custom disposition codes in the future.
 */

/**
 * The Item Object. This is optional but allows you to specify what the items are that are packaged in your box. In the future, this will be used to help facilitate one-click returns.
 * @typedef {Object} Item
 * @property {string} [name] - The name of this item.
 * @property {string} [sku] - The item sku.
 * @property {integer} [price] - The item's price as an integer.
 * @property {integer} [value] - The item's declared values as an integer.
 * @property {string} [product_id] - The id used to identify this product on your inventory system.
 * @property {string} [variant_id] - If this is a specific variant of a product id.
 * @property {integer} [length] - The length of the item in inches. Can use this for cheaper return labels if we know the box can be smaller.
 * @property {integer} [width] - The width of the item in inches. Can use this for cheaper return labels if we know the box can be smaller.
 * @property {integer} [height] - The height of the item in inches. Can use this for cheaper return labels if we know the box can be smaller.
 * @property {integer} [weight] - The weight of the item in pounds. Can use this for cheaper return labels if we know the box can be lighter.
 */

/**
 * The Tracker Object. This describes a tracking update.
 * @typedef {Object} Tracker
 * @property {Object} address - This is a basic address field that gives the general location of the item.
 * @property {(String|null)} address.address_line1 - The street address. Many carriers do not support this field and it can often be null.
 * @property {String} address.city - Name of the city.
 * @property {String} address.state - Name of the state, not abbreviated.
 * @property {String} address.zipcode - The zipcode.
 * @property {(String|null)} comment - If the courier added a comment for this update it will be here. These comments are not filtered by Dispatch at the moment, so it's safer to use the `message` property for customer notifications.
 * @property {String} message - The human readable message about this status given by Dispatch.
 * @property {String} status - The status string.
 * @property {String} substatus - The sub_status string.
 * @property {Array<(String)>} images - An array that includes any images that were added to this tracker. If there are no images, the array will be empty.
 */

/**
 * The Profile Object. This describes the profile of the sender who owns the API key
 * @typedef {Object} Profile
 * @property {String} id - The ID for this sender
 * @property {Object} branding - This describes how branding is used by the user
 * @property {Boolean} branding.emails - If this sender has their logo displayed on email. Requires a Pro plan
 * @property {Boolean} branding.labels - If this sender has their logo displayed on shipping labels. Requires a Pro plan
 * @property {Boolean} branding.tracking_notifications - If this sender wants dispatch to send tracking updates to recipients
 * @property {Integer} lead_time_hours - The lead time this sender requires for deliveries
 * @property {Array.<Object>} carrier_rate_card - An array of objects that describe the rate cards this user has
 * @property {String} carrier_rate_card[].carrier_id - The ID of the carrier this rate card is for
 * @property {Boolean} carrier_rate_card[].active - If this rate card is currently active
 * @property {String|null} carrier_rate_card[].rate_card_id - The ID of the rate card. The value is null if this rate card is for a Dispatch provided rate card
 * @property {String} logo_url - the logo url for the sender
 * @property {String} logo_url_trimmed - the logo url for the sender with the wight space trimmed
 * @property {Object} requirements - Shows which requirements are needed for this sender. Some features may be unavaible if there are outstanding requirements
 * @property {Array.<String>} requirements.required_now - A list of all of the requirements that are due now. No deliveries can be created if there are requirements due
 * @property {Array.<String>} requirements.pending_verification - A list of requirements that are pending verification. These are normally resolved within 24 hours
 * @property {Array.<String>} requirements.errors - These are errors that the account has. Accounts with errors could result in features of the account being disabled, such as the ability to purchase shipping labels
 * @property {Array.<String>} requirements.required_later - These are items that will be due in the future.
 * @property {Object} profile = An object that reflects the profile information for this sender
 * @property {String} profile.support_phone - The phone number for this sender to be contacted for support
 * @property {String} profile.support_email - The email for this sender to be contacted for support
 * @property {String} profile.name - The name of this sender
 * @property {String} profile.website - The website for this sender
 * @property {Object.<Address>} profile.address - The headquarters address for the sender.
 * @property {Integer} created_at - The time in seconds from Epoch that this sender was created
 * @property {Integer} updated_at - The time in seconds from Epoch that this sender was last updated
 * @property {Object} labels - The preferences this user has for shipping labels
 * @property {String} labels.format - The format the labels will come in for the sender.
 */

/**
 * The Address Object
 * @typedef {Object} Address
 * @property {String} street_number
 * @property {String} state
 * @property {String} city
 * @property {String} street_name
 * @property {String} state_name - The same as state
 * @property {String} postal_code - the same as zip code but more common name in other countires
 * @property {String} timezone
 * @property {String} street_suffix - the street suffix such as "Dr" of "St"
 * @property {String} state_abbreviation
 * @property {String} address_line1
 * @property {(String|null)} address_line2
 * @property {String} zipcode
 * @property {Boolean} verified - If this address has been verified by USPS
 * @property {String} formatted_address - The full string of the address
 * @property {String} textarea - The formatted address with "\r" breaks for it to be formatted nicely if you render it into a textarea
 * @property {String} place_name - The same as the city field
 */