Back

Step by Step Guide to Building a ShipStation API Integration in Go

Aug 12, 20249 minute read

Introduction

Hey there, fellow Go enthusiast! Ready to dive into the world of ShipStation API integration? You're in for a treat. ShipStation's API is a powerhouse for managing orders, shipments, and all things e-commerce. In this guide, we'll walk through building a robust integration that'll have you shipping like a pro in no time.

Prerequisites

Before we jump in, make sure you've got:

  • A Go environment set up and ready to roll
  • ShipStation API credentials (API key and secret)

Got those? Great! Let's get coding.

Setting up the project

First things first, let's create a new Go module:

mkdir shipstation-integration cd shipstation-integration go mod init github.com/yourusername/shipstation-integration

Now, let's grab the dependencies we'll need:

go get github.com/go-resty/resty/v2

We're using resty here because it makes HTTP requests a breeze. Feel free to use your favorite HTTP client if you prefer.

Authentication

ShipStation uses API key and secret for authentication. Let's create a reusable client:

package main import ( "github.com/go-resty/resty/v2" ) type ShipStationClient struct { client *resty.Client } func NewShipStationClient(apiKey, apiSecret string) *ShipStationClient { client := resty.New() client.SetBasicAuth(apiKey, apiSecret) client.SetBaseURL("https://ssapi.shipstation.com") return &ShipStationClient{client: client} }

Basic API Requests

Now that we've got our client set up, let's make some requests!

GET request example (fetching orders)

func (c *ShipStationClient) GetOrders() ([]Order, error) { var response OrdersResponse _, err := c.client.R(). SetResult(&response). Get("/orders") return response.Orders, err }

POST request example (creating a shipment)

func (c *ShipStationClient) CreateShipment(shipment Shipment) (CreatedShipment, error) { var response CreatedShipment _, err := c.client.R(). SetBody(shipment). SetResult(&response). Post("/shipments/createlabel") return response, err }

Handling Responses

ShipStation returns JSON responses. Let's parse them and handle errors:

type APIError struct { Message string `json:"message"` Code int `json:"code"` } func (c *ShipStationClient) doRequest(method, endpoint string, body interface{}) ([]byte, error) { resp, err := c.client.R(). SetBody(body). Execute(method, endpoint) if err != nil { return nil, err } if resp.IsError() { var apiError APIError if err := json.Unmarshal(resp.Body(), &apiError); err != nil { return nil, fmt.Errorf("unknown error: %s", resp.String()) } return nil, fmt.Errorf("API error: %s (code: %d)", apiError.Message, apiError.Code) } return resp.Body(), nil }

Implementing Key Functionalities

Now that we've got the basics down, let's implement some key functionalities:

Order management

func (c *ShipStationClient) GetOrder(orderID string) (Order, error) { var order Order _, err := c.client.R(). SetResult(&order). Get("/orders/" + orderID) return order, err }

Shipment creation

func (c *ShipStationClient) CreateShipment(shipment Shipment) (CreatedShipment, error) { var response CreatedShipment _, err := c.client.R(). SetBody(shipment). SetResult(&response). Post("/shipments/createlabel") return response, err }

Tracking information retrieval

func (c *ShipStationClient) GetTracking(carrierCode, trackingNumber string) (TrackingInfo, error) { var tracking TrackingInfo _, err := c.client.R(). SetResult(&tracking). Get(fmt.Sprintf("/shipments/gettrackinginfo?carrierCode=%s&trackingNumber=%s", carrierCode, trackingNumber)) return tracking, err }

Webhooks

ShipStation can send webhooks for various events. Here's a basic webhook handler:

func handleWebhook(w http.ResponseWriter, r *http.Request) { var webhook WebhookPayload if err := json.NewDecoder(r.Body).Decode(&webhook); err != nil { http.Error(w, "Invalid webhook payload", http.StatusBadRequest) return } // Process the webhook based on its resource_type and action switch webhook.ResourceType { case "ORDER_NOTIFY": // Handle order notification case "SHIP_NOTIFY": // Handle shipment notification } w.WriteHeader(http.StatusOK) }

Rate Limiting and Pagination

ShipStation has rate limits, so let's implement some basic rate limiting:

func (c *ShipStationClient) rateLimitedRequest(method, endpoint string, body interface{}) ([]byte, error) { time.Sleep(500 * time.Millisecond) // Ensure we don't exceed 2 requests per second return c.doRequest(method, endpoint, body) }

For pagination, we'll need to handle the page and pageSize parameters:

func (c *ShipStationClient) GetAllOrders() ([]Order, error) { var allOrders []Order page := 1 pageSize := 100 for { var response OrdersResponse _, err := c.client.R(). SetQueryParams(map[string]string{ "page": strconv.Itoa(page), "pageSize": strconv.Itoa(pageSize), }). SetResult(&response). Get("/orders") if err != nil { return nil, err } allOrders = append(allOrders, response.Orders...) if len(response.Orders) < pageSize { break } page++ } return allOrders, nil }

Testing

Don't forget to test your integration! Here's a quick example using the testing package:

func TestGetOrders(t *testing.T) { client := NewShipStationClient(os.Getenv("SHIPSTATION_API_KEY"), os.Getenv("SHIPSTATION_API_SECRET")) orders, err := client.GetOrders() if err != nil { t.Fatalf("Failed to get orders: %v", err) } if len(orders) == 0 { t.Fatal("Expected at least one order, got none") } }

Best Practices

  1. Always handle errors gracefully.
  2. Use environment variables for API credentials.
  3. Implement proper logging for debugging.
  4. Use context for cancellation and timeouts.

Conclusion

And there you have it! You've just built a solid foundation for a ShipStation API integration in Go. From here, you can expand on this integration to cover more endpoints and functionalities as needed for your specific use case.

Remember, the ShipStation API is vast and powerful. Don't be afraid to dive deeper into the documentation and experiment with different endpoints. Happy coding, and may your shipments always arrive on time!

Resources

Now go forth and conquer the world of e-commerce shipping with your new Go-powered ShipStation integration!