EasyPost / easypost-node

EasyPost Shipping API Client Library for Node
https://easypost.com/docs/api
MIT License
139 stars 54 forks source link

has_more data structure doesn't match documentation #195

Closed asbaca93 closed 2 years ago

asbaca93 commented 2 years ago

When running the retrieve a list of shipments path, the response format I receive doesn't match the format of the documentation. In the docs, an object is returned with a has_more key value pair and a shipments key value pair, however, when ran with the NodeJS Easypost SDK, I receive an array with the has_more as an index in the array.

https://www.easypost.com/docs/api/node#retrieve-a-list-of-shipments

Example response:

[
  {
    _validationErrors: null,
    created_at: '2021-12-08T15:53:32Z',
    is_return: false,
    messages: [],
    mode: 'test',
    options: { currency: 'USD', payment: [Object], date_advance: 0 },
    reference: null,
    status: 'unknown',
    tracking_code: null,
    updated_at: '2021-12-08T15:53:32Z',
    batch_id: null,
    batch_status: null,
    batch_message: null,
    customs_info: null,
    from_address: {
      id: 'adr_fe6332a2583e11ec83baac1f6bc7b362',
      object: 'Address',
      created_at: '2021-12-08T15:53:32+00:00',
      updated_at: '2021-12-08T15:53:32+00:00',
      name: null,
      company: null,
      street1: '',
      street2: '',
      city: '',
      state: 'NM',
      zip: '88012',
      country: 'US',
      phone: null,
      email: null,
      mode: 'test',
      carrier_facility: null,
      residential: null,
      federal_tax_id: null,
      state_tax_id: null,
      verifications: {}
    },
    insurance: null,
    order_id: null,
    parcel: {
      id: 'prcl_56010755a5e1432489d918135dcfd3a0',
      object: 'Parcel',
      created_at: '2021-12-08T15:53:32Z',
      updated_at: '2021-12-08T15:53:32Z',
      length: 10,
      width: 10,
      height: 10,
      predefined_package: null,
      weight: 10,
      mode: 'test'
    },
    postage_label: null,
    rates: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object]
    ],
    refund_status: null,
    scan_form: null,
    selected_rate: null,
    tracker: null,
    to_address: {
      id: 'adr_fe6147ac583e11ec83b9ac1f6bc7b362',
      object: 'Address',
      created_at: '2021-12-08T15:53:32+00:00',
      updated_at: '2021-12-08T15:53:32+00:00',
      name: null,
      company: null,
      street1: '',
      street2: null,
      city: '',
      state: 'NM',
      zip: '88005',
      country: 'US',
      phone: null,
      email: null,
      mode: 'test',
      carrier_facility: null,
      residential: null,
      federal_tax_id: null,
      state_tax_id: null,
      verifications: {}
    },
    usps_zone: 1,
    return_address: {
      id: 'adr_fe6332a2583e11ec83baac1f6bc7b362',
      object: 'Address',
      created_at: '2021-12-08T15:53:32+00:00',
      updated_at: '2021-12-08T15:53:32+00:00',
      name: null,
      company: null,
      street1: '',
      street2: '',
      city: 'Las Cruces',
      state: 'NM',
      zip: '88012',
      country: 'US',
      phone: null,
      email: null,
      mode: 'test',
      carrier_facility: null,
      residential: null,
      federal_tax_id: null,
      state_tax_id: null,
      verifications: {}
    },
    buyer_address: {
      id: 'adr_fe6147ac583e11ec83b9ac1f6bc7b362',
      object: 'Address',
      created_at: '2021-12-08T15:53:32+00:00',
      updated_at: '2021-12-08T15:53:32+00:00',
      name: null,
      company: null,
      street1: '',
      street2: null,
      city: 'Las cruces',
      state: 'NM',
      zip: '88005',
      country: 'US',
      phone: null,
      email: null,
      mode: 'test',
      carrier_facility: null,
      residential: null,
      federal_tax_id: null,
      state_tax_id: null,
      verifications: {}
    },
    forms: [],
    fees: [],
    id: 'shp_90ad4c50583c4a619d8f8642e342c0da',
    object: 'Shipment'
  },
  has_more: true
]
Justintime50 commented 2 years ago

Can you provide a shipment ID that is affected that we could check out?

asbaca93 commented 2 years ago

here is a shipment id: shp_90ad4c50583c4a619d8f8642e342c0da

This response is from the get all method:

const result = await api.Shipment.all({
      purchased: purchased ?? false,
      page_size: pageSize ?? 20,
      before_id: lastId,
});
Justintime50 commented 2 years ago

Oh my apologies, I misread. This is related to the /all shipment endpoint and not a single shipment.

I'm seeing that the has_more key in your example above is returned as it should be. You specified a page_size of 1 so only a single shipment was returned, with the has_more key inferring there are more shipments in total. To get those shipments, you'll need to change the page you're on.

Can you elaborate on the problem at hand? Based on your example and our docs, they are consistent and correct.

asbaca93 commented 2 years ago

the documentation states that the payload structure is an object, however I got an array as a response. I agree with you about the page size. The issue is the data structure, not the data itself. This is the example given on the documentation:

{
  "has_more": true,
  "shipments": [
    {
      "batch_id": null,
      "batch_message": null,
      "batch_status": null,
      "buyer_address": {
        ...
      },
      "created_at": "2016-11-28T20:03:25Z",
      "customs_info": null,
      "fees": [
        {
          "amount": "0.00000",
          "charged": true,
          "object": "Fee",
          "refunded": false,
          "type": "LabelFee"
        },
        {
          "amount": "2.60000",
          "charged": true,
          "object": "Fee",
          "refunded": false,
          "type": "PostageFee"
        }
      ],
      "forms": [],
      "from_address": {
        ...
      },
      "id": "shp_...",
      "insurance": null,
      "is_return": false,
      "messages": [],
      "mode": "production",
      "object": "Shipment",
      "options": {
        "currency": "USD",
        "date_advance": 0,
        "label_date": null,
        "label_format": "ZPL",
        "special_rates_eligibility": "USPS.MEDIAMAIL"
      },
      "parcel": {
        ...
      },
      "postage_label": {
        "created_at": "2016-11-28T20:04:42Z",
        "date_advance": 0,
        "id": "pl_...",
        "integrated_form": "none",
        "label_date": "2016-11-28T20:04:42Z",
        "label_epl2_url": null,
        "label_file": null,
        "label_file_type": "application/zpl",
        "label_pdf_url": null,
        "label_resolution": 203,
        "label_size": "4x6",
        "label_type": "default",
        "label_url": "https://easypost-files.s3-us-west-2.amazonaws.com/files/postage_label/20161128/9zdb0ccd6009418fa12f93794f8177df.zpl",
        "label_zpl_url": "https://easypost-files.s3-us-west-2.amazonaws.com/files/postage_label/20161128/9bdb0ccd6909418fa12f93794f8177df.zpl",
        "object": "PostageLabel",
        "updated_at": "2016-11-28T20:04:42Z"
      },
      "rates": [
        { ... },
        { ... }
      ],
      "reference": null,
      "refund_status": null,
      "return_address": {
        ...
      },
      "scan_form": null,
      "selected_rate": {
        ...
      },
      "status": "pre_transit",
      "to_address": {
        ...
      },
      "tracker": {
        ...
      },
      "tracking_code": "9400110896700986051652",
      "updated_at": "2016-11-29T03:25:18Z",
      "usps_zone": 8
    },
    {
      "id": "shp_..."
    }
  ]
}

This is an object with a has_more key and a shipment key. In my example response above (the direct response from the Shipment.all() call), I receive an array with a has_more index and a boolean value.

Justintime50 commented 2 years ago

I was able to recreate what you are seeing - it doesn't match after all. Thanks for reporting this! We'll do some digging into why this is the way it is and look at correcting if necessary. I will mention this may not be related solely to the shipments endpoint and may affect other all methods in this library. Changing its behavior if true would be a breaking change (probably for the better though). I'll update this thread when I know more.

Justintime50 commented 2 years ago

We are unwrapping the response here: https://github.com/EasyPost/easypost-node/blob/86d5c2faf3da89e080cb08e974e24c18ba0f9409/src/resources/base.js#L27

Changing this to const result = res.body seems to be a quick fix, continuing to investigate.

asbaca93 commented 2 years ago

Great, thanks for your help.