Skip to content
Last updated

Shipment Numbers & Uniqueness

The shipment_number is a user-friendly, human-readable identifier for shipments. Understanding how it works and its relationship to external_shipment_id is important for proper integration.

What is shipment_number?

The shipment_number is equivalent to orderNumber in the v1 API and Order Number in the ShipStation UI. It's designed to be:

  • Human-readable: Easy to reference in conversations and support tickets
  • Not unique: Multiple shipments can have the same shipment_number (just like Order Numbers in V1/UI)
  • Optional: You can provide your own or let the system generate one
  • Mutable: Can be updated after creation (unlike external_shipment_id)

v1 to v2 Mapping

v1 / UI Termv2 TermPurposeUniqueness
orderNumbershipment_numberUser-friendly display numberNot enforced
orderKeyexternal_shipment_idSystem identifier for the orderNot enforced per-shipment (multiple shipments can share the same value)

Uniqueness Rules

NO Enforced Uniqueness on shipment_number

The shipment_number field has NO uniqueness enforcement:

  • ✅ Multiple shipments can have the same shipment_number
  • ✅ This mirrors the behavior of Order Number in V1 API and ShipStation UI
  • ✅ You will not receive errors for duplicate shipment_number values

This allows for common scenarios like:

  • Multiple partial shipments from the same order sharing the same display number
  • Re-creating canceled shipments with the same number
  • Using simple sequential numbers without complex collision handling

How external_shipment_id Works

The external_shipment_id is functionally identical to orderKey in the V1 API:

  • Identifies the ORDER, not the individual shipment
  • Multiple shipments can (and often do) share the same external_shipment_id
  • Common in split-shipping scenarios where one order results in multiple shipments
  • Immutable once set (cannot be changed after shipment creation)
FieldUniquenessMutabilityPurpose
shipment_numberNot enforced (duplicates allowed)Can be updatedHuman-readable display number
external_shipment_idNot enforced per-shipment (multiple shipments can share)Cannot be changedLinks shipments to the source order
Split Shipping Example

When you split-ship one order into two shipments, both shipments typically share the same external_shipment_id (to identify they came from the same order) and the same shipment_number (to show the same order number to customers).

Automatic Population Rules

ShipStation follows a duplication rule when fields are not provided:

Scenario 1: You Provide Both

{
  "external_shipment_id": "ORDER-2024-12345",
  "shipment_number": "ORD-12345",
  ...
}

Result: Both values are used as provided.

Scenario 2: You Provide Only external_shipment_id

{
  "external_shipment_id": "ORDER-2024-12345",
  // shipment_number not provided
  ...
}

Result:

  • external_shipment_id = "ORDER-2024-12345" (your value)
  • shipment_number = "ORDER-2024-12345" (duplicated from external_shipment_id)
Common Pattern

Many integrations only provide external_shipment_id and let the system duplicate it to shipment_number. This works well if your external IDs are already human-readable.

Scenario 3: You Provide Only shipment_number

{
  // external_shipment_id not provided
  "shipment_number": "ORD-12345",
  ...
}

Result:

  • shipment_number = "ORD-12345" (your value)
  • external_shipment_id = "se-123456789" (system-generated based on shipment_id)

Scenario 4: You Provide Neither

{
  // Neither field provided
  ...
}

Result: Both are auto-generated based on the internal shipment_id:

  • external_shipment_id = "se-123456789"
  • shipment_number = "se-123456789"
Not Recommended

Relying on auto-generated values makes it harder to correlate ShipStation records with your own system. Always provide at least external_shipment_id.

Best Practices

Use Meaningful Identifiers

// ✅ Good - Clear, readable identifiers
{
  "external_shipment_id": "SHOPIFY-ORDER-98765",
  "shipment_number": "WEB-2024-0615-001"
}

// ❌ Not ideal - Cryptic or auto-generated values
{
  "external_shipment_id": "se-123456789",
  "shipment_number": "se-123456789"
}

Split Shipping Pattern

When creating multiple shipments from the same order, use the same identifiers:

// First shipment
{
  "external_shipment_id": "ORDER-12345",  // Same for all shipments from this order
  "shipment_number": "ORDER-12345",       // Same display number
  "packages": [
    // ... first package
  ]
}

// Second shipment (split from same order)
{
  "external_shipment_id": "ORDER-12345",  // Same - identifies the order
  "shipment_number": "ORDER-12345",       // Same - customer sees one order number
  "packages": [
    // ... remaining packages
  ]
}

Leverage the Duplication Rule

If your external_shipment_id values are already user-friendly, just provide that:

{
  "external_shipment_id": "ORDER-2024-06-15-001"
  // shipment_number will automatically duplicate: "ORDER-2024-06-15-001"
}

This reduces redundancy and ensures consistency.

Updating shipment_number

Unlike external_shipment_id, you can update the shipment_number after creation:

PUT /v2/shipments/se-123456
{
  "shipment_number": "NEW-NUMBER-456"
}

Since uniqueness is not enforced, you won't encounter conflicts when updating this field.

Common Scenarios

E-commerce Integration

{
  "external_shipment_id": "SHOPIFY-98765",  // Tracks the Shopify order
  "shipment_number": "ORDER-2024-001",       // What customers see
}

Sequential Order Numbers

{
  "external_shipment_id": "UUID-a1b2c3d4",
  "shipment_number": "100001",  // Sequential counter
}

Date-Based Order Numbers

{
  "external_shipment_id": "INTERNAL-789",
  "shipment_number": "20240615-001",  // YYYYMMDD-sequence
}