---
title: "Completes (receives) an in-transit standalone transfer (\"Complete Transfer\"), optionally with lines that did not arrive."
method: POST
path: "/api/v1/transfers/{id}/complete"
tags: ["Transfers"]
---

# Completes (receives) an in-transit standalone transfer ("Complete Transfer"), optionally with lines that did not arrive.

`POST /api/v1/transfers/{id}/complete`

## Request

- Base URL: `https://app.flexonthejob.com`
- URL: `https://app.flexonthejob.com/api/v1/transfers/{id}/complete`
- Auth: HTTP bearer

Requires `ManageTransfers` and an `Idempotency-Key` header. Body optional:
`{ "failedLines": [ { "lineId": 911, "reason": "Damaged in transit" } ] }` marks those
lines failed first (the app's per-line "Mark as Failed"); they stay where they are and end
`Returned`. Every other unit moves to its line's destination, its in-transit flag is
cleared, `quantityDelivered` is recorded and the transfer becomes `Completed`
(the `transfer.completed` webhook fires). Only standalone transfers in an in-transit
status (`InTransit`, `InTransitToWaypoint`, `AtWaypoint`,
`InTransitToDestination`) can be completed; job-site and sales-order transfers are
completed from their job or order.

## Path parameters

- `id` integer, required

## Request body

- CompleteTransferRequest: Optional body of `POST /api/v1/transfers/{id}/complete`: lines that did not arrive. Example: `{ "failedLines": [ { "lineId": 911, "reason": "Damaged in transit" } ] }`. Omit the body (or send `{}`) when everything arrived.
  - `failedLines` FailedTransferLineRequest[], nullable: Lines (ids from the transfer's `lines[].id`) to mark failed before completing; they stay where they are instead of moving. Up to 100.
    - `lineId` integer: Transfer line id (`lines[].id` of `GET /api/v1/transfers/{id}`). The line must be `InTransit` (or already `Failed`). Example: `911`.
    - `reason` string, required: Why the line failed (required, 1–500 characters); recorded on the line. Example: `Damaged in transit`.

## Response `200`

Transfer id and confirmation message (e.g. `Transfer completed.`).

- ApiOperationResponse: Body of a successful workflow-style write that has no richer resource to return (assign, start, complete, void…). Id is the affected resource's id; Warning carries a non-fatal note from the service (e.g. an email that could not be sent).
  - `id` integer: Id of the resource the operation acted on (e.g. the job id).
  - `message` string, nullable: Human-readable confirmation from the service (e.g. "Job started."). May be null.
  - `warning` string, nullable: Non-fatal problem encountered while completing the operation (e.g. a notification email that could not be sent). Null when there was none.

## Other responses

- `400`: Malformed body or missing `Idempotency-Key`.
- `401`: Unauthorized
- `403`: Forbidden
- `404`: No such transfer in this organization.
- `409`: A job-site or sales-order transfer, not in transit (start it first), a failed line that is not `InTransit`, or the key's creator is unknown on this server.
- `422`: A `failedLines` entry names a line that is not on this transfer, or has a blank reason (field listed in `errors`).
- `429`: Too Many Requests
- `500`: The change could not be saved. Retry with the same `Idempotency-Key`.

---

[API](https://skmtc.dev/flexonthejob/apis/flex-api.md) · [All operations](https://skmtc.dev/flexonthejob/apis/flex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/flexonthejob/apis/flex-api/revisions/19c8f4d27acf?raw)
