> ## Documentation Index
> Fetch the complete documentation index at: https://terminal49.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Assign Shipper, Consignee, and Other Parties

> Set the shipper, consignee, freight forwarder, notify party, customs broker, or dray carrier on shipments and containers through the Terminal49 API.

Use this guide to assign parties to your shipments from code instead of the dashboard bulk update.

## How parties and roles work

* A **party** is a company in your account, managed through [`/v2/parties`](/docs/api-docs/api-reference/parties/list-parties).
* A **party role** links one party to one shipment or container in one role.
* Roles are a list, not a field. A shipment can carry two parties as `consignee`. To replace a party, remove its role and assign a new one.

| Role                  | Tracking request creation | Shipment | Container |
| --------------------- | ------------------------- | -------- | --------- |
| `customer`            | Yes                       | Yes      | No        |
| `shipper`             | Yes                       | Yes      | No        |
| `consignee`           | Yes                       | Yes      | No        |
| `notify_party`        | Yes                       | Yes      | No        |
| `customs_broker`      | Yes                       | Yes      | No        |
| `freight_forwarder`   | Yes                       | Yes      | No        |
| `pickup_dray_carrier` | Yes                       | Yes      | Yes       |

You need an API key. See [Start here](/docs/api-docs/getting-started/start-here).

## Find or create the party

Search your parties by name:

```bash theme={null}
curl -s "https://api.terminal49.com/v2/parties?query=ACME" \
  -H "Authorization: Token YOUR_API_KEY"
```

If the party does not exist, [create it](/docs/api-docs/api-reference/parties/create-a-party):

```json Request theme={null}
{
  "data": {
    "type": "party",
    "attributes": {
      "company_name": "ACME LOGISTICS"
    }
  }
}
```

Keep the returned `data.id`. It is the `PARTY_ID` below.

## Assign roles when creating the tracking request

Pass each party as a relationship named after its role. One party per role.

Endpoint: **POST** - [https://api.terminal49.com/v2/tracking\_requests](/docs/api-docs/api-reference/tracking-requests/create-a-tracking-request)

```json Request theme={null}
{
  "data": {
    "type": "tracking_request",
    "attributes": {
      "request_type": "bill_of_lading",
      "request_number": "MEDUFR030802",
      "scac": "MSCU"
    },
    "relationships": {
      "customer": { "data": { "id": "CUSTOMER_PARTY_ID", "type": "party" } },
      "shipper": { "data": { "id": "SHIPPER_PARTY_ID", "type": "party" } },
      "consignee": { "data": { "id": "CONSIGNEE_PARTY_ID", "type": "party" } },
      "freight_forwarder": { "data": { "id": "FORWARDER_PARTY_ID", "type": "party" } }
    }
  }
}
```

The roles are copied to the shipment when it is created. The tracking request response does not list them; read them on the shipment as shown below. A party from another account fails the whole request with `422` and a pointer to the relationship.

## Assign roles to an existing shipment

Use this to add roles later, or to add a second party in the same role.

Endpoint: **POST** - [https://api.terminal49.com/v2/shipments/SHIPMENT\_ID/party\_roles](/docs/api-docs/api-reference/party-roles/assign-a-shipment-party-role)

```json Request theme={null}
{
  "data": {
    "type": "party_role",
    "attributes": {
      "role": "shipper"
    },
    "relationships": {
      "party": {
        "data": {
          "id": "PARTY_ID",
          "type": "party"
        }
      }
    }
  }
}
```

```json Response theme={null}
{
  "data": {
    "id": "PARTY_ROLE_ID",
    "type": "party_role",
    "attributes": {
      "role": "shipper",
      "roleable_type": "Shipment",
      "roleable_id": "SHIPMENT_ID",
      "created_at": "2026-09-01T14:02:11Z",
      "updated_at": "2026-09-01T14:02:11Z"
    },
    "relationships": {
      "party": {
        "data": {
          "id": "PARTY_ID",
          "type": "party"
        }
      }
    }
  },
  "included": [
    {
      "id": "PARTY_ID",
      "type": "party",
      "attributes": {
        "company_name": "ACME LOGISTICS"
      }
    }
  ]
}
```

Send one request per role. Repeat with `"role": "consignee"` and `"role": "freight_forwarder"`.

## Read the roles on the shipment

Request the shipment with `flag[parties]=true` and include the parties:

```bash theme={null}
curl -sg "https://api.terminal49.com/v2/shipments/SHIPMENT_ID?flag[parties]=true&include=party_roles.party" \
  -H "Authorization: Token YOUR_API_KEY"
```

The shipment carries a `party_roles` relationship and the `included` array holds each `party_role` and its `party`. The same flag works on `GET /v2/shipments`. `-g` stops curl from treating the brackets in `flag[parties]` as a range.

To list the roles alone, use [`GET /v2/shipments/SHIPMENT_ID/party_roles`](/docs/api-docs/api-reference/party-roles/list-shipment-party-roles).

## Replace a party

To replace the consignee:

1. List the roles and find the `party_role` with `"role": "consignee"`.
2. **DELETE** [https://api.terminal49.com/v2/shipments/SHIPMENT\_ID/party\_roles/PARTY\_ROLE\_ID](/docs/api-docs/api-reference/party-roles/remove-a-shipment-party-role). Returns `204`.
3. **POST** the new consignee.

## Assign a dray carrier to a container

Containers accept one role, `pickup_dray_carrier`:

Endpoint: **POST** - [https://api.terminal49.com/v2/containers/CONTAINER\_ID/party\_roles](/docs/api-docs/api-reference/party-roles/assign-a-container-party-role)

Read it back with [`GET /v2/containers/CONTAINER_ID/party_roles`](/docs/api-docs/api-reference/party-roles/list-container-party-roles).

## Errors

| Status                                | Cause                                                  | Fix                                                           |
| ------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------- |
| `401`                                 | The party or the record belongs to another account     | Use a party from `GET /v2/parties` and a shipment you created |
| `404`                                 | Unknown shipment, container, or party role ID          | Check the ID                                                  |
| `422` `Party has already been taken`  | The same party already has this role on the record     | Nothing to do, the role is set                                |
| `422` `'x' is not a valid role`       | Unknown role name                                      | Use a role from the table above                               |
| `422` `Role is not allowed for Cargo` | A role other than `pickup_dray_carrier` on a container | Assign it on the shipment instead                             |
