diff --git a/event.go b/event.go new file mode 100644 index 0000000..a91e11f --- /dev/null +++ b/event.go @@ -0,0 +1,147 @@ +package easypost + +import ( + "context" + "encoding/base64" + "encoding/json" + "net/http" + "time" +) + +// Event objects contain details about changes to EasyPost objects +type Event struct { + ID string `json:"id,omitempty"` + UserID string `json:"user_id,omitempty"` + Object string `json:"object,omitempty"` + Mode string `json:"mode,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Description string `json:"description,omitempty"` + PreviousAttributes map[string]interface{} `json:"previous_attributes,omitempty"` + // Result will be populated with the relevant object type, i.e. + // *Batch, *Insurance, *PaymentLog, *Refund, *Report, *Tracker or *ScanForm. + // It will be nil if no 'result' field is present, which is the case for + // the ListEvents and GetEvents methods. The RequestBody field of the + // EventPayload type will generally be an instance of *Event with this field + // present. Having the field here also enables re-using this type to + // implement a webhook handler. + Result interface{} `json:"result,omitempty"` + Status string `json:"status,omitempty"` + PendingURLs []string `json:"pending_urls,omitempty"` + CompletedURLs []string `json:"completed_urls,omitempty"` +} + +func (e *Event) UnmarshalJSON(data []byte) (err error) { + var buf json.RawMessage + event := Event{Result: &buf} + + type nonUnmarshaler *Event + if err = json.Unmarshal(data, nonUnmarshaler(&event)); err != nil { + return err + } + + if event.Result, err = UnmarshalJSONObject(buf); err == nil { + *e = event + } + + return err +} + +// EventPayload represents the result of a webhook call. +type EventPayload struct { + ID string `json:"id,omitempty"` + Object string `json:"object,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + RequestURL string `json:"request_url,omitempty"` + RequestHeaders map[string]string `json:"request_headers,omitempty"` + // RequestBody is the raw request body that was sent to the webhook. This is + // expected to be an Event object. It may either be encoded in the API + // response as a string (with JSON delimiters escaped) or as base64. The + // UnmarshalJSON method will attempt to convert it to an *Event type, but it + // may be set to a default type if decoding to an object fails. + RequestBody interface{} `json:"request_body,omitempty"` + ResponseHeaders map[string]string `json:"response_headers,omitempty"` + ResponseBody string `json:"response_body,omitempty"` + ResponseCode int `json:"response_code,omitempty"` + TotalTime int `json:"total_time,omitempty"` +} + +func (e *EventPayload) UnmarshalJSON(data []byte) (err error) { + var s string + payload := EventPayload{RequestBody: &s} + + type nonUnmarshaler *EventPayload + if err = json.Unmarshal(data, nonUnmarshaler(&payload)); err != nil { + return err + } + + // Attempt to base64 decode the body. Ignore errors. + if buf, err := base64.StdEncoding.DecodeString(s); err == nil { + s = string(buf) + } + + // try to decode RequestBody to an object, but if we can't, then just + // set it to the string. + if payload.RequestBody, err = UnmarshalJSONObject([]byte(s)); err != nil { + payload.RequestBody = s + } + + *e = payload + return nil +} + +// ListEventsResult holds the results from the list events API. +type ListEventsResult struct { + Events []*Event `json:"events,omitempty"` + // HasMore indicates if there are more responses to be fetched. If True, + // additional responses can be fetched by updating the ListEventsOptions + // parameter's AfterID field with the ID of the last item in this object's + // Events field. + HasMore bool `json:"has_more,omitempty"` +} + +// ListEvents provides a paginated result of Event objects. +func (c *Client) ListEvents(opts *ListOptions) (out *ListEventsResult, err error) { + return c.ListEventsWithContext(nil, opts) +} + +// ListEventsWithContext performs the same operation as ListEventes, but +// allows specifying a context that can interrupt the request. +func (c *Client) ListEventsWithContext(ctx context.Context, opts *ListOptions) (out *ListEventsResult, err error) { + err = c.do(ctx, http.MethodGet, "events", c.convertOptsToURLValues(opts), &out) + return +} + +// GetEvent retrieves a previously-created event by its ID. +func (c *Client) GetEvent(eventID string) (out *Event, err error) { + err = c.get(nil, "events/"+eventID, &out) + return +} + +// GetEventWithContext performs the same operation as GetEvent, but allows +// specifying a context that can interrupt the request. +func (c *Client) GetEventWithContext(ctx context.Context, eventID string) (out *Event, err error) { + err = c.get(ctx, "events/"+eventID, &out) + return +} + +type listEventPayloadsResult struct { + Payloads *[]*EventPayload `json:"payloads,omitempty"` +} + +// GetEventPayload retrieves the payload results of a previous webhook call. +func (c *Client) ListEventPayloads(eventID string) (out []*EventPayload, err error) { + return c.ListEventPayloadsWithContext(nil, eventID) +} + +// GetEventPayloadWithContext performs the same operation as GetEventPaylod, but +// allows specifying a context that can interrupt the request. +func (c *Client) ListEventPayloadsWithContext(ctx context.Context, eventID string) (out []*EventPayload, err error) { + err = c.get( + ctx, + "events/"+eventID+"/payloads", + &listEventPayloadsResult{Payloads: &out}, + ) + return +} diff --git a/examples/events/retrieve_all/retrieve_events.go b/examples/events/retrieve_all/retrieve_events.go new file mode 100644 index 0000000..4cfde82 --- /dev/null +++ b/examples/events/retrieve_all/retrieve_events.go @@ -0,0 +1,54 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "time" + + "github.com/EasyPost/easypost-go" +) + +func main() { + apiKey := os.Getenv("EASYPOST_API_KEY") + if apiKey == "" { + fmt.Fprintln(os.Stderr, "missing API key") + os.Exit(1) + return + } + client := easypost.New(apiKey) + + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + + // Retrieve events from the past day. + yesterday := time.Now().Add(-24 * time.Hour) + opts := &easypost.ListOptions{StartDateTime: &yesterday} + + results, err := &easypost.ListEventsResult{HasMore: true}, error(nil) + for results.HasMore && err == nil { + if results, err = client.ListEvents(opts); err == nil { + for i := range results.Events { + enc.Encode(results.Events[i]) + // If a webhook is registered, payloads can be examined to + // obtain the event result. + payloads, _ := client.ListEventPayloads(results.Events[i].ID) + if len(payloads) != 0 { + event, _ := payloads[0].RequestBody.(*easypost.Event) + if event != nil { + enc.Encode(event.Result) + } + } + } + if results.HasMore { + // Update BeforeID in order to fetch additional pages. + opts.BeforeID = results.Events[len(results.Events)-1].ID + } + } + } + + if err != nil { + fmt.Fprintln(os.Stderr, "error retrieving events:", err) + os.Exit(1) + } +} diff --git a/examples/webhooks/handler/webhook_handler.go b/examples/webhooks/handler/webhook_handler.go new file mode 100644 index 0000000..3991a0c --- /dev/null +++ b/examples/webhooks/handler/webhook_handler.go @@ -0,0 +1,171 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "net/http" + "strings" + + "github.com/EasyPost/easypost-go" +) + +type Handler struct { + Username string + Password string +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if req.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + if h.Username != "" { + user, pass, ok := req.BasicAuth() + if !ok || user != h.Username || pass != h.Password { + w.WriteHeader(http.StatusUnauthorized) + return + } + } + + var event easypost.Event + if err := json.NewDecoder(req.Body).Decode(&event); err != nil { + w.WriteHeader(http.StatusBadRequest) + log.Println("failed decoding request:", err) + return + } + + switch event.Description { + case "batch.created", "batch.updated": + h.HandleBatchEvent(&event) + case "insurance.cancelled", "insurance.purchased": + h.HandleInsuranceEvent(&event) + case "payment.completed", "payment.created", "payment.failed": + h.HandlePaymentEvent(&event) + case "refund.successful": + h.HandleRefundEvent(&event) + case "report.available", "report.failed", "report.new": + h.HandleReportEvent(&event) + case "scan_form.created", "scan_form.updated": + h.HandleScanFormEvent(&event) + case "tracker.created", "tracker.updated": + h.HandleTrackerEvent(&event) + default: + log.Println("unrecognized event type:", event.Description) + } +} + +func (h *Handler) HandleBatchEvent(event *easypost.Event) { + batch, ok := event.Result.(*easypost.Batch) + if !ok { + log.Printf("unexpected result type for batch event: %T\n", event.Result) + return + } + verb := strings.TrimPrefix(event.Description, "batch.") + log.Printf( + "batch %s %s with %d shipments and status "+ + "(postage_purchased: %d, postage_purchase_failed: %d, "+ + "queued_for_purchase: %d, creation_failed: %d)\n", + batch.ID, verb, batch.NumShipments, batch.Status.PostagePurchased, + batch.Status.PostagePurchaseFailed, batch.Status.QueuedForPurchase, + batch.Status.CreationFailed, + ) +} + +func (h *Handler) HandleInsuranceEvent(event *easypost.Event) { + insurance, ok := event.Result.(*easypost.Insurance) + if !ok { + log.Printf( + "unexpected result type for insurance event: %T\n", event.Result, + ) + return + } + verb := strings.TrimPrefix(event.Description, "insurance.") + log.Printf( + "insurance %s %s of %s for shipment %s\n", + insurance.ID, verb, insurance.Amount, insurance.ShipmentID, + ) +} + +func (h *Handler) HandlePaymentEvent(event *easypost.Event) { + payment, ok := event.Result.(*easypost.PaymentLog) + if !ok { + log.Printf("unexpected result type for payment event: %T\n", event.Result) + return + } + verb := strings.TrimPrefix(event.Description, "payment.") + log.Printf( + "payment %s %s with amount %s and status %d\n", + payment.ID, verb, payment.Amount, payment.Status, + ) +} + +func (h *Handler) HandleRefundEvent(event *easypost.Event) { + refund, ok := event.Result.(*easypost.Refund) + if !ok { + log.Printf("unexpected result type for refund event: %T\n", event.Result) + return + } + verb := strings.TrimPrefix(event.Description, "refund.") + log.Printf( + "refund %s %s with status %s for shipment %s\n", + refund.ID, verb, refund.Status, refund.ShipmentID, + ) +} + +func (h *Handler) HandleReportEvent(event *easypost.Event) { + report, ok := event.Result.(*easypost.Report) + if !ok { + log.Printf("unexpected result type for report event: %T\n", event.Result) + return + } + verb := strings.TrimPrefix(event.Description, "report.") + log.Printf( + "report %s %s with status %s and URL %s\n", + report.ID, verb, report.Status, report.URL, + ) +} + +func (h *Handler) HandleScanFormEvent(event *easypost.Event) { + scanForm, ok := event.Result.(*easypost.ScanForm) + if !ok { + log.Printf("unexpected result type for batch event: %T\n", event.Result) + return + } + verb := strings.TrimPrefix(event.Description, "scan_form.") + log.Printf( + "scan form %s %s with status %s and tracking codes %s\n", + scanForm.ID, verb, scanForm.Status, + strings.Join(scanForm.TrackingCodes, ", "), + ) +} + +func (h *Handler) HandleTrackerEvent(event *easypost.Event) { + tracker, ok := event.Result.(*easypost.Tracker) + if !ok { + log.Printf("unexpected result type for tracker event: %T\n", event.Result) + return + } + verb := strings.TrimPrefix(event.Description, "tracker.") + log.Printf( + "tracker %s %s with status %s and tracking code %s\n", + tracker.ID, verb, tracker.Status, tracker.TrackingCode, + ) +} + +func main() { + var addr, user, pass, path string + flag.StringVar(&addr, "addr", ":8080", "Local HTTP listener address") + flag.StringVar(&user, "user", "", "HTTP user name required in requests") + flag.StringVar(&pass, "pass", "", "HTTP user password required in requests") + flag.StringVar(&path, "path", "/easypost/events", "HTTP webhook handler URI path") + flag.Parse() + handler := &Handler{Username: user, Password: pass} + mux := http.NewServeMux() + mux.Handle(path, handler) + if err := http.ListenAndServe(addr, mux); err != http.ErrServerClosed { + fmt.Println("error:", err) + } +} diff --git a/object.go b/object.go new file mode 100644 index 0000000..0832893 --- /dev/null +++ b/object.go @@ -0,0 +1,101 @@ +package easypost + +import ( + "encoding/json" +) + +// UnmarshalJSONObject attempts to unmarshal an easypost object from JSON data. +// An error is only returned if data is non-zero length and JSON decoding fails. +// If data contains a valid JSON object with an "object" key/value that matches +// a known object type, it will return a pointer to the corresponding object +// type from this package, e.g. *Address, *Batch, *Refund, etc. If the decoded +// JSON doesn't match, the return value will be the default type stored by +// json.Unmarshal. +func UnmarshalJSONObject(data []byte) (interface{}, error) { + if len(data) == 0 { + return nil, nil + } + + var obj struct { + Object string `json:"object"` + } + + if err := json.Unmarshal(data, &obj); err != nil { + return nil, err + } + + var result interface{} + switch obj.Object { + case "Address": + result = new(Address) + case "ApiKey": + result = new(APIKey) + case "Batch": + result = new(Batch) + case "CarrierAccount": + result = new(CarrierAccount) + case "CarrierDetail": + result = new(TrackingCarrierDetail) + case "CarrierType": + result = new(CarrierType) + case "CustomsInfo": + result = new(CustomsInfo) + case "CustomsItem": + result = new(CustomsItem) + case "Event": + result = new(Event) + case "Form": + result = new(Form) + case "Insurance": + result = new(Insurance) + case "Order": + result = new(Order) + case "Parcel": + result = new(Parcel) + case "Payload": + result = new(EventPayload) + case "PaymentLog": + result = new(PaymentLog) + case "PaymentLogReport": + result = new(Report) + case "Pickup": + result = new(Pickup) + case "PostageLabel": + result = new(PostageLabel) + case "Rate": + result = new(Rate) + case "Refund": + result = new(Refund) + case "RefundReport": + result = new(Report) + case "ScanForm": + result = new(ScanForm) + case "Shipment": + result = new(Shipment) + case "ShipmentInvoiceReport": + result = new(Report) + case "ShipmentReport": + result = new(Report) + case "Tracker": + result = new(Tracker) + case "TrackerReport": + result = new(Report) + case "TrackingDetail": + result = new(TrackingDetail) + case "TrackingLocation": + result = new(TrackingLocation) + case "User": + result = new(User) + case "Webhook": + result = new(Webhook) + } + + // If 'obj' didn't match one of the types above, result will be a nil + // interface type. This will cause Unmarshal to use the default Go type for + // the JSON value, like map[string]interface{}. + if err := json.Unmarshal(data, &result); err != nil { + return nil, err + } + + return result, nil +} diff --git a/payment_log.go b/payment_log.go new file mode 100644 index 0000000..5ccf8aa --- /dev/null +++ b/payment_log.go @@ -0,0 +1,17 @@ +package easypost + +import "time" + +type PaymentLog struct { + ID string `json:"id,omitempty"` + Object string `json:"object,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + SourceType string `json:"source_type,omitempty"` + TargetType string `json:"target_type,omitempty"` + Date string `json:"date,omitempty"` + ChargeType string `json:"charge_type,omitempty"` + Status string `json:"status,omitempty"` + Amount string `json:"amount,omitempty"` + Last4 string `json:"last4,omitempty"` +} diff --git a/refund.go b/refund.go new file mode 100644 index 0000000..1a913af --- /dev/null +++ b/refund.go @@ -0,0 +1,15 @@ +package easypost + +import "time" + +type Refund struct { + ID string `json:"id,omitempty"` + Object string `json:"object,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + TrackingCode string `json:"tracking_code,omitempty"` + ConfirmationNumber string `json:"confirmation_number,omitempty"` + Status string `json:"status,omitempty"` + Carrier string `json:"carrier,omitempty"` + ShipmentID string `json:"shipment_id,omitempty"` +} diff --git a/tests/event_test.go b/tests/event_test.go new file mode 100644 index 0000000..8dd89cc --- /dev/null +++ b/tests/event_test.go @@ -0,0 +1,73 @@ +package easypost_test + +import "github.com/EasyPost/easypost-go" + +func (c *ClientTests) TestEventsGet() { + client := c.TestClient() + assert := c.Assert() + + events, err := client.ListEvents(nil) + assert.NoError(err) + if assert.Len(events.Events, 7) { + assert.Equal(events.Events[0].Description, "tracker.updated") + assert.Equal( + events.Events[0].PreviousAttributes, + map[string]interface{}{"status": "out_for_delivery"}, + ) + assert.Equal(events.Events[5].Description, "refund.successful") + assert.Equal(events.Events[5].Status, "completed") + assert.Equal(events.Events[6].Description, "payment.failed") + assert.Len(events.Events[6].CompletedURLs, 1) + + event, err := client.GetEvent(events.Events[0].ID) + assert.NoError(err) + assert.Equal(events.Events[0], event) + } +} + +func (c *ClientTests) TestEventsGetPayloads() { + client := c.TestClient() + assert := c.Assert() + + events, err := client.ListEvents(nil) + assert.NoError(err) + if assert.Len(events.Events, 7) { + payloads, err := client.ListEventPayloads(events.Events[0].ID) + assert.NoError(err) + if assert.Len(payloads, 1) { + if assert.IsType((*easypost.Event)(nil), payloads[0].RequestBody) { + event := payloads[0].RequestBody.(*easypost.Event) + assert.Equal("tracker.updated", event.Description) + if assert.IsType((*easypost.Tracker)(nil), event.Result) { + tracker := event.Result.(*easypost.Tracker) + assert.Equal("9470100897846040813025", tracker.TrackingCode) + } + } + } + payloads, err = client.ListEventPayloads(events.Events[5].ID) + assert.NoError(err) + if assert.Len(payloads, 1) { + if assert.IsType((*easypost.Event)(nil), payloads[0].RequestBody) { + event := payloads[0].RequestBody.(*easypost.Event) + assert.Equal("refund.successful", event.Description) + if assert.IsType((*easypost.Refund)(nil), event.Result) { + refund := event.Result.(*easypost.Refund) + assert.Equal("USPS", refund.Carrier) + } + } + } + payloads, err = client.ListEventPayloads(events.Events[6].ID) + assert.NoError(err) + if assert.Len(payloads, 1) { + if assert.IsType((*easypost.Event)(nil), payloads[0].RequestBody) { + event := payloads[0].RequestBody.(*easypost.Event) + assert.Equal("payment.failed", event.Description) + if assert.IsType((*easypost.PaymentLog)(nil), event.Result) { + payment := event.Result.(*easypost.PaymentLog) + assert.Equal("1000.00000", payment.Amount) + } + } + } + } + +} diff --git a/tests/testdata/TestClient/TestEventsGet.yaml b/tests/testdata/TestClient/TestEventsGet.yaml new file mode 100644 index 0000000..8f07433 --- /dev/null +++ b/tests/testdata/TestClient/TestEventsGet.yaml @@ -0,0 +1,230 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events + method: GET + response: + body: ' + { + "events": [ + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "out_for_delivery" + }, + "created_at": "2020-06-09T21:00:02.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T21:00:32.000Z", + "id": "evt_36940ed69d634b92bfec365705549936", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "in_transit" + }, + "created_at": "2020-06-09T20:59:02.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:59:32.000Z", + "id": "evt_c5fa871c225441b4ac048484ed374f83", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "pre_transit" + }, + "created_at": "2020-06-09T20:58:01.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:58:32.000Z", + "id": "evt_dc4939b6785c49f9acc14f32780af52a", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "unknown" + }, + "created_at": "2020-06-09T20:57:01.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:57:32.000Z", + "id": "evt_762eded480254931a1035c88c2a84bba", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.created", + "mode": "test", + "previous_attributes": null, + "created_at": "2020-06-09T20:56:31.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:57:02.000Z", + "id": "evt_92f027e67c5446a69ed4496401820d8e", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "refund.successful", + "mode": "test", + "previous_attributes": null, + "created_at": "2020-06-09T15:54:07.000Z", + "pending_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "completed_urls": [], + "updated_at": "2020-06-09T21:10:30.000Z", + "id": "evt_8dab6a095ace4d01a90d393f37447ea2", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "payment.failed", + "mode": "test", + "previous_attributes": null, + "created_at": "2020-06-09T21:15:53.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T21:16:28.000Z", + "id": "evt_0b576769da9c416295ed6ed934e4c8bd", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + } + ], + "has_more": false + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - 6ed1139d5edff95eec6624e200031415 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb9sj + X-Proxied: + - intlb1sj a38b562602 + - intlb1wdc a38b562602 + - extlb1wdc 5834894b53 + X-Runtime: + - "0.046399" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_36940ed69d634b92bfec365705549936 + method: GET + response: + body: ' + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "out_for_delivery" + }, + "created_at": "2020-06-09T21:00:02.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T21:00:32.000Z", + "id": "evt_36940ed69d634b92bfec365705549936", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - 6ed1139d5edff95eec6624e200031431 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb8sj + X-Proxied: + - intlb2sj a38b562602 + - intlb2wdc a38b562602 + - extlb1wdc 5834894b53 + X-Runtime: + - "0.038172" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/tests/testdata/TestClient/TestEventsGetPayloads.yaml b/tests/testdata/TestClient/TestEventsGetPayloads.yaml new file mode 100644 index 0000000..265485d --- /dev/null +++ b/tests/testdata/TestClient/TestEventsGetPayloads.yaml @@ -0,0 +1,766 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events + method: GET + response: + body: ' + { + "events": [ + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "out_for_delivery" + }, + "created_at": "2020-06-09T21:00:02.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T21:00:32.000Z", + "id": "evt_36940ed69d634b92bfec365705549936", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "in_transit" + }, + "created_at": "2020-06-09T20:59:02.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:59:32.000Z", + "id": "evt_c5fa871c225441b4ac048484ed374f83", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "pre_transit" + }, + "created_at": "2020-06-09T20:58:01.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:58:32.000Z", + "id": "evt_dc4939b6785c49f9acc14f32780af52a", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.updated", + "mode": "test", + "previous_attributes": { + "status": "unknown" + }, + "created_at": "2020-06-09T20:57:01.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:57:32.000Z", + "id": "evt_762eded480254931a1035c88c2a84bba", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "tracker.created", + "mode": "test", + "previous_attributes": null, + "created_at": "2020-06-09T20:56:31.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T20:57:02.000Z", + "id": "evt_92f027e67c5446a69ed4496401820d8e", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "refund.successful", + "mode": "test", + "previous_attributes": null, + "created_at": "2020-06-09T15:54:07.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T21:10:30.000Z", + "id": "evt_8dab6a095ace4d01a90d393f37447ea2", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + }, + { + "description": "payment.failed", + "mode": "test", + "previous_attributes": null, + "created_at": "2020-06-09T21:15:53.000Z", + "pending_urls": [], + "completed_urls": [ + "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0" + ], + "updated_at": "2020-06-09T21:16:28.000Z", + "id": "evt_0b576769da9c416295ed6ed934e4c8bd", + "user_id": "user_66bb044575114f29930ae33901f6c9a6", + "status": "completed", + "object": "Event" + } + ], + "has_more": false + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a542 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb9sj + X-Proxied: + - intlb1sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.044446" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_36940ed69d634b92bfec365705549936/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_f6dc012918e54e2ca1f3808f0f811145", + "object": "Payload", + "created_at": "2020-06-09T21:00:32Z", + "updated_at": "2020-06-09T21:00:32Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent": "EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "{\"description\":\"tracker.updated\",\"mode\":\"test\",\"previous_attributes\":{\"status\":\"out_for_delivery\"},\"created_at\":\"2020-06-09T21:00:02.000Z\",\"pending_urls\":[\"https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0\"],\"completed_urls\":[],\"updated_at\":\"2020-06-09T21:00:02.000Z\",\"id\":\"evt_36940ed69d634b92bfec365705549936\",\"user_id\":\"user_66bb044575114f29930ae33901f6c9a6\",\"status\":\"pending\",\"object\":\"Event\",\"result\":{\"id\":\"trk_9508c8ccb51f4eb4aa276957fcc9c923\",\"user_id\":599470,\"object\":\"Tracker\",\"mode\":\"test\",\"tracking_code\":\"9470100897846040813025\",\"status\":\"delivered\",\"status_detail\":\"arrived_at_destination\",\"created_at\":\"2020-06-09T20:56:01Z\",\"updated_at\":\"2020-06-09T20:59:02Z\",\"signed_by\":\"John + Tester\",\"weight\":null,\"est_delivery_date\":\"2020-06-09T20:59:02Z\",\"shipment_id\":\"shp_88374a87390c49dabd536fad7b9714d6\",\"carrier\":\"USPS\",\"tracking_details\":[{\"object\":\"TrackingDetail\",\"message\":\"Pre-Shipment + Info Sent to USPS\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-09T20:59:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":null,\"state\":null,\"country\":null,\"zip\":null}},{\"object\":\"TrackingDetail\",\"message\":\"Shipping + Label Created\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-10T09:36:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at USPS Origin Facility\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-10T19:41:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"NORTH + HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77315\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at USPS Facility\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-11T21:17:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"COLUMBIA\",\"state\":\"SC\",\"country\":null,\"zip\":\"29201\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at Post Office\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-12T00:08:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}},{\"object\":\"TrackingDetail\",\"message\":\"Sorting + Complete\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-12T05:48:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}},{\"object\":\"TrackingDetail\",\"message\":\"Out + for Delivery\",\"description\":null,\"status\":\"out_for_delivery\",\"status_detail\":\"out_for_delivery\",\"datetime\":\"2020-05-12T05:58:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}},{\"object\":\"TrackingDetail\",\"message\":\"Delivered\",\"description\":null,\"status\":\"delivered\",\"status_detail\":\"arrived_at_destination\",\"datetime\":\"2020-05-12T10:50:02Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}}],\"carrier_detail\":{\"object\":\"CarrierDetail\",\"service\":\"First-Class + Package Service\",\"container_type\":null,\"est_delivery_date_local\":null,\"est_delivery_time_local\":null,\"origin_location\":\"HOUSTON + TX, 77001\",\"origin_tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"NORTH + HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77315\"},\"destination_location\":\"CHARLESTON + SC, 29401\",\"destination_tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"},\"guaranteed_delivery_date\":null,\"alternate_identifier\":null,\"initial_delivery_attempt\":\"2020-05-12T10:50:02Z\"},\"finalized\":true,\"is_return\":false,\"public_url\":\"https://track.easypost.com/djE6dHJrXzk1MDhjOGNjYjUxZjRlYjRhYTI3Njk1N2ZjYzljOTIz\"}}", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection": "close", + "Vary": "Accept-Encoding", + "X-Request-Id": "74fd5238-ea6b-4be1-a263-b7b81887a4c0", + "X-Token-Id": "6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control": "no-cache, private", + "Date": "Tue, 09 Jun 2020 21:00:32 GMT", + "Set-Cookie": "laravel_session=GtLus0oOB0qQY5C3AwnTb5hYC4ZlDNgsbn092nJ9; expires=Tue, 09-Jun-2020 23:00:32 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "652.5" + }, + "response_body": null, + "response_code": 200, + "total_time": 652 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a545 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb10sj + X-Proxied: + - intlb2sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.055001" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_c5fa871c225441b4ac048484ed374f83/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_cc04edc39ce540869c6ca24504d76653", + "object": "Payload", + "created_at": "2020-06-09T20:59:32Z", + "updated_at": "2020-06-09T20:59:32Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent": "EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "{\"description\":\"tracker.updated\",\"mode\":\"test\",\"previous_attributes\":{\"status\":\"in_transit\"},\"created_at\":\"2020-06-09T20:59:02.000Z\",\"pending_urls\":[\"https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0\"],\"completed_urls\":[],\"updated_at\":\"2020-06-09T20:59:02.000Z\",\"id\":\"evt_c5fa871c225441b4ac048484ed374f83\",\"user_id\":\"user_66bb044575114f29930ae33901f6c9a6\",\"status\":\"pending\",\"object\":\"Event\",\"result\":{\"id\":\"trk_9508c8ccb51f4eb4aa276957fcc9c923\",\"user_id\":599470,\"object\":\"Tracker\",\"mode\":\"test\",\"tracking_code\":\"9470100897846040813025\",\"status\":\"out_for_delivery\",\"status_detail\":\"out_for_delivery\",\"created_at\":\"2020-06-09T20:56:01Z\",\"updated_at\":\"2020-06-09T20:58:01Z\",\"signed_by\":null,\"weight\":null,\"est_delivery_date\":\"2020-06-09T20:58:01Z\",\"shipment_id\":\"shp_88374a87390c49dabd536fad7b9714d6\",\"carrier\":\"USPS\",\"tracking_details\":[{\"object\":\"TrackingDetail\",\"message\":\"Pre-Shipment + Info Sent to USPS\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-09T20:58:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":null,\"state\":null,\"country\":null,\"zip\":null}},{\"object\":\"TrackingDetail\",\"message\":\"Shipping + Label Created\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-10T09:35:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at USPS Origin Facility\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-10T19:40:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"NORTH + HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77315\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at USPS Facility\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-11T21:16:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"COLUMBIA\",\"state\":\"SC\",\"country\":null,\"zip\":\"29201\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at Post Office\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-12T00:07:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}},{\"object\":\"TrackingDetail\",\"message\":\"Sorting + Complete\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-12T05:47:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}},{\"object\":\"TrackingDetail\",\"message\":\"Out + for Delivery\",\"description\":null,\"status\":\"out_for_delivery\",\"status_detail\":\"out_for_delivery\",\"datetime\":\"2020-05-12T05:57:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}}],\"carrier_detail\":{\"object\":\"CarrierDetail\",\"service\":\"First-Class + Package Service\",\"container_type\":null,\"est_delivery_date_local\":null,\"est_delivery_time_local\":null,\"origin_location\":\"HOUSTON + TX, 77001\",\"origin_tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"NORTH + HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77315\"},\"destination_location\":\"CHARLESTON + SC, 29401\",\"destination_tracking_location\":null,\"guaranteed_delivery_date\":null,\"alternate_identifier\":null,\"initial_delivery_attempt\":null},\"finalized\":true,\"is_return\":false,\"public_url\":\"https://track.easypost.com/djE6dHJrXzk1MDhjOGNjYjUxZjRlYjRhYTI3Njk1N2ZjYzljOTIz\"}}", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection": "close", + "Vary": "Accept-Encoding", + "X-Request-Id": "de1b3e24-cae3-4483-bbdd-c11f4a92595e", + "X-Token-Id": "6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control": "no-cache, private", + "Date": "Tue, 09 Jun 2020 20:59:32 GMT", + "Set-Cookie": "laravel_session=8ov93bSID3j1n1YGWEQ4CsNGdn2caziD8UhABG1X; expires=Tue, 09-Jun-2020 22:59:32 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "653.7" + }, + "response_body": null, + "response_code": 200, + "total_time": 653 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a54b + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb8sj + X-Proxied: + - intlb2sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.041621" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_dc4939b6785c49f9acc14f32780af52a/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_eb14c708d31b48ca99bb532e597f18b1", + "object": "Payload", + "created_at": "2020-06-09T20:58:32Z", + "updated_at": "2020-06-09T20:58:32Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent": "EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "{\"description\":\"tracker.updated\",\"mode\":\"test\",\"previous_attributes\":{\"status\":\"pre_transit\"},\"created_at\":\"2020-06-09T20:58:01.000Z\",\"pending_urls\":[\"https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0\"],\"completed_urls\":[],\"updated_at\":\"2020-06-09T20:58:01.000Z\",\"id\":\"evt_dc4939b6785c49f9acc14f32780af52a\",\"user_id\":\"user_66bb044575114f29930ae33901f6c9a6\",\"status\":\"pending\",\"object\":\"Event\",\"result\":{\"id\":\"trk_9508c8ccb51f4eb4aa276957fcc9c923\",\"user_id\":599470,\"object\":\"Tracker\",\"mode\":\"test\",\"tracking_code\":\"9470100897846040813025\",\"status\":\"in_transit\",\"status_detail\":\"status_update\",\"created_at\":\"2020-06-09T20:56:01Z\",\"updated_at\":\"2020-06-09T20:57:01Z\",\"signed_by\":null,\"weight\":null,\"est_delivery_date\":\"2020-06-09T20:57:01Z\",\"shipment_id\":\"shp_88374a87390c49dabd536fad7b9714d6\",\"carrier\":\"USPS\",\"tracking_details\":[{\"object\":\"TrackingDetail\",\"message\":\"Pre-Shipment + Info Sent to USPS\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-09T20:57:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":null,\"state\":null,\"country\":null,\"zip\":null}},{\"object\":\"TrackingDetail\",\"message\":\"Shipping + Label Created\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-10T09:34:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at USPS Origin Facility\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-10T19:39:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"NORTH + HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77315\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at USPS Facility\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-11T21:15:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"COLUMBIA\",\"state\":\"SC\",\"country\":null,\"zip\":\"29201\"}},{\"object\":\"TrackingDetail\",\"message\":\"Arrived + at Post Office\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"arrived_at_facility\",\"datetime\":\"2020-05-12T00:06:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}},{\"object\":\"TrackingDetail\",\"message\":\"Sorting + Complete\",\"description\":null,\"status\":\"in_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-12T05:46:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"CHARLESTON\",\"state\":\"SC\",\"country\":null,\"zip\":\"29407\"}}],\"carrier_detail\":{\"object\":\"CarrierDetail\",\"service\":\"First-Class + Package Service\",\"container_type\":null,\"est_delivery_date_local\":null,\"est_delivery_time_local\":null,\"origin_location\":\"HOUSTON + TX, 77001\",\"origin_tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"NORTH + HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77315\"},\"destination_location\":\"CHARLESTON + SC, 29401\",\"destination_tracking_location\":null,\"guaranteed_delivery_date\":null,\"alternate_identifier\":null,\"initial_delivery_attempt\":null},\"finalized\":true,\"is_return\":false,\"public_url\":\"https://track.easypost.com/djE6dHJrXzk1MDhjOGNjYjUxZjRlYjRhYTI3Njk1N2ZjYzljOTIz\"}}", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection": "close", + "Vary": "Accept-Encoding", + "X-Request-Id": "d20c28a0-33a5-4e43-95a6-a40e19b8e909", + "X-Token-Id": "6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control": "no-cache, private", + "Date": "Tue, 09 Jun 2020 20:58:32 GMT", + "Set-Cookie": "laravel_session=jyF5vJeTf9edzpG9lDSmqtNE7mRFPr8Y2vJpgzaX; expires=Tue, 09-Jun-2020 22:58:32 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "644.31" + }, + "response_body": null, + "response_code": 200, + "total_time": 644 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a559 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb10sj + X-Proxied: + - intlb1sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.043679" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_762eded480254931a1035c88c2a84bba/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_7ded9e0b34d648f3bb4f0cca4aa4202e", + "object": "Payload", + "created_at": "2020-06-09T20:57:32Z", + "updated_at": "2020-06-09T20:57:32Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent":" EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "{\"description\":\"tracker.updated\",\"mode\":\"test\",\"previous_attributes\":{\"status\":\"unknown\"},\"created_at\":\"2020-06-09T20:57:01.000Z\",\"pending_urls\":[\"https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0\"],\"completed_urls\":[],\"updated_at\":\"2020-06-09T20:57:01.000Z\",\"id\":\"evt_762eded480254931a1035c88c2a84bba\",\"user_id\":\"user_66bb044575114f29930ae33901f6c9a6\",\"status\":\"pending\",\"object\":\"Event\",\"result\":{\"id\":\"trk_9508c8ccb51f4eb4aa276957fcc9c923\",\"user_id\":599470,\"object\":\"Tracker\",\"mode\":\"test\",\"tracking_code\":\"9470100897846040813025\",\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"created_at\":\"2020-06-09T20:56:01Z\",\"updated_at\":\"2020-06-09T20:56:01Z\",\"signed_by\":null,\"weight\":null,\"est_delivery_date\":\"2020-06-09T20:56:01Z\",\"shipment_id\":\"shp_88374a87390c49dabd536fad7b9714d6\",\"carrier\":\"USPS\",\"tracking_details\":[{\"object\":\"TrackingDetail\",\"message\":\"Pre-Shipment + Info Sent to USPS\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-09T20:56:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":null,\"state\":null,\"country\":null,\"zip\":null}},{\"object\":\"TrackingDetail\",\"message\":\"Shipping + Label Created\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-10T09:33:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"}}],\"carrier_detail\":{\"object\":\"CarrierDetail\",\"service\":\"First-Class + Package Service\",\"container_type\":null,\"est_delivery_date_local\":null,\"est_delivery_time_local\":null,\"origin_location\":\"HOUSTON + TX, 77001\",\"origin_tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"},\"destination_location\":\"CHARLESTON + SC, 29401\",\"destination_tracking_location\":null,\"guaranteed_delivery_date\":null,\"alternate_identifier\":null,\"initial_delivery_attempt\":null},\"finalized\":true,\"is_return\":false,\"public_url\":\"https://track.easypost.com/djE6dHJrXzk1MDhjOGNjYjUxZjRlYjRhYTI3Njk1N2ZjYzljOTIz\"}}", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection": "close", + "Vary": "Accept-Encoding", + "X-Request-Id": "545dd686-62bc-4306-9251-992068b1f4ec", + "X-Token-Id": "6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control" :"no-cache, private", + "Date": "Tue, 09 Jun 2020 20:57:32 GMT", + "Set-Cookie": "laravel_session=FPTtlh1gp0BAwJgMuw9mx2buUqvaYB8dYRdYDTar; expires=Tue, 09-Jun-2020 22:57:32 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "648.06" + }, + "response_body": null, + "response_code": 200, + "total_time": 648 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a561 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb6sj + X-Proxied: + - intlb2sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.045900" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_92f027e67c5446a69ed4496401820d8e/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_19ade9c8ccc34a27b286668d9a698660", + "object": "Payload", + "created_at": "2020-06-09T20:57:02Z", + "updated_at": "2020-06-09T20:57:02Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent":"EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "{\"description\":\"tracker.created\",\"mode\":\"test\",\"previous_attributes\":{},\"created_at\":\"2020-06-09T20:56:31.000Z\",\"pending_urls\":[\"https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0\"],\"completed_urls\":[],\"updated_at\":\"2020-06-09T20:56:31.000Z\",\"id\":\"evt_8dab6a095ace4d01a90d393f37447ea2\",\"user_id\":\"user_66bb044575114f29930ae33901f6c9a6\",\"status\":\"pending\",\"object\":\"Event\",\"result\":{\"id\":\"trk_9508c8ccb51f4eb4aa276957fcc9c923\",\"user_id\":599470,\"object\":\"Tracker\",\"mode\":\"test\",\"tracking_code\":\"9470100897846040813025\",\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"created_at\":\"2020-06-09T20:56:01Z\",\"updated_at\":\"2020-06-09T20:56:01Z\",\"signed_by\":null,\"weight\":null,\"est_delivery_date\":\"2020-06-09T20:56:01Z\",\"shipment_id\":\"shp_88374a87390c49dabd536fad7b9714d6\",\"carrier\":\"USPS\",\"tracking_details\":[{\"object\":\"TrackingDetail\",\"message\":\"Pre-Shipment + Info Sent to USPS\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-09T20:56:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":null,\"state\":null,\"country\":null,\"zip\":null}},{\"object\":\"TrackingDetail\",\"message\":\"Shipping + Label Created\",\"description\":null,\"status\":\"pre_transit\",\"status_detail\":\"status_update\",\"datetime\":\"2020-05-10T09:33:01Z\",\"source\":\"USPS\",\"carrier_code\":null,\"tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"}}],\"carrier_detail\":{\"object\":\"CarrierDetail\",\"service\":\"First-Class + Package Service\",\"container_type\":null,\"est_delivery_date_local\":null,\"est_delivery_time_local\":null,\"origin_location\":\"HOUSTON + TX, 77001\",\"origin_tracking_location\":{\"object\":\"TrackingLocation\",\"city\":\"HOUSTON\",\"state\":\"TX\",\"country\":null,\"zip\":\"77063\"},\"destination_location\":\"CHARLESTON + SC, 29401\",\"destination_tracking_location\":null,\"guaranteed_delivery_date\":null,\"alternate_identifier\":null,\"initial_delivery_attempt\":null},\"finalized\":true,\"is_return\":false,\"public_url\":\"https://track.easypost.com/djE6dHJrXzk1MDhjOGNjYjUxZjRlYjRhYTI3Njk1N2ZjYzljOTIz\"}}", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection": "close", + "Vary": "Accept-Encoding", + "X-Request-Id": "a70a71e8-f42f-48e9-ae64-566f2f50f2e4", + "X-Token-Id": "6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control": "no-cache, private", + "Date": "Tue, 09 Jun 2020 20:57:02 GMT", + "Set-Cookie":" laravel_session=oxJ4TCw5cGkvfJMc5jAVdztPI5XWhOGV0i70thaI; expires=Tue, 09-Jun-2020 22:57:02 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "636.99" + }, + "response_body": null, + "response_code": 200, + "total_time":636 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a578 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb8sj + X-Proxied: + - intlb1sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.044723" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_8dab6a095ace4d01a90d393f37447ea2/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_8a26e14a8ecd44c6a446ef88d139d5ae", + "object": "Payload", + "created_at": "2020-06-08T21:39:54Z", + "updated_at": "2020-06-08T21:39:54Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent": "EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "{\"result\":{\"id\":\"rfnd_c09a2ba9be1a4c03ac6beadabb33097f\",\"object\":\"Refund\",\"created_at\":\"2020-05-25T15:54:02Z\",\"updated_at\":\"2020-06-09T15:54:07Z\",\"tracking_code\":\"1234567890123456789012\",\"confirmation_number\":null,\"status\":\"refunded\",\"carrier\":\"USPS\",\"shipment_id\":\"shp_c637bb9ed55949c58ba7a8286d3d2bae\"},\"description\":\"refund.successful\",\"mode\":\"production\",\"previous_attributes\":null,\"completed_urls\":[\"https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0\"],\"user_id\":\"user_66bb044575114f29930ae33901f6c9a6\",\"status\":\"completed\",\"object\":\"Event\",\"id\":\"evt_8dab6a095ace4d01a90d393f37447ea2\"}", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection":" close", + "Vary": "Accept-Encoding", + "X-Request-Id": "10c18413-010b-4c05-b891-9d360e88fb63", + "X-Token-Id":" 6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control": "no-cache, private", + "Date": "Mon, 08 Jun 2020 21:39:54 GMT", + "Set-Cookie": "laravel_session=mHLcf3EXgcSFawoQ8s1wWpTmJDoY6UZTvdahtVGj; expires=Mon, 08-Jun-2020 23:39:54 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "652.8" + }, + "response_body": null, + "response_code": 200, + "total_time": 652 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a57f + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb11sj + X-Proxied: + - intlb2sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.046708" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + User-Agent: + - EasyPost/v2 GoClient/1.0.3 + url: https://api.easypost.com/v2/events/evt_0b576769da9c416295ed6ed934e4c8bd/payloads + method: GET + response: + body: ' + { + "payloads": [ + { + "id": "payload_9ea65855824940148786bcefc846cfbd", + "object": "Payload", + "created_at": "2020-06-08T21:38:53Z", + "updated_at": "2020-06-08T21:38:53Z", + "request_url": "https://webhook.site/6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "request_headers": { + "User-Agent": "EasyPost WebHook Agent 1.0", + "Content-Type": "application/json", + "Connection": "close", + "Expect": "", + "X-Webhook-User-Id": "user_66bb044575114f29930ae33901f6c9a6" + }, + "request_body": "eyJyZXN1bHQiOnsiaWQiOiJwYXlsb2dfNDBiYmE3Y2M5ZGJmNDFhM2I4ODEy\nNGRkZmM4MDk4MTQiLCJvYmplY3QiOiJQYXltZW50TG9nIiwic291cmNlX3R5\ncGUiOiJjcmVkaXRfY2FyZCIsInRhcmdldF90eXBlIjoiZWFzeXBvc3Rfc3Ry\naXBlIiwiZGF0ZSI6IjIwMjAtMDYtMDkgMjE6MTU6NTMgVVRDIiwiY2hhcmdl\nX3R5cGUiOiJyZWNoYXJnZSIsInN0YXR1cyI6ImZhaWx1cmUiLCJhbW91bnQi\nOiIxMDAwLjAwMDAwIiwiY3JlYXRlZF9hdCI6IjIwMjAtMDYtMDlUMjE6MTU6\nNTNaIiwidXBkYXRlZF9hdCI6IjIwMjAtMDYtMDlUMjE6MTU6NTNaIiwibGFz\ndDQiOiIxMjM0In0sImRlc2NyaXB0aW9uIjoicGF5bWVudC5mYWlsZWQiLCJt\nb2RlIjoicHJvZHVjdGlvbiIsInByZXZpb3VzX2F0dHJpYnV0ZXMiOm51bGws\nImNvbXBsZXRlZF91cmxzIjpudWxsLCJ1c2VyX2lkIjoidXNlcl82NmJiMDQ0\nNTc1MTE0ZjI5OTMwYWUzMzkwMWY2YzlhNiIsInN0YXR1cyI6InBlbmRpbmci\nLCJvYmplY3QiOiJFdmVudCIsImlkIjoiZXZ0XzBiNTc2NzY5ZGE5YzQxNjI5\nNWVkNmVkOTM0ZTRjOGJkIn0=\n", + "response_headers": { + "Server": "nginx/1.14.2", + "Content-Type": "text/plain; charset=UTF-8", + "Transfer-Encoding": "chunked", + "Connection": "close", + "Vary": "Accept-Encoding", + "X-Request-Id": "839fb551-711f-47f2-abd6-dd9151fed084", + "X-Token-Id": "6db0d77f-77bb-48b7-ba65-b3bc141025d0", + "Cache-Control": "no-cache, private", + "Date": "Mon, 08 Jun 2020 21:38:53 GMT", + "Set-Cookie": "laravel_session=EqeCRlkohMZT6Q8Ac87TPlf0OIHfGNWXqfUq6tzb; expires=Mon, 08-Jun-2020 23:38:53 GMT; Max-Age=7200; path=/; httponly", + "X-Faraday-Runtime": "644.5" + }, + "response_body" :null, + "response_code": 200, + "total_time": 644 + } + ] + } + ' + headers: + Cache-Control: + - no-cache, no-store, must-revalidate, private + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=15768000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Ep-Request-Uuid: + - cc3597b95ee000a4ec54aa090002a586 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb3sj + X-Proxied: + - intlb1sj a38b562602 + - extlb1sj 5834894b53 + X-Runtime: + - "0.105986" + X-Version-Label: + - easypost-202006091919-12f0b90a2e-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/tracker.go b/tracker.go index 80b64ee..a95cd53 100644 --- a/tracker.go +++ b/tracker.go @@ -21,9 +21,11 @@ type TrackingLocation struct { type TrackingDetail struct { Object string `json:"object,omitempty"` Message string `json:"message,omitempty"` + Description string `json:"description,omitempty"` Status string `json:"status,omitempty"` DateTime string `json:"datetime,omitempty"` Source string `json:"source,omitempty"` + CarrierCode string `json:"carrier_code,omitempty"` TrackingLocation *TrackingLocation `json:"tracking_location,omitempty"` } @@ -37,6 +39,7 @@ type TrackingCarrierDetail struct { EstDeliveryTimeLocal string `json:"est_delivery_time_local,omitempty"` OriginLocation string `json:"origin_locaion,omitempty"` OriginTrackingLocation *TrackingLocation `json:"origin_tracking_location,omitempty"` + DestinationLocation string `json:"destination_location,omitempty"` DestinationTrackingLocation *TrackingLocation `json:"destination_tracking_location,omitempty"` GuaranteedDeliveryDate *time.Time `json:"guaranteed_delivery_date,omitempty"` AlternateIdentifier string `json:"alternate_identifier,omitempty"` @@ -61,6 +64,8 @@ type Tracker struct { CarrierDetail *TrackingCarrierDetail `json:"carrier_detail,omitempty"` PublicURL string `json:"public_url,omitempty"` Fees []*Fee `json:"fees,omitempty"` + Finalized bool `json:"finalized,omitempty"` + IsReturn bool `json:"is_return,omitempty"` } // CreateTrackerOptions specifies options for creating a new tracker.