# Batch Guide

`Batches` are used to purchase shipping labels for multiple existing shipments through
a coordinated asynchronous workflow. Once purchased, labels within a `Batch` can be downloaded
together in a single file, simplifying high-volume label management.

This guide explains the intended and supported process for working with batches using the EasyPost API.

---

## Prerequisites

{/* prettier-ignore */}
1. Sign up for an EasyPost account or log in to an existing account.
2. Configure Webhook URLs for both Test and Production modes.
3. Use one of EasyPost's official client libraries.
4. Review the Getting Started Guide for basic EasyPost concepts.

Related:

- [Webhooks Guide](https://docs.easypost.com/guides/getting-started)

---

## Step 1: Create a Batch of Shipments

A `batch` is a collection of existing `shipment` objects that are processed together
for label purchase and retrieval.

Shipments must be created (and optionally purchased) **before** they are added to a batch. Batches do not replace individual shipment creation.

> Note: It is recommended to keep each batch under 1,000 shipments. This best practice helps avoid timeout errors
  during the batch buying process.

### Asynchronous Process

Batch operations are processed asynchronously due to the potential volume of shipments involved.

1. Submit a `POST` request to create the batch using existing shipment IDs.
2. The batch enters a `“status”: “created”` state.
3. A webhook event is sent once the batch reaches `“status”: “created”`.

> Note: Due to the webhook update being asynchronous, carefully consider the implications of using Batches
     instead of multiple shipment requests.

If any shipments fail during batch creation, the webhook event will indicate `”status”: “creation_failed”`.

> Note: The asynchronous behavior described here applies to batch processing only. Shipment creation is a separate
  operation and must be completed before shipments are added to the batch.

#### Creating a Batch

### Example: POST /batches

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/batches \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "batch": {
      "shipments": [
        {
          "id": "shp_..."
        },
        {
          "id": "shp_..."
        }
      ]
    }
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func create() {
	client := easypost.New("EASYPOST_API_KEY")

	shipment, _ := client.GetShipment("shp_...")

	batch, _ := client.CreateBatch(shipment)

	fmt.Println(batch)
}
```

#### Java

```java
package batches;

import com.easypost.exception.EasyPostException;
import com.easypost.model.Batch;
import com.easypost.service.EasyPostClient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Create {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        List<HashMap<String, Object>> shipmentsList = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> shipmentMap = new HashMap<String, Object>();

        shipmentMap.put("id", "shp_...");

        shipmentsList.add(shipmentMap);

        HashMap<String, Object> params = new HashMap<String, Object>();

        params.put("shipment", shipmentsList);

        Batch batch = client.batch.create(params);

        System.out.println(batch);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.Shipment shipment = await client.Shipment.Retrieve("shp_...");

            EasyPost.Parameters.Batch.Create parameters = new()
            {
                Shipments = new List<EasyPost.Parameters.IShipmentParameter>()
                {
                    shipment
                }
            };

            EasyPost.Models.API.Batch batch = await client.Batch.Create(parameters);

            Console.WriteLine(JsonConvert.SerializeObject(batch, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const batch = await client.Batch.create({
    shipments: [{ id: 'shp_...' }, { id: 'shp_...' }],
  });

  console.log(batch);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$batch = $client->batch->create([
    'shipments' => [
        ['id' => 'shp_...'],
        ['id' => 'shp_...'],
    ]
]);

echo $batch;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

batch = client.batch.create(
    shipments=[
        {"id": "shp_..."},
        {"id": "shp_..."},
    ],
)

print(batch)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

batch = client.batch.create(
  shipments: [
    { id: 'shp_...' },
    { id: 'shp_...' },
  ],
)

puts batch
```

Related:

- [Shipment Object](https://docs.easypost.com/docs/batches)

---

## Step 2: Add and Remove Shipments from a Batch

After a batch is created, shipments can be added or removed as needed.

### Add Shipments

To add shipments, create and purchase the shipment object, then add it to an existing
batch using the `add_shipments` endpoint.

### Example: POST /batches/:id/add_shipments

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/batches/batch_.../add_shipments \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "shipments": [
      {
        "id": "shp_..."
      },
      {
        "id": "shp_..."
      }
    ]
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func addShipments() {
	client := easypost.New("EASYPOST_API_KEY")

	shipment, _ := client.GetShipment("shp_...")

	batch, _ := client.AddShipmentsToBatch("batch_...", shipment)

	fmt.Println(batch)
}
```

#### Java

```java
package batches;

import com.easypost.exception.EasyPostException;
import com.easypost.model.Batch;
import com.easypost.service.EasyPostClient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class AddShipments {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        HashMap<String, Object> shipment1 = new HashMap<String, Object>();
        shipment1.put("id", "shp_...");

        HashMap<String, Object> shipment2 = new HashMap<String, Object>();
        shipment2.put("id", "shp_...");

        List<HashMap<String, Object>> shipments = new ArrayList<HashMap<String, Object>>();
        shipments.add(shipment1);
        shipments.add(shipment2);

        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("shipments", shipments);

        Batch batch = client.batch.addShipments("batch_...", params);

        System.out.println(batch);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.Shipment shipment = await client.Shipment.Retrieve("shp_...");

            EasyPost.Parameters.Batch.AddShipments parameters = new()
            {
                Shipments = new List<Models.API.Shipment> { shipment },
            };

            EasyPost.Models.API.Batch batch = await client.Batch.AddShipments("batch_...", parameters);

            Console.WriteLine(JsonConvert.SerializeObject(batch, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const batch = await client.Batch.addShipments('batch_...', ['shp_...', 'shp_...']);

  console.log(batch);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$batch = $client->batch->addShipments(
    'batch_...',
    [
        'shipments' => [
            ['id' => 'shp_...'],
            ['id' => 'shp_...'],
        ]
    ]
);

echo $batch;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

batch = client.batch.add_shipments(
    "batch_...",
    shipments=[
        {"id": "shp_..."},
        {"id": "shp_..."},
    ],
)

print(batch)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

batch = client.batch.add_shipments(
  'batch_...',
  shipments: [
    { id: 'shp_...' },
    { id: 'shp_...' },
  ],
)

puts batch
```

### Remove Shipments

Shipments may be removed for various reasons, such as incorrect addresses or changes in shipping requirements.
EasyPost provides a straightforward method to remove shipments from an existing batch using the `remove_shipments` endpoint.

### Example: POST /batches/:id/remove_shipments

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/batches/batch_.../remove_shipments \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "shipments": [
      {
        "id": "shp_..."
      }
    ]
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func removeShipments() {
	client := easypost.New("EASYPOST_API_KEY")

	shipment, _ := client.GetShipment("shp_...")

	batch, _ := client.RemoveShipmentsFromBatch("batch_...", shipment)

	fmt.Println(batch)
}
```

#### Java

```java
package batches;

import com.easypost.exception.EasyPostException;
import com.easypost.model.Batch;
import com.easypost.service.EasyPostClient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class RemoveShipments {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        HashMap<String, Object> shipment1 = new HashMap<String, Object>();
        shipment1.put("id", "shp_...");

        List<HashMap<String, Object>> shipments = new ArrayList<HashMap<String, Object>>();
        shipments.add(shipment1);

        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("shipments", shipments);

        Batch batch = client.batch.removeShipments("batch_...", params);

        System.out.println(batch);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.Shipment shipment = await client.Shipment.Retrieve("shp_...");

            EasyPost.Parameters.Batch.RemoveShipments parameters = new()
            {
                Shipments = new List<Models.API.Shipment> { shipment },
            };

            EasyPost.Models.API.Batch batch = await client.Batch.RemoveShipments("batch_...", parameters);

            Console.WriteLine(JsonConvert.SerializeObject(batch, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const batch = await client.Batch.removeShipments('batch_...', ['shp_...']);

  console.log(batch);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$batch = $client->batch->removeShipments(
    'batch_...',
    [
        'shipments' => [
            ['id' => 'shp_...']
        ]
    ]
);

echo $batch;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

batch = batch.remove_shipments(
    "batch_...",
    shipments=[
        {
            "id": "shp_...",
        }
    ],
)

print(batch)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

batch = client.batch.remove_shipments(
  'batch_...',
  shipments: [
    { id: 'shp_...' },
  ],
)

puts batch
```

---

## Step 3: Create and Purchase Shipping Labels for a Batch

Purchasing shipping labels for a batch is performed as a separate asynchronous operation on an existing batch.

### Initiate the Purchase

Issue a `buy request` for the intended batch. This action triggers an asynchronous operation to generate necessary labels.

### How Batch Purchasing Works

- The buy request queues all shipments in the bach for label purchase.
- The initial response does not include label URLs.
- A webhook event is sent when the batch reaches a terminal state:
  1.  `“purchased”`
  2.  `“purchase_failed”`

Considering the support for high-volume shipments in a single Batch, the label creation process will need additional time to complete for all shipments included.

> Note: It is recommended to keep each batch under 1,000 shipments. This best practice helps avoid timeout errors
  during the batch buying process.

### Error Handling

Once all labels have been purchased and created for a batch, a webhook notification is sent to the designated application endpoint. The state of the Batch Object will be:

`“purchased”`

In the event of errors during the label creation process, the batch’s state changes to:

`“purchase_failed”`.

Any issues must be addressed by fixing or removing the failed shipments before proceeding to the `batch label` process.

#### Buying a Batch

### Example: POST /batches/:id/buy

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/batches \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "batch": {
      "shipments": [
        "from_address": {"id": "adr_..."},
        "to_address": {"id": "adr_..."},
        "parcel": {"id": "prcl_..."},
        "service": "First",
        "carrier": "USPS",
        "carrier_accounts": ["ca_..."]
      ]
    }
  }'

curl -X POST https://api.easypost.com/v2/batches/batch_.../buy \
  -u "EASYPOST_API_KEY":
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func buy() {
	client := easypost.New("EASYPOST_API_KEY")

	createdBatch, _ := client.CreateBatch(
		&easypost.Shipment{
			FromAddress: &easypost.Address{
				ID: "adr_...",
			},
			ToAddress: &easypost.Address{
				ID: "adr_...",
			},
			Parcel: &easypost.Parcel{
				ID: "prcl_...",
			},
			Service:           "First",
			Carrier:           "USPS",
			CarrierAccountIDs: []string{"ca_..."},
		},
	)

	batch, _ := client.BuyBatch(createdBatch.ID)

	fmt.Println(batch)
}
```

#### Java

```java
package batches;

import com.easypost.exception.EasyPostException;
import com.easypost.model.Batch;
import com.easypost.service.EasyPostClient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Buy {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        List<HashMap<String, Object>> shipmentsList = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> shipmentMap = new HashMap<String, Object>();

        HashMap<String, Object> fromAddress = new HashMap<String, Object>();
        fromAddress.put("id", "adr_...");
        shipmentMap.put("from_address", fromAddress);

        HashMap<String, Object> toAddress = new HashMap<String, Object>();
        toAddress.put("id", "adr_...");
        shipmentMap.put("to_address", toAddress);

        HashMap<String, Object> parcel = new HashMap<String, Object>();
        parcel.put("id", "prcl_...");
        shipmentMap.put("parcel", parcel);

        shipmentMap.put("service", "First");
        shipmentMap.put("carrier", "USPS");

        String[] carrierAccounts = { "ca_..." };
        shipmentMap.put("carrier_accounts", carrierAccounts);

        shipmentsList.add(shipmentMap);

        HashMap<String, Object> params = new HashMap<String, Object>();

        params.put("shipment", shipmentsList);

        Batch createdBatch = client.batch.create(params);

        Batch batch = client.batch.buy(createdBatch.getId());

        System.out.println(batch);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Parameters.Shipment.Create shipmentParameters = new()
            {
                ToAddress = new EasyPost.Parameters.Address.Create
                {
                    Id = "adr_..."
                },
                FromAddress = new EasyPost.Parameters.Address.Create
                {
                    Id = "adr_..."
                },
                Parcel = new EasyPost.Parameters.Parcel.Create
                {
                    Id = "prcl_..."
                },
                Service = "First",
                Carrier = "USPS",
                CarrierAccountIds = new List<string> { "ca_..." }
            };

            EasyPost.Parameters.Batch.Create parameters = new()
            {
                Shipments = new List<EasyPost.Parameters.IShipmentParameter>()
                {
                    shipmentParameters
                }
            };

            EasyPost.Models.API.Batch batch = await client.Batch.Create(parameters);

            EasyPost.Models.API.Batch batch = await client.Batch.Buy(batch.Id);

            Console.WriteLine(JsonConvert.SerializeObject(batch, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const createdBatch = await client.Batch.create({
    shipments: [
      {
        from_address: { id: 'adr_...' },
        to_address: { id: 'adr_...' },
        parcel: { id: 'prcl_...' },
        service: 'First',
        carrier: 'USPS',
        carrier_accounts: ['ca_...'],
      },
    ],
  });

  const batch = await client.Batch.buy(createdBatch.id);

  console.log(batch);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$createdBatch = $client->batch->create([
    'shipments' => [
        ['from_address' => ['id' => 'adr_...']],
        ['to_address' => ['id' => 'adr_...']],
        ['parcel' => ['id' => 'prcl_...']],
        ['service' => 'First'],
        ['carrier' => 'USPS'],
        ['carrier_accounts' => ['ca_...']],
    ]
]);

$batch = $client->batch->buy($createdBatch['id']);

echo $batch;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

createdBatch = client.batch.create(
    shipments=[
        {
            "from_address": {"id": "adr_..."},
            "to_address": {"id": "adr_..."},
            "parcel": {"id": "prcl_..."},
            "service": "First",
            "carrier": "USPS",
            "carrier_accounts": ["ca_..."],
        },
    ],
)

batch = client.batch.buy(createdBatch.id)

print(batch)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

created_batch = client.batch.create(
  shipments: [
    {
      from_address: { id: 'adr_...' },
      to_address: { id: 'adr_...' },
      parcel: { id: 'prcl_...' },
      service: 'First',
      carrier: 'USPS',
      carrier_accounts: ['ca_...'],
    },
  ],
)

batch = client.batch.buy(created_batch.id)

puts batch
```

---

## Step 4: Create and Retrieve a Batch Label

After purchasing, compile all shipping labels into a single `batch label`. All Shipments must have
a `"status": “postage_purchased”` status to generate a label. Failed purchases must be removed or resolved during the Create and Purchase Shipping Labels process.

1. Submit a `POST` request to generate a batch label, specifying the desired file format (PDF, EPL2, or ZPL).
2. Retrieve labels by downloading the batch label file containing all individual shipment labels. View an example of retrieving labels in a single PDF file

If the batch label fails to create, the batch object will return to a `“purchased”` state.

#### Create a Batch Label

### Example: POST /batches/:id/label

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/batches/batch_.../label \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "file_format": "PDF"
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func label() {
	client := easypost.New("EASYPOST_API_KEY")

	batch, _ := client.GetBatchLabels("batch_...", "PDF")

	fmt.Println(batch)
}
```

#### Java

```java
package batches;

import com.easypost.exception.EasyPostException;
import com.easypost.model.Batch;
import com.easypost.service.EasyPostClient;

import java.util.HashMap;

public class Label {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("file_format", "PDF");

        Batch batch = client.batch.label("batch_...", params);

        System.out.println(batch);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Parameters.Batch.GenerateLabel parameters = new()
            {
                FileFormat = "PDF",
            };

            EasyPost.Models.API.Batch batch = await client.Batch.GenerateLabel("batch_...", parameters);

            Console.WriteLine(JsonConvert.SerializeObject(batch, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const batch = await client.Batch.generateLabel('batch_...', 'PDF');

  console.log(batch);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$batchWithLabel = $client->batch->label(
    'batch_...',
    ['file_format' => 'PDF']
);

echo $batchWithLabel;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

batch = client.batch.label("batch_...", file_format="PDF")

print(batch)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

batch = client.batch.label(
  'batch_...',
  file_format: 'PDF',
)

puts batch
```

---

## Step 5: Use Webhooks for a Batch

Webhooks play a critical role in managing batches by providing real-time updates
at various stages:

- Step 1 - Create a Batch of Shipments
- Step 3 - Create and Purchase Shipping Labels
- Step 4 - Create and Retrieve a Batch Label

### Understanding Webhook Operations

#### Asynchronous Updates

Due to the asynchronous nature of batch operations, webhooks are used at two crucial points:

- Immediately following the initial `POST` request to create, purchase, or retrieve labels for a batch.
- Once the given action has reached a final state.

#### Error Notifications

Should any errors arise during these processes, detailed information about them is passed back in the associated webhook, enabling prompt resolution.

### Identifying Batch Events in Webhooks

#### Batch State

Evaluate the `state` of the `batch object` to check if the batch was successfully processed.

#### Errors and Resolutions

In case of errors like `“creation failed”` or `“purchase_failed”`, inspect the `“batch_status”` of each shipment object included in the batch. A summary of
successes and failures is provided to understand how many shipments need attention.

#### Example Webhook for a Batch

```json
{
  "completed_urls": [],
  "created_at": "2014-07-22T07:46:44Z",
  "description": "batch.updated",
  "id": "evt_...",
  "mode": "test",
  "object": "Event",
  "pending_urls": ["https://webhooks.example.com"],
  "previous_attributes": { "state": "label_generating" },
  "result": {
    "created_at": "2014-07-22T07:46:44Z",
    "id": "batch_...",
    "label_url": "https://amazonaws.com/.../a1b2c3.pdf",
    "mode": "test",
    "num_shipments": 1,
    "object": "Batch",
    "reference": null,
    "scan_form": null,
    "shipments": [
      { "batch_message": null, "batch_status": "created", "id": "shp_..." },
      { "batch_message": null, "batch_status": "created", "id": "shp_..." },
      { "batch_message": null, "batch_status": "created", "id": "shp_..." },
      { "batch_message": null, "batch_status": "created", "id": "shp_..." }
    ],
    "state": "label_generated",
    "status": {
      "created": 0,
      "creation_failed": 0,
      "postage_purchase_failed": 0,
      "postage_purchased": 1,
      "queued_for_purchase": 0
    },
    "updated_at": "2014-08-04T22:37:52Z"
  },
  "updated_at": "2014-08-04T22:37:51Z"
}
```

---

## Additional Resources

### Support and Troubleshooting

EasyPost offers support to assist with FAQs, troubleshooting issues, and inquiries related to the EasyPost platform.

Please visit the API Docs or the Help Center for more information.

Related:

- [API Docs](https://docs.easypost.com/docs/authentication)
- [Help Center](https://support.easypost.com/hc/en-us)