# How to Integrate Retool with ShipStation

- Tool: Retool
- Difficulty: Intermediate
- Time required: 20 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to ShipStation by adding a REST API Resource with ShipStation's base URL and your API Key + API Secret encoded as Basic Auth credentials. Once configured, build queries to view and manage orders, create shipping labels, and track shipments across all carriers and sales channels. Setup takes about 20 minutes and gives your operations team a unified fulfillment management panel.

## Why Connect Retool to ShipStation?

ShipStation excels at aggregating orders from dozens of sales channels — Shopify, Amazon, eBay, Etsy, BigCommerce, and more — and providing a unified interface for shipping label creation. But ShipStation's own dashboard has fixed views that don't always match how your operations team actually works. Connecting ShipStation to Retool lets you build custom fulfillment dashboards with exactly the data your team needs: cross-channel order queues, carrier performance metrics, exception handling panels, and bulk action tools that ShipStation's native UI doesn't support.

ShipStation's REST API exposes the full range of fulfillment operations: listing and filtering orders, marking orders as shipped, creating shipping labels, managing warehouses and products, and querying shipment history. This gives Retool enough surface area to build everything from a simple daily shipping queue to a comprehensive operations center that combines ShipStation data with your own PostgreSQL database, CRM, and customer support tools.

A common pattern is building a Retool 'exception queue' — orders in ShipStation that require manual attention because of address issues, stock problems, or carrier exceptions. ShipStation's API lets you filter by order status and tag, so you can build a focused view that shows exactly the orders needing human intervention, with action buttons to update status, add notes, or void labels, all from within Retool without switching between multiple tools.

## Before you start

- A ShipStation account with at least one connected store and carrier (Starter plan or higher)
- ShipStation API credentials: navigate to Account Settings → API Settings to generate your API Key and API Secret
- A Retool account (Cloud or self-hosted) with permission to add Resources
- Basic familiarity with HTTP Basic Auth and Retool's REST API Resource configuration
- Optional: a database Resource already configured in Retool if you plan to combine ShipStation data with internal records

## Step-by-step guide

### 1. Generate ShipStation API credentials

Log into your ShipStation account at app.shipstation.com. Click on your account name in the top-right corner of the navigation bar and select Account Settings from the dropdown menu. In the Account Settings page, look for the API Settings section — it may be listed as 'API' in the left sidebar navigation within settings. Click on it to open the API credentials panel.

ShipStation displays your API Key and API Secret on this page. If you don't see credentials yet, click the Generate API Keys button to create them. Note that ShipStation generates a single API Key and Secret per account — there is no scoping or multiple key support. The same credentials are used for all API access.

Copy both the API Key and API Secret values. ShipStation uses HTTP Basic Auth with the API Key as the username and the API Secret as the password. In Retool, you will store these as separate configuration variables and reference them in the resource's Basic Auth configuration.

In your Retool account, navigate to Settings → Configuration Variables. Create two variables:
- SHIPSTATION_API_KEY: paste your API Key value, mark as secret
- SHIPSTATION_API_SECRET: paste your API Secret value, mark as secret

This separation makes it easy to rotate either credential independently. ShipStation credentials don't expire but should be rotated if compromised — you can regenerate them in the same API Settings page, which immediately invalidates the old credentials.

**Expected result:** You have ShipStation API Key and API Secret stored as secret configuration variables in Retool, ready to reference in the resource configuration.

### 2. Add a ShipStation REST API Resource in Retool

Open Retool and navigate to the Resources tab in the home page sidebar. Click Add Resource in the top-right corner and select REST API from the resource type selector.

In the configuration form, fill in the following fields:
- Name: 'ShipStation API' or 'ShipStation Production' for clarity in the query editor
- Base URL: https://ssapi.shipstation.com — this is ShipStation's API base URL. All endpoint paths are appended to this base in each query.
- Authentication: Select Basic Auth from the Authentication dropdown. This reveals two fields: Username and Password. Set Username to {{ environment.variables.SHIPSTATION_API_KEY }} and Password to {{ environment.variables.SHIPSTATION_API_SECRET }}. Retool encodes these as a Base64 Basic Auth header on every request, matching ShipStation's authentication requirement.

Leave the Headers section empty — ShipStation does not require custom headers beyond the Authorization header that Basic Auth automatically provides.

Click Save Changes. The resource now appears in your Resources list. To test it, create a quick query with Method GET and URL /orders?pageSize=5 and click Run. A successful response returns an 'orders' array with your five most recent ShipStation orders, confirming the authentication is working correctly.

**Expected result:** A ShipStation API Resource appears in your Retool Resources list. A test query to /orders returns ShipStation order data, confirming the Basic Auth credentials are correctly configured.

### 3. Query ShipStation orders with filtering and pagination

ShipStation's orders endpoint supports a rich set of query parameters for filtering. The most important ones for building an operations dashboard are: orderStatus (awaiting_payment, awaiting_shipment, shipped, cancelled, on_hold), storeId (filters by sales channel), orderDateStart/orderDateEnd (ISO 8601 date strings), and pageSize/page for pagination.

Create a new query in the Retool Code panel. Select your ShipStation resource, set Method to GET and URL to /orders. In the Params section, add the following parameters:
- orderStatus: bind to a Select component value: {{ statusSelect.value || 'awaiting_shipment' }}
- pageSize: {{ 100 }} — ShipStation allows up to 500 per page
- page: {{ currentPage.value || 1 }}
- orderDateStart: bind to a DateRange component: {{ dateRange.startDate }}
- orderDateEnd: {{ dateRange.endDate }}

Enable Run this query automatically when inputs change so the Table refreshes when the status Select or date range changes.

ShipStation returns an orders array, a total (total matching orders), and pagination metadata. Create a JavaScript transformer to flatten the nested order structure for Retool's Table:

Bind the transformer output to a Table component. Configure columns for: orderNumber, storeName, customerName, orderDate, orderStatus, totalAmount, serviceCode (shipping service), and itemCount. The Table's built-in search and column-level sorting provide additional filtering on top of the API-level filters.

```
// JavaScript transformer for ShipStation orders response
// Flatten nested order structure for Retool Table display
const response = data;
const orders = response.orders || [];

return orders.map(order => ({
  orderId: order.orderId,
  orderNumber: order.orderNumber,
  storeName: order.storeName || 'Unknown',
  orderStatus: order.orderStatus,
  customerName: order.shipTo ? order.shipTo.name : 'N/A',
  customerEmail: order.customerEmail || 'N/A',
  orderDate: order.orderDate
    ? new Date(order.orderDate).toLocaleDateString()
    : 'N/A',
  orderTotal: order.orderTotal ? `$${order.orderTotal.toFixed(2)}` : '$0.00',
  serviceCode: order.serviceCode || 'Not specified',
  carrierCode: order.carrierCode || 'N/A',
  requestedService: order.requestedShippingService || 'N/A',
  tagNames: order.tagIds ? order.tagIds.join(', ') : '',
  itemCount: order.items ? order.items.length : 0,
  weight: order.weight ? `${order.weight.value} ${order.weight.WeightUnits}` : 'N/A'
}));
```

**Expected result:** A Table in the Retool app displays ShipStation orders filtered by the selected status and date range. The transformer flattens nested fields like shipTo.name and items.length into readable Table columns. Changing the status Select or date range automatically refreshes the Table.

### 4. Create shipments and generate labels from Retool

ShipStation's label creation flow involves two steps: first create or update the Shipment record with carrier and service selection, then call the label creation endpoint. For orders already in ShipStation (imported from your stores), you typically use the existing order ID and just specify the carrier rate.

To create a label for a selected order, build the following workflow in Retool:

1. A detail panel shows when the operator selects an order row in the Table. The panel displays the shipping address from {{ ordersTable.selectedRow }} and input fields for carrier selection and service code.

2. Create a query to fetch available rates for the order. ShipStation's rate endpoint (POST /shipments/getrates) accepts the orderID or shipTo/shipFrom addresses plus package dimensions and returns available carrier rates. Set up a POST query with the order's shipping details.

3. Show the returned rates in a Select component or secondary Table so the operator can choose the carrier and service level.

4. Create a label creation query using POST /orders/createlabelfororder. This endpoint takes the orderId and the selected carrierCode, serviceCode, and packageCode and returns the labelData (base64-encoded PDF) and trackingNumber.

In the On Success event handler of the label creation query, trigger a secondary query that saves the tracking number to your database and updates the order's status in your internal records. Show a success notification with the tracking number.

For the label PDF, decode the base64 labelData using a JavaScript query and create a temporary download link, or display it in an IFrame component using a data URL.

```
// POST body for /orders/createlabelfororder
// Creates a shipping label for an existing ShipStation order
{
  "orderId": {{ ordersTable.selectedRow.orderId }},
  "carrierCode": "{{ carrierSelect.value }}",
  "serviceCode": "{{ serviceSelect.value }}",
  "packageCode": "{{ packageSelect.value || 'package' }}",
  "confirmation": "none",
  "shipDate": "{{ new Date().toISOString().split('T')[0] }}",
  "weight": {
    "value": {{ weightInput.value || ordersTable.selectedRow.weight }},
    "units": "ounces"
  },
  "testLabel": false
}
```

**Expected result:** Selecting an order from the Table, choosing a carrier rate, and clicking 'Create Label' generates a ShipStation shipping label. The tracking number appears in a success notification and the label PDF is accessible for printing.

### 5. Build multi-store analytics with Charts and KPI metrics

One of the most valuable ShipStation Retool dashboards is an executive summary that shows fulfillment performance across all connected sales channels. Use ShipStation's shipments endpoint (GET /shipments) filtered by a date range to pull historical shipping data, then aggregate it in JavaScript transformers to calculate KPI metrics.

Create a query to fetch shipments from the last 30 days. ShipStation's shipments endpoint supports shipDateStart and shipDateEnd parameters. Set pageSize to 500 and plan for pagination if you ship high volumes.

Create a JavaScript transformer (or a standalone JavaScript query) that aggregates the shipment data:
- Total shipments by store (sales channel) — for a Bar Chart by store name
- Total shipments by carrier — for a Pie Chart of carrier distribution
- Total shipping cost by day — for a Line Chart showing spending trends
- Average cost per shipment — displayed as a Stat metric

Drag a Stat component onto the canvas for each top-level KPI. Drag a Chart component for the Bar Chart (shipments by store) and configure it with the aggregated data. A second Chart component shows carrier distribution as a Pie chart.

Add a DateRange component at the top of the dashboard to let users adjust the analysis window. When the date range changes, all queries that reference {{ dateRange.startDate }} and {{ dateRange.endDate }} automatically refresh, updating all metrics and charts simultaneously.

```
// JavaScript transformer for ShipStation shipments analytics
// Aggregates shipment data for Charts and KPI metrics
const shipments = data.shipments || [];

// Aggregate by store (sales channel)
const byStore = shipments.reduce((acc, s) => {
  const store = s.storeName || 'Unknown';
  acc[store] = (acc[store] || 0) + 1;
  return acc;
}, {});

// Aggregate by carrier
const byCarrier = shipments.reduce((acc, s) => {
  const carrier = s.carrierCode || 'Unknown';
  acc[carrier] = (acc[carrier] || 0) + 1;
  return acc;
}, {});

// Calculate total shipping cost
const totalCost = shipments.reduce((sum, s) => {
  return sum + (s.shipmentCost || 0);
}, 0);

// Format for Chart component
return {
  byStore: Object.entries(byStore).map(([name, count]) => ({ name, count })),
  byCarrier: Object.entries(byCarrier).map(([carrier, count]) => ({ carrier, count })),
  totalCost: totalCost.toFixed(2),
  avgCost: shipments.length > 0 ? (totalCost / shipments.length).toFixed(2) : '0.00',
  totalShipments: shipments.length
};
```

**Expected result:** The analytics dashboard displays total shipments by sales channel as a Bar Chart, carrier distribution as a Pie Chart, and total shipping spend and average cost per shipment as KPI Stat components. Changing the date range refreshes all charts and metrics simultaneously.

## Best practices

- Store ShipStation API Key and Secret in Retool configuration variables marked as secret — never embed them in query bodies or resource configurations directly.
- Respect ShipStation's 40-requests-per-minute rate limit by using Manual trigger mode for non-critical queries and combining related data fetches into fewer, larger queries.
- Use ShipStation's orderStatus filter in every orders query rather than fetching all orders and filtering client-side — server-side filtering is dramatically faster and reduces API usage.
- Set testLabel: true during development when testing label creation to avoid generating real carrier charges or consuming carrier label balance.
- Build label creation workflows with confirmation dialogs — label purchases are immediate and difficult to void, so operators should explicitly confirm their carrier and service selection before the API call fires.
- Log all ShipStation write operations (label creation, order updates, status changes) to your own database for audit purposes, since ShipStation's native history view is limited.
- For high-volume operations, pre-aggregate ShipStation analytics in a nightly Retool Workflow and store results in your database — loading pre-computed KPIs is faster and more reliable than computing them from raw API data on each dashboard load.

## Use cases

### Build a cross-channel daily shipping queue

Create a Retool fulfillment dashboard that fetches all ShipStation orders with status 'awaiting_shipment' across all connected stores. Display them in a Table with columns for order number, channel (Shopify, Amazon, etc.), customer name, items ordered, total weight, and days since order. Allow operators to filter by sales channel or carrier preference, select multiple orders, and trigger bulk label creation. Show a count of unshipped orders as a KPI metric at the top.

Prompt example:

```
Build a Retool shipping queue that queries ShipStation for all orders with orderStatus 'awaiting_shipment'. Display in a Table with columns: orderNumber, storeName (sales channel), customerName, orderDate, item count, orderTotal, and requestedShippingService. Add a Select dropdown to filter by store. Show a stat at the top with total count of orders awaiting shipment. Add a 'Mark as Shipped' button for selected rows that calls the ShipStation mark-as-shipped endpoint with a tracking number input.
```

### Create a carrier performance analytics dashboard

Build a ShipStation analytics panel that queries shipment history and calculates carrier performance metrics: on-time delivery rates, average transit days, and cost per shipment by carrier and service level. Display results in Charts and a comparative Table. Allow filtering by date range and carrier. Identify which carrier-service combinations are most cost-effective for different destination zones.

Prompt example:

```
Create a Retool analytics dashboard that fetches ShipStation shipments from the last 30 days using the shipments endpoint with a date range filter. Group shipments by carrierCode and serviceCode using a JavaScript transformer. Show a Bar Chart of shipment count by carrier, a Table with average cost and estimated vs. actual delivery time by service, and a stat showing total shipping spend for the period. Add date range pickers to filter the data.
```

### Build an order exception management panel

Create a Retool panel specifically for handling ShipStation orders that need manual attention — orders tagged with specific exception tags, orders with address validation failures, or orders held for manual review. Display exception details in a Table and provide action buttons to void labels, update shipping addresses, re-route to a different carrier, or add internal notes. Log all exception handling actions to your database for audit purposes.

Prompt example:

```
Build a Retool exception queue that queries ShipStation for orders with orderStatus 'on_hold' or tagged with 'address_issue' or 'exception'. Show a Table with orderNumber, holdReason, customer address, flagged field, and days in hold. Add action buttons: 'Update Address' (opens a Form modal to edit the shipping address via the ShipStation order update endpoint), 'Release Hold' (changes status to awaiting_shipment), and 'Cancel Order'. Write all actions to an audit_log table in PostgreSQL.
```

## Troubleshooting

### All ShipStation API queries return 401 Unauthorized

Cause: The Basic Auth credentials are incorrect, the API Key or Secret is stored with extra whitespace or characters, or the configuration variables are not correctly referenced in the resource's Username and Password fields.

Solution: In the Resources tab, click your ShipStation resource and verify the Username field contains {{ environment.variables.SHIPSTATION_API_KEY }} and Password contains {{ environment.variables.SHIPSTATION_API_SECRET }}. Then go to Settings → Configuration Variables and confirm both variables exist with the correct values — copy-paste them again from ShipStation's API Settings page if unsure. Check for leading/trailing whitespace in the variable values.

### ShipStation orders query returns 429 Too Many Requests

Cause: ShipStation enforces a rate limit of 40 API requests per minute. Retool dashboards with many auto-running queries that all load simultaneously can exhaust this limit quickly.

Solution: Convert non-critical queries from Auto to Manual trigger mode, adding explicit Refresh buttons for each data section. Combine multiple small queries into fewer larger queries where possible — for example, fetch orders and stores in a single query and split the data client-side using transformers. In Retool Workflows, add a Wait block between queries when processing batch operations.

### Label creation query returns 'Invalid carrier code' or 'Service not available for this weight/zone'

Cause: The carrierCode or serviceCode values sent in the label creation request don't match what ShipStation supports for the given shipment parameters — weight, dimensions, origin, and destination combination.

Solution: Use ShipStation's getrates endpoint (POST /shipments/getrates) to retrieve valid carrier and service options for the specific shipment before attempting label creation. Display these rates in a Select component and use the returned carrierCode and serviceCode values directly in the label creation request rather than hardcoding them. This ensures the combination is always valid for the shipment.

### Shipment data is missing stores or orders from certain sales channels

Cause: ShipStation filters results by store when a storeId parameter is included. Omitting this parameter returns orders from all stores, but if the authenticated API key belongs to a sub-user with limited store access, some stores may be excluded.

Solution: Ensure the API credentials belong to the main ShipStation account owner rather than a sub-user with restricted store permissions. To fetch all stores, first call GET /stores to retrieve the full list of connected stores and their IDs. If specific store IDs are missing from the list, check the store's connection status in ShipStation's store settings.

## Frequently asked questions

### Does ShipStation have a native Retool connector?

No. ShipStation connects to Retool via a generic REST API Resource using HTTP Basic Auth with your API Key and Secret. All ShipStation endpoints — orders, shipments, stores, carriers, products, and labels — are accessible from Retool's query editor once the resource is configured with the correct base URL (https://ssapi.shipstation.com) and credentials.

### Can Retool access all my ShipStation connected stores and channels?

Yes, as long as the API credentials belong to the main ShipStation account owner. The orders and shipments endpoints return data from all connected stores by default. Use the storeId parameter to filter to a specific channel, or fetch the list of stores first using GET /stores and bind a Select component to let users filter by channel dynamically.

### How do I handle ShipStation's pagination in Retool for large order volumes?

ShipStation returns a total field with the total count of matching orders and uses page and pageSize parameters for pagination. In your Retool query, bind the page parameter to a Number Input component or track page state in a variable. Add Previous and Next buttons that decrement and increment the page value respectively. Display 'Showing X of Y orders' using the total field from the response and the current page offset.

### Can I void a shipping label from Retool using the ShipStation API?

Yes. Use ShipStation's void label endpoint: POST /shipments/voidlabel with the shipmentId in the request body. Create a query in Retool for this endpoint, triggered by a 'Void Label' button in your app, and always include a confirmation dialog. Note that voiding a label depends on the carrier's void window — most carriers allow voiding within 24-48 hours, but some restrict it. ShipStation will show the void status in its dashboard.

### What's the difference between ShipStation's orderStatus values and how do I filter by them in Retool?

ShipStation uses these orderStatus values: awaiting_payment (order placed, payment not yet received), awaiting_shipment (paid, ready to ship — the most common status for fulfillment queues), pending_fulfillment (sent to a 3PL or fulfillment service), on_hold (manually held for review), shipped (label created and marked as shipped), cancelled (order cancelled). In Retool, bind a Select component to these values and pass the selection as the orderStatus parameter in your orders query.

---

Source: https://www.rapidevelopers.com/retool-integrations/shipstation
© RapidDev — https://www.rapidevelopers.com/retool-integrations/shipstation
