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

# Send loads to an Alvys carrier with the Tender API

> Send load tenders from your TMS to an Alvys carrier with the Tender API. Set up routing IDs, create, update, and cancel tenders, and track loads with webhooks.

Use the Tender API to send loads from your system to a carrier that runs on Alvys. You send each load as a JSON tender. The carrier accepts the tender, Alvys creates a load from it, and you follow that load with webhooks. You do not need an EDI network or an X12 identity. If you already exchange EDI 204s, the same endpoints carry the same data as JSON.

This guide has two readers:

* **Partner**: the TMS, broker, or shipper system that sends tenders.
* **Carrier admin**: the person who sets up the connection in the carrier's Alvys account.

Each section says which reader it is for.

> [!NOTE]
>
> **Getting API access**
>
> * Existing Alvys customers can obtain API access by contacting their account representative.
> * Independent Software Vendors (ISVs) should contact the Alvys Partnership team.

## What you need

*For the partner and the carrier admin.*

| Item | Who provides it | Notes |
| :- | :- | :- |
| API client credentials | Carrier admin | Created in the carrier's account under **Admin → API Access**. You call the API as the carrier. See [Authenticate with the Alvys Public API](https://docs.alvys.com/en/api/guides/authentication-1.md). |
| Six routing IDs | Agreed by both | Sender and receiver ISA ID, ISA ID qualifier, and GS ID. See [How Alvys finds the carrier and the customer](#how-alvys-finds-the-carrier-and-the-customer). |
| Carrier SCAC | Carrier admin | Required on every tender. |
| An HTTPS endpoint | Partner | Receives webhook events. See [Webhooks overview](https://docs.alvys.com/en/api/reference/webhooks/overview.md). |

The carrier's plan must include Public API access. If it does not, every call returns `402`.

### Scopes

The credential decides the scopes. The `scope` field in the token request cannot narrow them. Ask the carrier admin to assign these scopes:

| Scope | Lets you |
| :- | :- |
| `tender:create` | Create, update, and cancel tenders |
| `tender:read` | Get and search tenders |
| `tender:update` | Accept, reject, accept changes, and accept cancellations. Only needed if you accept tenders for the carrier. |
| `load:read` | Get the load and list its documents |
| `load:update` | Upload documents to the load |
| `webhook:create`, `webhook:read`, `webhook:update` | Create and manage your webhook subscription |
| `subsidiary:read` | List subsidiaries to scope your webhook |
| `customer:read` | Search locations. Only needed if you accept tenders through the API. |

> [!WARNING]
>
> Updating and cancelling a tender needs `tender:create`, not `tender:update`.

All paths below are relative to the [base URL](https://docs.alvys.com/en/api/guides/base-url.md) `https://integrations.alvys.com`. Tender, webhook, location, and subsidiary endpoints use `v1.0`. Load endpoints use `v2.0`. See [Versioning](https://docs.alvys.com/en/api/guides/versioning.md).

## How Alvys finds the carrier and the customer

*For the partner and the carrier admin.*

Every tender carries six routing IDs. They tell Alvys which carrier connection the tender belongs to, and through that connection, which of the carrier's customers the load is for.

| Tender field | Meaning |
| :- | :- |
| `SenderIsaIdQualifier`, `SenderIsaId` | Your ISA ID and its qualifier |
| `SenderGsId` | Your GS ID |
| `ReceiverIsaIdQualifier`, `ReceiverIsaId` | The carrier's ISA ID and its qualifier |
| `ReceiverGsId` | The carrier's GS ID |

The carrier stores the same six values on a connection in Alvys. Alvys compares them as exact strings. Case, spaces, and padding all count. `ZZ` and `zz` are different values.

A connection has one of two types:

* **Per-customer connection.** The connection names one customer. Every tender that matches its six IDs is booked to that customer.
* **Catch-all connection.** One connection takes tenders from any sender. Alvys books each tender to the customer whose **Company Number** equals the tender's `SenderGsId`. Exactly one customer must have that Company Number.

Alvys looks for a connection in this order:

1. A connection whose six IDs all equal the tender's six IDs.
2. If there is none, the carrier's catch-all connection.
3. If there is none, the request fails with `Integration is missing`.

Other identifiers:

* `ShipmentId` is your identifier for the tender. Alvys uses it to find the tender when you send an update or a cancellation. It becomes the **order number** of the load.
* `SCAC` is stored on the tender. It does not route the tender.
* Stop `IdCode` values do not select a location. Alvys matches stop locations by address and name.

## Without EDI: choose the routing IDs

*For the partner and the carrier admin.*

You do not need an X12 identity. Agree on six values with the carrier, and the carrier enters them on the connection. Use the qualifier `ZZ` (mutually defined) and short, uppercase IDs without spaces.

| Tender field | Example | Label on the carrier's connection |
| :- | :- | :- |
| `SenderIsaIdQualifier` | `ZZ` | **Customer ISA ID Qualifier** |
| `SenderIsaId` | `ACMESHIP` | **Customer ISA ID** |
| `SenderGsId` | `ACMESHIP` | **Customer GS ID** |
| `ReceiverIsaIdQualifier` | `ZZ` | **Your ISA ID Qualifier** |
| `ReceiverIsaId` | `FASTCARRIER` | **Your ISA ID** |
| `ReceiverGsId` | `FASTCARRIER` | **Your GS ID** |

> [!WARNING]
>
> If the carrier uses a catch-all connection, `SenderGsId` must equal the **Company Number** of the customer in Alvys. If no customer has that Company Number, or more than one does, the tender is rejected.

## With EDI: reuse your X12 IDs

*For partners that already exchange EDI 204s.*

Send your real ISA and GS IDs and qualifiers. The JSON endpoints map to the 204 purpose codes:

| EDI 204 | Tender API |
| :- | :- |
| Original | `POST /api/p/v1.0/tenders` |
| Change | `POST /api/p/v1.0/tenders/update` |
| Cancel | `POST /api/p/v1.0/tenders/cancel` |

Differences from classic X12 over a VAN or AS2:

| | X12 over VAN or AS2 | Tender API |
| :- | :- | :- |
| Transport | EDI file through your network | HTTPS and JSON |
| Functional acknowledgment | 997 | None. The HTTP response confirms receipt. |
| Stop type | S5 stop reason code | `Type` is `Pickup` or `Delivery`. X12 codes in `Type` are not translated. |
| Accept or reject | 990 | `tender.accepted` or `tender.rejected` webhook |
| Shipment status | 214 | `load.status.changed` and `tender.stop.*` webhooks |

> [!WARNING]
>
> Alvys finds the connection by the six routing IDs only. It does not check the connection's transport. If your IDs match a connection that uses an EDI transport, such as AS2, SFTP, or a VAN, Alvys sends EDI responses such as 990s over that connection, the same as for an EDI tender. Ask the carrier to set up a separate connection with the **Public API** transport for your API traffic, with routing IDs that no EDI connection uses.

## Carrier setup checklist

*For the carrier admin.*

1. Create API client credentials for the partner under **Admin → API Access** and assign the [scopes](#scopes) above.
2. Create the customer the loads are for. If you use a catch-all connection, set the customer's **Company Number** to the agreed `SenderGsId`.
3. Go to **Manage → EDI & Visibility** and add a connection for the partner:
   * Set the transport to **Public API**.
   * Enter the six routing IDs.
   * Choose the customer, or make it a catch-all connection.
   * Choose the subsidiary the loads belong to.
4. Decide how tenders are accepted. To accept them automatically, turn on **Auto-Accept EDI Tenders** on the customer. If you use fleets, also set the customer's default fleet.
5. Send the partner the six routing IDs and your SCAC.

A connection with the **Public API** transport sends nothing back over EDI. The partner gets every outcome through webhooks or by polling the API.

## Workflow

*For the partner.*

| Step | Request | What you get |
| :- | :- | :- |
| 1 | `POST /oauth/token` | A bearer token |
| 2 | `POST /api/p/v1.0/webhooks` | A subscription and its signing secret |
| 3 | `POST /api/p/v1.0/tenders` | `201` and the tender's location |
| 4 | `tender.created` webhook, or `POST /api/p/v1.0/tenders/search` | The tender id |
| 5 | Carrier accepts, or `POST /api/p/v1.0/tenders/{tenderId}/accept` | `tender.accepted` with the load number |
| 6 | `GET /api/p/v2.0/loads?orderNumber={ShipmentId}` | The load |
| 7 | `POST /api/p/v1.0/tenders/update` or `/cancel` | A changed or cancelled tender |
| 8 | Webhooks, and `GET /api/p/v2.0/loads/{loadNumber}/documents` | Status updates and documents |

A tender moves through these statuses:

```mermaid theme={null}
stateDiagram-v2
    direction LR
    New --> Accepted: carrier accepts
    New --> Rejected: carrier rejects
    New --> Cancelled: you cancel
    Accepted --> Rejected: carrier rejects
    Accepted --> Cancelled: you cancel, carrier confirms
```

### 1. Get a token

Request a token with the client credentials grant and send it as `Authorization: Bearer <token>` on every call. Cache the token until it expires. See [Authenticate with the Alvys Public API](https://docs.alvys.com/en/api/guides/authentication-1.md).

```bash theme={null}
curl --request POST \
  --url https://auth.alvys.com/oauth/token \
  --header 'Content-Type: application/json' \
  --data '{
    "client_id": "<client_id>",
    "client_secret": "<client_secret>",
    "audience": "https://api.alvys.com/public/",
    "grant_type": "client_credentials"
  }'
```

### 2. Subscribe to tender and load events

Create the subscription before you send the first tender, so you do not miss `tender.created`.

* List every event by its exact name. There are no wildcards.
* Send exactly one of `SubsidiaryIds` or `AllSubsidiaries`. `SubsidiaryId` is deprecated. Get subsidiary ids from [List subsidiaries](https://docs.alvys.com/en/api/reference/subsidiaries/list-subsidiaries.md).
* A subscription can hold up to 50 events.

```http theme={null}
POST /api/p/v1.0/webhooks
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "Name": "Tender sync",
  "Url": "https://tms.example.com/alvys/webhooks",
  "AllSubsidiaries": true,
  "IncludePreviousAttributes": false,
  "Events": [
    "tender.created",
    "tender.accepted",
    "tender.rejected",
    "tender.cancelled",
    "tender.change.created",
    "tender.change.accepted",
    "load.status.changed",
    "load.document.uploaded",
    "load.document.deleted"
  ]
}
```

The `201` response includes `Secret`. Store it. Get and list calls return it masked. Use it to [verify signatures](https://docs.alvys.com/en/api/reference/webhooks/security-signature-verification.md).

```json theme={null}
{
  "Id": "5b1f0c3e-8a2d-4f6b-9e71-2c4d8a0b6f13",
  "Name": "Tender sync",
  "Url": "https://tms.example.com/alvys/webhooks",
  "Secret": "whsec_...",
  "AllSubsidiaries": true,
  "SubsidiaryIds": [],
  "Events": ["tender.created", "tender.accepted", "..."],
  "IncludePreviousAttributes": false
}
```

The response above is shortened. See [Create webhook subscription](https://docs.alvys.com/en/api/reference/webhooks/create-webhook-subscription.md) for every field.

### 3. Create a tender

`POST /api/p/v1.0/tenders` creates a tender in the carrier's account. The smallest valid tender has the routing IDs, `SCAC`, `ShipmentId`, and two stops:

```http theme={null}
POST /api/p/v1.0/tenders
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "SenderIsaIdQualifier": "ZZ",
  "SenderIsaId": "ACMESHIP",
  "SenderGsId": "ACMESHIP",
  "ReceiverIsaIdQualifier": "ZZ",
  "ReceiverIsaId": "FASTCARRIER",
  "ReceiverGsId": "FASTCARRIER",
  "SCAC": "FSTC",
  "ShipmentId": "SHP-100234",
  "Stops": [
    {
      "Type": "Pickup",
      "Entity": {
        "Name": "Acme DC Dallas",
        "Street": "100 Main St",
        "City": "Dallas",
        "State": "TX",
        "PostalCode": "75201",
        "CountryCode": "US"
      },
      "ScheduledArrivalStart": "2026-11-10T08:00:00-06:00"
    },
    {
      "Type": "Delivery",
      "Entity": {
        "Name": "Acme Store 12",
        "Street": "200 Oak Ave",
        "City": "Houston",
        "State": "TX",
        "PostalCode": "77002",
        "CountryCode": "US"
      },
      "ScheduledArrivalStart": "2026-11-11T14:00:00-06:00"
    }
  ]
}
```

A successful call returns `201 Created` with an empty body. The `Location` header points to the new tender:

```http theme={null}
HTTP/1.1 201 Created
Location: https://integrations.alvys.com/api/p/v1.0/tenders/8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42
```

A fuller tender adds equipment, weight, rate, references, and notes:

```json theme={null}
{
  "SenderIsaIdQualifier": "ZZ",
  "SenderIsaId": "ACMESHIP",
  "SenderGsId": "ACMESHIP",
  "ReceiverIsaIdQualifier": "ZZ",
  "ReceiverIsaId": "FASTCARRIER",
  "ReceiverGsId": "FASTCARRIER",
  "SCAC": "FSTC",
  "ShipmentId": "SHP-100234",
  "PoNumber": "PO-55821",
  "Rate": 1850.00,
  "ExpirationDate": "2026-11-09T17:00:00-06:00",
  "QtyPallets": "22",
  "Weight": "38000",
  "WeightUnitCode": "L",
  "Equipment": { "Length": "53", "Type": "TV" },
  "Entities": [
    { "Type": "Shipper", "Name": "Acme Corp", "City": "Dallas", "State": "TX" },
    {
      "Type": "BillTo",
      "Name": "Acme Corp AP",
      "Street": "1 Finance Way",
      "City": "Dallas",
      "State": "TX",
      "PostalCode": "75201",
      "CountryCode": "US",
      "Email": "ap@acme.example"
    }
  ],
  "References": [
    { "Qualifier": "BM", "Id": "BOL-778812", "Type": "BOL Number" }
  ],
  "Notes": ["Driver must check in at gate 3"],
  "Stops": [
    {
      "Type": "Pickup",
      "SequenceNumber": "1",
      "Entity": {
        "Name": "Acme DC Dallas",
        "Street": "100 Main St",
        "City": "Dallas",
        "State": "TX",
        "PostalCode": "75201",
        "CountryCode": "US",
        "Phone": "2145550100"
      },
      "ScheduledArrivalStart": "2026-11-10T08:00:00-06:00",
      "ScheduledArrivalEnd": "2026-11-10T10:00:00-06:00",
      "Orders": [
        { "Quantity": "22", "Weight": "38000", "WeightUnitCode": "L", "PoNumber": "PO-55821", "Description": "Packaged goods" }
      ],
      "References": [
        { "Qualifier": "PU", "Id": "PU-9981", "Type": "Pickup Number" }
      ],
      "Notes": ["Live load"]
    },
    {
      "Type": "Delivery",
      "SequenceNumber": "2",
      "Entity": {
        "Name": "Acme Store 12",
        "Street": "200 Oak Ave",
        "City": "Houston",
        "State": "TX",
        "PostalCode": "77002",
        "CountryCode": "US"
      },
      "ScheduledAppointment": "2026-11-11T14:00:00-06:00",
      "References": [
        { "Qualifier": "DO", "Id": "DEL-4471", "Type": "Delivery Number" }
      ]
    }
  ]
}
```

The qualifier and unit codes in this example (`L`, `TV`, `BM`, `PU`, `DO`) are common X12 values. Alvys does not validate them.

Rules for the tender body:

* Send at least two stops. Each stop `Type` is `Pickup` or `Delivery`.
* Include at least one pickup and one delivery whose `Entity` has a city **and** a state. If not, Alvys still returns `201`, but the tender cannot be accepted until the carrier fixes it in Alvys.
* Set `Type` on each reference to the reference name the carrier uses, for example `BOL Number`. The name becomes the reference name on the load. A reference without `Type` can be dropped.
* `Rate` becomes the linehaul and billing rate on the load. You cannot send fuel surcharge or accessorial charges on a tender.
* The response does not include the tender. Read it in the next step.

See [Create tender](https://docs.alvys.com/en/api/reference/tenders/create-tender.md) for every field.

### Dates and time zones

Send each date as the local wall-clock time at the stop or at the customer. Alvys keeps the clock time you send and applies the time zone it resolves for the tender. A UTC timestamp, such as one ending in `Z`, can therefore move by several hours.

Alvys ignores the offset in your timestamps. The `-06:00` in the examples on this page has no effect. If Alvys cannot resolve a time zone for the tender, it drops `ExpirationDate`, and the tender shows no response deadline.

### 4. Find your tender id

You need the tender id to read the tender and to accept or reject it. Get it in one of three ways:

* The `Location` header of the create response.
* `data.tenderId` in the `tender.created` webhook.
* A search by `ShipmentId`:

```http theme={null}
POST /api/p/v1.0/tenders/search
Authorization: Bearer <token>
Content-Type: application/json
```

```json theme={null}
{
  "Page": 0,
  "PageSize": 25,
  "Filter": { "ShipmentId": "SHP-100234" }
}
```

The response is a page with `Items`, `Total`, `Page`, and `PageSize`. Each item is a tender with its `Id`, `Status`, `ShipmentId`, and stops.

> [!WARNING]
>
> The tender id usually stays the same. It can change if Alvys links the tender to an existing load. Take the id from the latest webhook, or search by `ShipmentId`, before you act on a tender.

### 5. Accept the tender

A tender is accepted in one of three ways. The carrier chooses which.

| Path | Who acts | What happens |
| :- | :- | :- |
| Auto-accept | Alvys | When the tender arrives, Alvys matches each stop to a location by address, or creates the location. It then creates the load. |
| Accept in Alvys | Carrier | A dispatcher reviews the tender in Alvys, picks a location for each stop, and accepts. |
| Accept through the API | Partner or carrier | You send a location id for every stop. Use this path only if you act for the carrier. |

When Alvys creates a load from the tender, it sends `tender.accepted` with the new load's `loadId` and `loadNumber`. The new load gets the tender's id, so `loadId` equals `tenderId`:

```json theme={null}
{
  "id": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42-2",
  "type": "tender.accepted",
  "timestamp": "2026-11-05T15:10:02+00:00",
  "version": "v2",
  "etag": "0b00a1c2-0000-0700-0000-6729f1a30000",
  "subsidiaryId": "2d7e4c19-5a3b-4f8e-b1d6-7c9a0e3f5b42",
  "data": {
    "tenderId": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42",
    "loadId": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42",
    "loadNumber": "100457",
    "tender": {
      "id": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42",
      "status": "Accepted",
      "shipmentId": "SHP-100234",
      "loadNumber": "100457"
    }
  }
}
```

The `data.tender` snapshot above is shortened. It has the same fields as [Get tender](https://docs.alvys.com/en/api/reference/tenders/get-tender.md), in camelCase. See [Tender events](https://docs.alvys.com/en/api/reference/webhooks/tender-events.md).

> [!WARNING]
>
> If the carrier already has a load whose order number equals your `ShipmentId`, Alvys links the tender to that load and does not create a new load. The tender takes the id of that load. Alvys then sends `tender.created` for the new tender id, with `data.tender.status` set to `Accepted`, and does not send `tender.accepted`. Treat a `tender.created` with status `Accepted` as an acceptance, and match it to your tender by `shipmentId`.

> [!NOTE]
>
> If auto-accept fails, for example because a stop location cannot be matched or the customer has no default fleet, the tender stays `New`. The reason is shown to the carrier in Alvys. It is not in the API response.

#### Accept through the API

1. Get the tender and read the `StopId` of each stop:

   ```http theme={null}
   GET /api/p/v1.0/tenders/8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42
   Authorization: Bearer <token>
   ```

   ```json theme={null}
   {
     "Id": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42",
     "Status": "New",
     "ShipmentId": "SHP-100234",
     "Stops": [
       { "StopId": "3f1c9a52-6d0e-4a9b-9c1e-2b7f0d4e8a11", "Type": "Pickup", "SequenceNumber": "1" },
       { "StopId": "9b2e7d10-1a4c-4f3e-8b6d-5c9a0e1f2d33", "Type": "Delivery", "SequenceNumber": "2" }
     ]
   }
   ```

2. Find the Alvys location id for each stop with [Get location](https://docs.alvys.com/en/api/reference/locations/get-location.md) or [Search locations](https://docs.alvys.com/en/api/reference/locations/search-locations.md). The location must already exist. Accepting through the API does not create locations.

3. Accept with one link for **every** stop on the tender. `FleetId` is optional.

   ```http theme={null}
   POST /api/p/v1.0/tenders/8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42/accept
   Authorization: Bearer <token>
   Content-Type: application/json
   ```

   ```json theme={null}
   {
     "StopCompanyLinks": [
       { "StopId": "3f1c9a52-6d0e-4a9b-9c1e-2b7f0d4e8a11", "CompanyId": "c0a8e1f2-4b7e-4d3a-9a1e-2f3b4c5d6e7f" },
       { "StopId": "9b2e7d10-1a4c-4f3e-8b6d-5c9a0e1f2d33", "CompanyId": "d4b2c3a1-4e2f-4a9b-8c1d-2e3f4a5b6c7d" }
     ],
     "FleetId": "<fleetId>"
   }
   ```

The response is `200` with the tender. `Status` is `Accepted` and `LoadNumber` is set. If you accept a tender that is already accepted, Alvys returns it unchanged.

### 6. Read the load

After acceptance, the tender has a load. Get the load by its order number, which is your `ShipmentId`, or by the `loadNumber` from `tender.accepted`. Send exactly one query parameter.

```http theme={null}
GET /api/p/v2.0/loads?orderNumber=SHP-100234
Authorization: Bearer <token>
```

```json theme={null}
{
  "Id": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42",
  "LoadNumber": "100457",
  "OrderNumber": "SHP-100234",
  "PONumber": "PO-55821",
  "CustomerName": "Acme Corp",
  "Status": "<status>",
  "TenderId": "8d0c3b8e-2f51-4c1e-9a77-0e5b6a1f9c42",
  "Stops": ["..."],
  "References": ["..."]
}
```

The response above is shortened. See [Get load](https://docs.alvys.com/en/api/reference/loads/get-load.md) for every field.

### 7. Send changes and cancellations

Send a change to `POST /api/p/v1.0/tenders/update` and a cancellation to `POST /api/p/v1.0/tenders/cancel`.

* Send the **full** tender body each time, with the same routing IDs and `ShipmentId`, and the full list of stops. For a cancellation, send the body of the last tender you sent.
* Both return `201` with an empty body, like create.
* If no tender exists for the `ShipmentId`, or the latest tender was cancelled, an update creates a new tender.
* If no tender exists for the `ShipmentId`, a cancellation creates a tender and cancels it, so the carrier sees the cancellation in Alvys.
* If you send a create again for a `ShipmentId` whose latest tender is not cancelled or rejected, Alvys treats it as an update. This includes a tender that is already accepted. If the latest tender was cancelled or rejected, or its load was cancelled, Alvys creates a new tender.

What happens next:

* **Update.** Alvys sends `tender.change.created`. If `queuedForReview` is `true`, the carrier reviews the change in Alvys, and you get `tender.change.accepted` when it is applied. If it is `false`, the change was applied directly.
* **Cancel, tender not yet accepted.** The tender is cancelled. You get `tender.cancelled`.
* **Cancel, tender accepted.** By default, the carrier confirms the cancellation, and then the load is cancelled. Some connections cancel the load at once, without the carrier's confirmation. You get `tender.cancelled`.
* **Cancel, no tender for the `ShipmentId`.** Alvys creates a tender and cancels it. You get `tender.created`, and then `tender.cancelled`.

> [!WARNING]
>
> Use a `ShipmentId` that is unique within the carrier's account, for example with a prefix for your system. Alvys finds the tender to update or cancel by `ShipmentId`.

### 8. Reject a tender

*For the carrier, or a partner that acts for the carrier.*

`POST /api/p/v1.0/tenders/{tenderId}/reject` rejects a tender. Set `CancelLinkedLoad` to `true` to also cancel a load that was already created from it.

```json theme={null}
{
  "ReasonCode": "EQU",
  "ReasonDescription": "No Equipment Available",
  "CancelLinkedLoad": false
}
```

Reason codes are free text. Common values are `A13` (Other reasons), `EQU` (No equipment available), `CPU` (Agreed-upon capacity exceeded), `LL1` (Load does not belong to us), and `LL2` (Unable to complete the load). The partner gets `tender.rejected`.

### 9. Track status and documents

* **Status.** `load.status.changed` carries `previousStatus`, `status`, and the load. See [Load events](https://docs.alvys.com/en/api/reference/webhooks/load-events.md).
* **Stop updates.** `tender.stop.arrived`, `tender.stop.departed`, and `tender.stop.eta_updated` report stop progress against the tender. See [Tender events](https://docs.alvys.com/en/api/reference/webhooks/tender-events.md).
* **Documents.** `load.document.uploaded` carries the load number and a `document` with a `downloadUrl`. The link is valid for 10 minutes. For a fresh link, call `GET /api/p/v2.0/loads/{loadNumber}/documents`. See [Document events](https://docs.alvys.com/en/api/reference/webhooks/document-events.md).
* **Upload documents.** `POST /api/p/v2.0/loads/{loadNumber}/document` uploads a file to the load. See [Upload load document](https://docs.alvys.com/en/api/reference/loads/upload-load-document.md).

Webhooks can arrive more than once and out of order. Use `X-Alvys-Event-Id` to ignore duplicates. To recover events you missed, poll [Get load](https://docs.alvys.com/en/api/reference/loads/get-load.md) and the documents list on a schedule. See [Event delivery reliability](https://docs.alvys.com/en/api/reference/webhooks/event-delivery-reliability.md).

> [!NOTE]
>
> The REST API uses PascalCase property names, for example `LoadNumber`. Webhook payloads use camelCase, for example `loadNumber`, and leave out properties that have no value.

## Common errors

Errors are listed with the most frequent first. "Conflict" errors return `400`, not `409`. Some errors return a plain JSON string instead of a problem object.

| Error | Status | Cause | Fix |
| :- | :- | :- | :- |
| `Integration is missing` | 400 | The six routing IDs match no connection, and the carrier has no catch-all connection. | Compare all six values with the carrier's connection, character by character. |
| `EDI catch-all requires a single company with Company Number: '…'.` | 400 | Catch-all connection, and no customer, or more than one, has Company Number equal to `SenderGsId`. | Ask the carrier to set the Company Number on exactly one customer. |
| `Failed to ingest tender` | 400 | The connection matched, but Alvys could not book the tender, for example because no customer is set. | Ask the carrier to check the connection's customer and subsidiary. |
| `At least two stops are required` | 400 | Fewer than two stops. | Send a pickup and a delivery. |
| `The ShipmentId field is required.` (and other required fields) | 400 | A required field is missing. | Send all routing IDs, `SCAC`, `ShipmentId`, and `Stops`. |
| `EDI 204 has no valid pickup stop (pickup stop missing, or its address has no city/state). Tender quarantined for manual review.` | Shown in Alvys | The tender was created (`201`), but it has no usable pickup. The delivery has a matching message. | Send city and state on every stop, then send an update. |
| `The request has a different number of stops than the tender` (title `Stop count mismatch`) | 400 | API accept sent a different number of links than the tender has stops. | Send one link for every stop. |
| `At least two stop-company links are required` | 400 | API accept sent fewer than two links. | Send one link for every stop. |
| `Company with ID '…' not found for stop '…'` | 404 | API accept sent a location id that does not exist. | Look up the location id again. |
| `The tender cannot be accepted. It has been cancelled.` | 400 | The tender was cancelled. | None. Send a new tender if the load is still needed. |
| `Duplicate tender … found. Load … already exists` | 400 | A load with this order number exists and cannot be linked. | Ask the carrier to check the existing load. |
| `These changes were already accepted or rejected. Reload the changes.` | 400 | The pending change was already handled. | Get the tender again. |
| `Requested Tender Not Found` | 404 | The tender id does not exist, or it changed on accept. | Search by `ShipmentId`. |
| Payment required | 402 | The carrier's plan does not include Public API access. | Ask the carrier to contact Alvys. |

If none of these match, contact [support@alvys.com](mailto:support@alvys.com) with the `ShipmentId`, the time of the call, and the response body.

## Related resources

* [Tender API reference](https://docs.alvys.com/en/api/reference/tenders/create-tender.md)
* [Tender events](https://docs.alvys.com/en/api/reference/webhooks/tender-events.md)
* [Load events](https://docs.alvys.com/en/api/reference/webhooks/load-events.md)
* [Document events](https://docs.alvys.com/en/api/reference/webhooks/document-events.md)
* [Webhook signature verification](https://docs.alvys.com/en/api/reference/webhooks/security-signature-verification.md)
* [EDI integrations](https://docs.alvys.com/en/api/guides/edi-integrations.md): map a carrier's own EDI transactions to the API
* [Versioning](https://docs.alvys.com/en/api/guides/versioning.md)
