# How to Integrate Retool with Shippo

- Tool: Retool
- Difficulty: Beginner
- Time required: 15 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Shippo by adding a REST API Resource with Shippo's API base URL and your API token as Bearer authentication. Once configured, build queries to compare carrier rates, generate shipping labels, and track packages. The setup takes about 15 minutes and gives you a custom shipping label tool and rate comparison dashboard without any code outside of Retool.

## Why Connect Retool to Shippo?

Shippo's multi-carrier API unlocks discounted rates and label generation across 85+ carriers from a single integration. Connecting it to Retool lets you build a custom shipping tool tailored to your team's exact workflow — one that your operations staff can use without touching code or navigating Shippo's dashboard. Whether you need a simple label generator, a carrier rate comparison panel, or a full order-to-label workflow that reads from your database and writes back tracking numbers, Retool's query builder and component library give you the building blocks.

The Shippo API uses a two-step model: first create a Shipment object (defining origin, destination, and parcels), then retrieve the list of available Rates on that shipment and purchase the one you want by creating a Transaction. This maps naturally to a Retool workflow — Form inputs collect address details, a query creates the Shipment and returns rates, a Table shows the rate options, and a button purchase query fires when the operator selects their preferred carrier and service level.

Because Retool proxies all Shippo API calls server-side, your Shippo token never reaches the browser. This is particularly valuable for label purchase operations — transaction endpoints that actually charge your Shippo balance require server-side execution. The Retool pattern ensures these sensitive operations happen server-side by design, with no additional infrastructure required.

## Before you start

- A Shippo account (free tier available, paid plans for higher volume and discounted rates)
- A Shippo API token from your Shippo dashboard under API → Test Tokens (for testing) or Live Tokens (for production)
- A Retool account (Cloud or self-hosted) with permission to add Resources
- Basic understanding of shipping concepts: origin/destination addresses, parcel dimensions and weight, carrier service levels

## Step-by-step guide

### 1. Get your Shippo API token

Log into your Shippo dashboard at app.goshippo.com. In the left sidebar, navigate to API in the settings section. Shippo provides separate Test and Live tokens — test tokens connect to Shippo's sandbox environment where label purchases do not charge your balance and generate sample labels, while live tokens connect to production and result in real carrier charges and labels.

For initial Retool setup and development, copy your Test token. You can switch to the Live token once your Retool app is working correctly. Test tokens are prefixed with 'shippo_test_' and live tokens are prefixed with 'shippo_live_'. Both formats work identically with the API — the prefix determines which environment the calls execute in.

Copy the token value. In Retool, you will store this in a configuration variable rather than pasting it directly into the resource form. Navigate to Settings → Configuration Variables in your Retool account. Click Add Variable, name it SHIPPO_API_TOKEN, paste the token as the value, and check the Mark as Secret checkbox. This ensures the token resolves only server-side and is never sent to the browser.

**Expected result:** You have a Shippo API token stored in a Retool configuration variable marked as secret, ready to reference in the resource configuration.

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

Open Retool and go to the Resources tab in the left sidebar of the home page. Click Add Resource in the top-right corner. In the resource type selector, find and click REST API.

In the configuration form, set the following:
- Name: 'Shippo API' or 'Shippo - Test' to distinguish from a future production resource
- Base URL: https://api.goshippo.com — this is Shippo's API root URL. Individual endpoint paths like /shipments, /rates, and /transactions are appended in each query.
- Authentication: Select Bearer Token from the Authentication dropdown. In the Bearer Token field, enter {{ environment.variables.SHIPPO_API_TOKEN }} to reference the configuration variable you created in the previous step.
- Headers: Click Add Header and add a header with Name: SHIPPO-API-VERSION and Value: 2018-02-08 — this pins your API calls to a stable Shippo API version and is recommended by Shippo's documentation to prevent breaking changes from affecting your integration.

Click Save Changes to store the resource. The resource now appears in your Resources list and is available in the query editor's Resource dropdown.

**Expected result:** A Shippo API Resource appears in your Retool Resources list. The resource is configured with the correct base URL, Bearer Token authentication via configuration variable, and the API version header.

### 3. Create a Shippo Shipment and retrieve carrier rates

The core Shippo workflow starts with creating a Shipment object. A Shipment combines an address_from (origin), address_to (destination), and one or more parcels (weight and dimensions). The Shipment creation response includes a list of available Rate objects from all carriers you have enabled in your Shippo account.

In a Retool app, add Form components for recipient address input: Text Input fields for recipient name, street1, city, state, zip, and country. Also add Number Input fields for parcel weight (in ounces by default), length, width, and height (in inches).

Create a new query in the Code panel. Select your Shippo resource, set Method to POST, and URL to /shipments. In the Body section, select JSON and construct the shipment payload referencing your Form components:

Set this query to Manual trigger mode (it should only run when the operator clicks 'Get Rates', not automatically). Create a Button component and add an event handler that triggers this shipment creation query on click.

After the shipment query runs successfully, its response includes a rates array. Create a second query or use the first query's transformer to extract the rates. Bind the rates to a Table component. Configure the Table columns to show: provider (carrier name), servicelevel.display_name, estimated_days, and amount (price). Add a currency formatter to the amount column.

```
// Request body for POST /shipments
// Reference Retool Form component values using {{ }} syntax
{
  "address_from": {
    "name": "{{ originNameInput.value }}",
    "street1": "{{ originStreetInput.value }}",
    "city": "{{ originCityInput.value }}",
    "state": "{{ originStateInput.value }}",
    "zip": "{{ originZipInput.value }}",
    "country": "{{ originCountryInput.value || 'US' }}"
  },
  "address_to": {
    "name": "{{ recipientNameInput.value }}",
    "street1": "{{ recipientStreetInput.value }}",
    "city": "{{ recipientCityInput.value }}",
    "state": "{{ recipientStateInput.value }}",
    "zip": "{{ recipientZipInput.value }}",
    "country": "{{ recipientCountryInput.value || 'US' }}"
  },
  "parcels": [{
    "length": "{{ lengthInput.value }}",
    "width": "{{ widthInput.value }}",
    "height": "{{ heightInput.value }}",
    "distance_unit": "in",
    "weight": "{{ weightInput.value }}",
    "mass_unit": "oz"
  }],
  "async": false
}
```

**Expected result:** Clicking 'Get Rates' creates a Shippo Shipment and the rates Table populates with available carrier options including pricing, carrier name, service level, and estimated delivery days.

### 4. Purchase a label by creating a Shippo Transaction

Once the operator selects a rate from the rates Table, they can purchase the corresponding label by creating a Shippo Transaction. A Transaction references the selected Rate object's ID and instructs Shippo to actually purchase the label from the carrier.

In Retool, the rates Table has a selectedRow property accessible as {{ ratesTable.selectedRow }}. The selected rate's object ID is {{ ratesTable.selectedRow.object_id }}.

Create a new query in the Code panel. Select your Shippo resource, set Method to POST, and URL to /transactions. In the Body section, select JSON and use the selected rate ID:

Add a Button component labeled 'Purchase Label' and configure it to only be enabled when a rate is selected: set the Disabled property to {{ !ratesTable.selectedRow || !ratesTable.selectedRow.object_id }}. Add a confirmation dialog: in the Button's Interaction settings, enable 'Require confirmation' and set the message to 'Purchase {{ ratesTable.selectedRow.provider }} label for ${{ ratesTable.selectedRow.amount }}?'.

Wire the button to trigger the transaction query on click. In the query's On Success event handler, add a 'Show notification' action with message 'Label purchased successfully' and type 'success'. Also add a second event handler that opens the label URL: use 'Open URL' action with URL set to {{ purchaseLabelQuery.data.label_url }}.

For warehouse operations, you may want to print the label automatically. The label_url from Shippo is a direct link to a PDF or ZPL file depending on your Shippo account's label format settings. You can embed this URL in an IFrame component in your Retool app to show the label inline for printing.

```
// Request body for POST /transactions
// Creates a label purchase for the selected Shippo rate
{
  "rate": "{{ ratesTable.selectedRow.object_id }}",
  "label_file_type": "PDF",
  "async": false
}
```

**Expected result:** Selecting a rate from the Table and clicking 'Purchase Label' creates a Shippo Transaction. The label PDF URL is returned in the query response, and a success notification appears in the Retool app. The label opens in a new tab or embedded IFrame for printing.

### 5. Add package tracking using Shippo's tracking endpoint

Shippo provides a tracking endpoint that returns the latest status and event history for any shipment, whether it was created through Shippo or not. This lets you build a universal tracking panel in Retool for all of your outbound orders.

Create a new query with Method GET and URL /tracks/{{ carrierSelect.value }}/{{ trackingInput.value }}. The Shippo tracking endpoint requires two path parameters: the carrier code (e.g., 'usps', 'ups', 'fedex', 'dhl_express') and the carrier tracking number (not the Shippo object ID). Add a Text Input component for the tracking number and a Select component populated with common carrier codes.

The tracking response includes a tracking_status object with the most recent status, a location, and a status_date, plus an array of tracking_history events. Create a JavaScript transformer to format these for display:

Bind the transformer output to a Table component showing the event history. Add a separate stat display using Text components to show the top-level tracking_status.status, eta (estimated delivery date), and carrier name from the response.

For bulk tracking across all recent orders, create a second query that fetches orders from your database with tracking numbers, then use a JavaScript query to call Shippo's tracking endpoint for each and aggregate the results. Note that for high order volumes, this is better implemented as a Retool Workflow that runs on a schedule and writes tracking status updates to your database, rather than fetching live on each page load.

```
// JavaScript transformer for Shippo tracking response
// Formats tracking history events for a Retool Table
const response = data;
const events = response.tracking_history || [];

return events.map(event => ({
  date: event.status_date
    ? new Date(event.status_date).toLocaleDateString()
    : 'N/A',
  time: event.status_date
    ? new Date(event.status_date).toLocaleTimeString()
    : 'N/A',
  status: event.status,
  description: event.status_details || event.status,
  location: event.location
    ? [event.location.city, event.location.state, event.location.country]
        .filter(Boolean).join(', ')
    : 'Location unavailable'
})).reverse(); // newest event first
```

**Expected result:** Entering a tracking number and carrier code displays the package's current status and full event history in the Retool app. The tracking history Table shows events in reverse chronological order with date, time, status, description, and location.

## Best practices

- Store your Shippo API token in a Retool configuration variable marked as secret (Settings → Configuration Variables) rather than embedding it in queries or the resource form directly.
- Use Shippo's test token during development and testing, then switch to the live token only when deploying to production — test tokens prevent accidental charges and real label creation.
- Always set async: false in Shipment and Transaction creation requests to receive synchronous responses — asynchronous Shippo processing requires polling and adds complexity unnecessary for Retool-based workflows.
- Require confirmation dialogs on label purchase buttons to prevent accidental purchases — each Transaction charges your Shippo balance at the carrier's rate.
- Store Shippo tracking numbers and label URLs back to your own database after purchase using a chained query in the event handler's On Success step — Shippo-hosted label URLs are time-limited.
- Pin the SHIPPO-API-VERSION header in your REST API Resource configuration to prevent Shippo API changes from breaking your integration without warning.
- Add a transformer to the rates query that sorts rates by amount ascending so the cheapest carrier always appears first in the Table — operators should see the most cost-effective option by default.

## Use cases

### Build a rate comparison and label generation tool

Create a Retool app where warehouse staff enter a recipient address, package weight, and dimensions using Form components. On submit, the app creates a Shippo Shipment and retrieves all available carrier rates. Display the rates in a Table sorted by price, showing carrier, service level, estimated delivery days, and cost. A 'Purchase Label' button on the selected row calls Shippo's transactions endpoint to buy the label and displays the label URL as a printable link.

Prompt example:

```
Build a Retool shipping label tool. A Form at the top collects: recipient name, address line 1, city, state, zip, country, and package weight in ounces. On 'Get Rates' button click, create a Shippo shipment and display returned rates in a Table with columns: carrier, service name, estimated days, and price. When a row is selected, enable a 'Purchase Label' button that creates a Shippo transaction for that rate and shows the label_url in an iframe below the table.
```

### Create an order-to-label pipeline connected to your database

Build a fulfillment dashboard that reads pending orders from your PostgreSQL database, pre-fills shipping address fields from the order record, and allows operators to generate a Shippo label with one click. On label purchase, write the Shippo tracking number and label URL back to the orders table and update the order status to 'Shipped'. Show a count of remaining unshipped orders as a KPI metric at the top of the dashboard.

Prompt example:

```
Create a Retool fulfillment panel that queries the PostgreSQL database for orders with status 'Ready to Ship'. Display them in a Table. When an operator clicks a row, pre-fill a shipping Form with the customer's address from the order record. Add a 'Get Rates' button that creates a Shippo shipment using those details and shows rates in a second Table. After selecting a rate and clicking 'Buy Label', update the orders table to set the tracking_number and label_url fields and change status to 'Shipped'.
```

### Build a package tracking dashboard from Shippo tracking data

Create a tracking panel where customer service agents enter a Shippo tracking number or carrier tracking number to retrieve the latest package status and event history. Display the tracking events as a Timeline component showing each scan event with location and timestamp. Include a bulk tracking view that queries multiple orders from the database and their associated tracking numbers to show their current Shippo status in a Table.

Prompt example:

```
Build a Retool tracking dashboard. Add a Text Input for tracking number and a Select for carrier code. On search, call Shippo's tracking endpoint and display the tracking status, carrier, and eta in a stat display. Show all tracking events in a Table with columns: date, time, description, and location. Below, add a bulk tracking Table that queries the database for all orders shipped in the last 7 days and shows their Shippo tracking status fetched from the tracking endpoint.
```

## Troubleshooting

### Shipment creation returns 400 Bad Request with 'Invalid address' or validation errors

Cause: Shippo validates addresses against carrier requirements. Common issues include missing required fields (street1, city, state/province, zip, country), unsupported country codes, or incorrectly formatted postal codes.

Solution: Check the error response body — Shippo returns detailed field-level validation errors. Ensure all address fields are populated using the Form component values. Country codes must be 2-letter ISO codes (e.g., 'US' not 'United States'). US zip codes must be 5-digit numeric strings. For address validation before shipment creation, use Shippo's address validation endpoint (POST /addresses with validate: true) to verify addresses interactively as users type.

### Rates array is empty after shipment creation — no carrier options shown

Cause: No carriers in your Shippo account support the specified origin-destination combination, parcel dimensions, or service requirements. This can also happen when using test mode with carriers that don't support test transactions.

Solution: In your Shippo dashboard, check which carriers are activated under Carriers & Connections. Ensure at least USPS (which is enabled by default for US accounts) is active. Verify your parcel weight and dimensions are within carrier limits — very heavy or oversized parcels may exclude most carriers. In test mode, some carriers return no rates; switch to a USPS-only test to verify your setup works before adding other carriers.

### Transaction purchase succeeds but label_url returns a 404 when opened

Cause: Shippo label URLs are time-limited. Labels are accessible immediately after creation but may expire after a period. Alternatively, the label may still be generating (though async: false should prevent this).

Solution: Download and store the label PDF immediately after purchase rather than relying on the Shippo-hosted URL for long-term access. In the On Success event handler of your transaction query, use a Retool Workflow or a second query to download the label content and store it in your own storage (e.g., Amazon S3 or Retool Storage) and save the permanent URL to your database.

### Tracking endpoint returns 404 or 'Tracking number not found'

Cause: The carrier code in the URL path doesn't match Shippo's expected carrier slug, or the tracking number has not yet been scanned into the carrier's system (this is common for newly purchased labels).

Solution: Check Shippo's documentation for the exact carrier code slug required in the tracking URL path — for example, use 'fedex' not 'FedEx' or 'FEDEX'. For newly purchased labels, tracking data may not appear for 12-24 hours while the carrier scans the first package event. Add a note in your Retool app that tracking may not be immediately available for recently created labels.

## Frequently asked questions

### Does Shippo have a native Retool connector?

No. Shippo connects to Retool via a generic REST API Resource. You configure the base URL, Bearer Token authentication, and API version header once in the resource settings, and then build all queries — shipment creation, rate retrieval, label purchase, and tracking — using Retool's visual query builder with GET/POST requests to Shippo's API endpoints.

### Can Retool generate and print Shippo labels directly?

Retool can retrieve the label_url from a Shippo Transaction response and display it in an IFrame component for in-browser viewing and printing. For direct printing to a label printer (e.g., Zebra ZPL format), request label_file_type: 'ZPLII' in the Transaction body and use the returned label_url to download the ZPL file. Automated printing from Retool to a locally connected label printer requires a browser print bridge, which is outside Retool's native capabilities.

### How do I use Shippo's discounted carrier rates in Retool?

Shippo negotiates discounted rates with USPS and other carriers that are available to all Shippo accounts. These discounted rates appear automatically in the rates array returned by the Shipment creation endpoint — you do not need to configure anything additional. The rates displayed in your Retool Table will include Shippo's discounted pricing alongside standard commercial rates, clearly labeled by carrier and service level.

### Can I connect multiple carrier accounts to Shippo and access them from Retool?

Yes. In your Shippo dashboard under Carriers & Connections, you can add your own UPS, FedEx, DHL, and other carrier accounts to access your negotiated rates. These accounts become available automatically in the rates returned for any Shipment created through the Shippo API. Your Retool integration does not change — all carrier rates are returned through the same Shipment creation query.

---

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