Create a Label | ShipEngine

🎉ShipEngine is becoming ShipStation API🎉

Over the next few months you'll notice the ShipEngine website, documentation portal, and dashboard being rebranded as ShipStation API. For our ShipEngine customers, you don't need to take any action or change any of your integrations in any way. All endpoints will remain the same and continue to function as they always have.

To learn more about what's coming, review our New ShipStation API page.

Create a Shipping Label

This guide will walk you through how to create your first shipping label using ShipStation API and provides the details and context you need to understand how this process works.

Before you begin:

When you create a shipping label with ShipStation API, you'll generally follow these basic steps (described in detail below):

  1. Prepare your request
  2. Send the request
  3. Download the label

In this tutorial, you'll request a label using the UPS services that are included with your ShipStation API account. However, the general steps are the same no matter which carrier you use.

TIP: To access your API key directly in this tutorial, sign into your ShipStation API account first. Your API key will then populate into the example requests so you can easily copy and paste into your own tools.

Step 1: Prepare Your Request

To create a label, you'll send an HTTP POST request to https://api.shipengine.com/v1/labels. From now on we'll refer to this as the /v1/labels endpoint.

Headers

There are two HTTP headers that you need to set in your request:

HTTP Header Desription
Content-Type The Content-Type header specifies the media type of your API request. ShipStation API requires all requests to be in JSON format, so this header should always be set to application/json.
API-Key For this header you'll need to pass your ShipStation API key. This is how the ShipStation API knows who you are.

Request Body

The body of your request is where you'll specify all the information about the shipping label you want to create, such as the "from" and "to" addresses, the package weight and dimensions, etc.

For this tutorial, we'll create a label with the following details:

Field Value
Delivery Service UPS Ground
Ship from address John Doe
4301 Bull Creek Rd
Austin, TX 78731
+1 555-555-5555
Ship to address Jane Doe
525 S Winchester Blvd
San Jose, CA 95128
+1 444-444-4444
Package weight 20 ounces
Package dimensions 12 x 24 x 6 inches

Here's what our label request body will look like using the above shipment details. There are additional optional fields that are left out of this request, but it does include the minimum fields recommended for shipping a package.

{
  "shipment": {
    "carrier_id": "se-123456",
    "service_code": "ups_ground",
    "ship_to": {
      "name": "Jane Doe",
      "phone": "+1 444-444-4444",
      "address_line1": "525 S Winchester Blvd",
      "city_locality": "San Jose",
      "state_province": "CA",
      "postal_code": "95128",
      "country_code": "US",
      "address_residential_indicator": "yes"
    },
    "ship_from": {
      "name": "John Doe",
      "company_name": "Example Corp",
      "phone": "+1 555-555-5555",
      "address_line1": "4301 Bull Creek Rd",
      "city_locality": "Austin",
      "state_province": "TX",
      "postal_code": "78731",
      "country_code": "US",
      "address_residential_indicator": "no"
    },
    "packages": [
      {
        "weight": {
          "value": 20,
          "unit": "ounce"
        },
        "dimensions": {
          "height": 6,
          "width": 12,
          "length": 24,
          "unit": "inch"
        }
      }
    ]
  }
}

Step 2: Send the Request

Now, we'll take the request body from Step 1 for the POST /v1/labels call and put it all together using curl. When you use POST /v1/labels to create labels with your production API key, you are purchasing the label from the selected carrier. For ShipStation Carriers, the label cost will be deducated from your account balance. For your own carriers you've connected to ShipStation API, you'll be invoiced according to that carrier's usual method.

TIP: You can copy/paste the following curl example into your Terminal, or you can change the programming language of this code sample using the dropdown list in the top right corner. We suggest selecting "curl" for this tutorial.

Example Request & Response

POST /v1/labels HTTP/1.1

{
  "shipment": {
    "carrier_id": "se-123456",
    "service_code": "ups_ground",
    "ship_to": {
      "name": "Jane Doe",
      "phone": "+1 444-444-4444",
      "email": "recipient@example.com",
      "address_line1": "525 S Winchester Blvd",
      "city_locality": "San Jose",
      "state_province": "CA",
      "postal_code": "95128",
      "country_code": "US",
      "address_residential_indicator": "yes"
    },
    "ship_from": {
      "name": "John Doe",
      "company_name": "Example Corp",
      "phone": "+1 555-555-5555",
      "email": "sender@example.com",
      "address_line1": "4301 Bull Creek Rd",
      "city_locality": "Austin",
      "state_province": "TX",
      "postal_code": "78731",
      "country_code": "US",
      "address_residential_indicator": "no"
    },
    "packages": [
      {
        "weight": {
          "value": 20,
          "unit": "ounce"
        },
        "dimensions": {
          "height": 6,
          "width": 12,
          "length": 24,
          "unit": "inch"
        }
      }
    ]
  }
}

Response

If your request was successful, you'll receive an HTTP 200 response. The response payload includes all the details you need about the label, including (but not limited to):

{
    "label_id": "se-396884371",
    "status": "completed",
    "shipment_id": "se-1080108982",
    "ship_date": "2024-01-03T08:00:00Z",
    "created_at": "2024-01-03T17:37:21.6482315Z",
    "shipment_cost": {
        "currency": "usd",
        "amount": 17.58
    },
    "insurance_cost": {
        "currency": "usd",
        "amount": 0.0
    },
    "requested_comparison_amount": null,
    "rate_details": [],
    "tracking_number": "1ZYF85760394283643",
    "is_return_label": false,
    "rma_number": null,
    "is_international": false,
    "batch_id": "",
    "carrier_id": "se-123456",
    "service_code": "ups_ground",
    "package_code": "package",
    "voided": false,
    "voided_at": null,
    "label_format": "pdf",
    "display_scheme": "label",
    "label_layout": "4x6",
    "trackable": true,
    "label_image_id": null,
    "carrier_code": "ups",
    "tracking_status": "in_transit",
    "label_download": {
        "pdf": "https://api.shipengine.com/v1/downloads/10/N7a1AuQIwk2PjYM2H2KVrA/label-396884371.pdf",
        "png": "https://api.shipengine.com/v1/downloads/10/N7a1AuQIwk2PjYM2H2KVrA/label-396884371.png",
        "zpl": "https://api.shipengine.com/v1/downloads/10/N7a1AuQIwk2PjYM2H2KVrA/label-396884371.zpl",
        "href": "https://api.shipengine.com/v1/downloads/10/N7a1AuQIwk2PjYM2H2KVrA/label-396884371.pdf"
    },
    "form_download": null,
    "qr_code_download": null,
    "insurance_claim": null,
    "packages": [
        {
            "package_id": 415397454,
            "package_code": "package",
            "weight": {
                "value": 20.00,
                "unit": "ounce"
            },
            "dimensions": {
                "unit": "inch",
                "length": 24.00,
                "width": 12.00,
                "height": 6.00
            },
            "insured_value": {
                "currency": "usd",
                "amount": 0.00
            },
            "tracking_number": "1ZYF85760394283643",
            "label_download": {
                "pdf": "https://api.shipengine.com/v1/downloads/10/HKNTqQS9yEq7rWuATnCSqQ/labelpackage-415397454.pdf",
                "png": "https://api.shipengine.com/v1/downloads/10/HKNTqQS9yEq7rWuATnCSqQ/labelpackage-415397454.png",
                "zpl": "https://api.shipengine.com/v1/downloads/10/HKNTqQS9yEq7rWuATnCSqQ/labelpackage-415397454.zpl"
            },
            "qr_code_download": null,
            "label_messages": {
                "reference1": null,
                "reference2": null,
                "reference3": null
            },
            "external_package_id": null,
            "content_description": null,
            "sequence": 1,
            "alternative_identifiers": []
        }
    ],
    "charge_event": "carrier_default",
    "alternative_identifiers": []
}

Step 3: Download the Label

In your response, the label_download object includes the URLs you can use to download the label in various formats.

{
  "label_download": {
    "pdf": "https://api.shipengine.com/v1/downloads/10/XNGDhq7uZ0CAEt5LOnCxIg/label-7764944.pdf",
    "png": "https://api.shipengine.com/v1/downloads/10/XNGDhq7uZ0CAEt5LOnCxIg/label-7764944.png",
    "zpl": "https://api.shipengine.com/v1/downloads/10/XNGDhq7uZ0CAEt5LOnCxIg/label-7764944.zpl",
    "href": "https://api.shipengine.com/v1/downloads/10/XNGDhq7uZ0CAEt5LOnCxIg/label-7764944.pdf"
  }
}

The label download formats include:

Format Description Uses
pdf Adobe PDF file A common format that's supported by most printers. Also a good format for email attachments when sending shipping labels to customers.
png PNG image file PNG images are great for embedding in emails, web pages, or mobile apps.
zpl Zebra Printer file If you print labels using a Zebra Printer, then ZPL is probably the best file format to use. However, please note that not all carriers support the ZPL format.

These URLs are just like any other URLs in that you can paste them into a browser to download the file. You can also download the label using curl.

Congratulations! You've downloaded your first label!

Automated Carrier Selection with Rate Shopper

If you don't want to manually select a carrier and service for each label, you can use the Rate Shopper endpoint to automate this decision based on cost, speed, or value optimization.

When to Use Rate Shopper

Rate Shopper is ideal for:

How It Works

Instead of specifying carrier_id and service_code in your shipment, you provide a rate_shopper_id in the URL path. ShipStation API will:

  1. Retrieve rates from all your connected wallet carriers
  2. Select the best rate according to your strategy
  3. Create and return the label in one step

Example Request

POST /v1/labels/rate_shopper_id/{rate_shopper_id}

This example uses the cheapest strategy to automatically select the lowest-cost carrier and service:

POST /v1/labels/rate_shopper_id/cheapest HTTP/1.1

{
  "shipment": {
    "ship_to": {
      "name": "Jane Doe",
      "phone": "+1 444-444-4444",
      "address_line1": "525 S Winchester Blvd",
      "city_locality": "San Jose",
      "state_province": "CA",
      "postal_code": "95128",
      "country_code": "US",
      "address_residential_indicator": "yes"
    },
    "ship_from": {
      "name": "John Doe",
      "company_name": "Example Corp",
      "phone": "+1 555-555-5555",
      "address_line1": "4301 Bull Creek Rd",
      "city_locality": "Austin",
      "state_province": "TX",
      "postal_code": "78731",
      "country_code": "US",
      "address_residential_indicator": "no"
    },
    "packages": [
      {
        "weight": {
          "value": 20,
          "unit": "ounce"
        },
        "dimensions": {
          "height": 6,
          "width": 12,
          "length": 24,
          "unit": "inch"
        }
      }
    ]
  },
  "label_format": "pdf",
  "label_layout": "4x6"
}

Response

The response includes which carrier and service were automatically selected:

{
  "label_id": "se-396884371",
  "status": "completed",
  "shipment_id": "se-1080108982",
  "ship_date": "2026-02-27T08:00:00Z",
  "created_at": "2026-02-27T17:37:21.648Z",
  "shipment_cost": {
    "currency": "usd",
    "amount": 17.58
  },
  "insurance_cost": {
    "currency": "usd",
    "amount": 0.0
  },
  "tracking_number": "1ZYF85760394283643",
  "is_return_label": false,
  "is_international": false,
  "batch_id": "",
  "carrier_id": "se-5904054",
  "service_code": "ups_ground",
  "carrier_code": "ups",
  "package_code": "package",
  "voided": false,
  "label_format": "pdf",
  "label_layout": "4x6",
  "trackable": true,
  "tracking_status": "in_transit",
  "rate_shopper_id": "cheapest",
  "label_download": {
    "pdf": "https://api.shipengine.com/v1/downloads/10/xxx/label-396884371.pdf",
    "png": "https://api.shipengine.com/v1/downloads/10/xxx/label-396884371.png",
    "zpl": "https://api.shipengine.com/v1/downloads/10/xxx/label-396884371.zpl",
    "href": "https://api.shipengine.com/v1/downloads/10/xxx/label-396884371.pdf"
  },
  "form_download": null,
  "packages": [
    {
      "package_id": 415397454,
      "package_code": "package",
      "weight": {
        "value": 20.00,
        "unit": "ounce"
      },
      "dimensions": {
        "unit": "inch",
        "length": 24.00,
        "width": 12.00,
        "height": 6.00
      },
      "insured_value": {
        "currency": "usd",
        "amount": 0.00
      },
      "tracking_number": "1ZYF85760394283643",
      "label_messages": {
        "reference1": null,
        "reference2": null,
        "reference3": null
      },
      "external_package_id": null,
      "sequence": 1
    }
  ],
  "charge_event": "carrier_default"
}

Notice the rate_shopper_id field in the response, which confirms the strategy used, and the automatically selected carrier_id, service_code, and carrier_code.

Important Requirements

⚠️ Critical: When using Rate Shopper, you must NOT include any of these fields in your shipment object:

If any of these fields are present, the API will return a validation error. Rate Shopper determines these values automatically.

Rate Shopper Strategies

Strategy Path Parameter Use Case
Cheapest /cheapest Minimize shipping costs for non-urgent deliveries
Fastest /fastest Time-critical shipments where speed is paramount
Best Value /best_value Balance cost and speed (arrives within 4 days)

Troubleshooting

No rates available

If you receive a 404 error with message "No rates found", verify:

If you need to ship to a specific carrier, use the standard label creation endpoint (POST /v1/labels) with explicit carrier_id and service_code.

Cancel a Label

If you need to cancel a label due to a mistake or because something about the package changed after you created the label, you can do so! Check out our guide on voiding a label to learn more.

What's Next?

There are multiple ways to create labels with ShipStation API, each suited for different workflows:

  1. Automated carrier selection with Rate Shopper
  2. Create a label from a rate
  3. Create a label from a shipment
  4. Create labels in bulk

Finally, explore the following options to customize or make your workflow more efficient: