The Transfer Orders API enables you to create and manage transfer orders for moving inventory between locations. This helps you track inventory redistribution and maintain accurate stock levels across multiple locations.
Overview
The Transfer Orders client provides methods for:
- Creating transfer orders to move inventory between locations
- Searching for transfer orders
- Retrieving transfer order details
- Updating transfer orders
- Starting, canceling, and receiving transfer orders
Client Initialization
import (
"context"
"github.com/square/square-go-sdk/square"
)
client := square.NewClient(
square.WithAccessToken("YOUR_ACCESS_TOKEN"),
)
Methods
Create Transfer Order
Creates a new transfer order in DRAFT status representing the intent to move items from one location to another.
request := &square.CreateTransferOrderRequest{
IdempotencyKey: "65cc0586-3e82-384s-b524-3885cffd52",
TransferOrder: &square.CreateTransferOrderData{
SourceLocationID: "EXAMPLE_SOURCE_LOCATION_ID_123",
DestinationLocationID: "EXAMPLE_DEST_LOCATION_ID_456",
ExpectedAt: square.String("2025-11-09T05:00:00Z"),
Notes: square.String("Example transfer order for inventory redistribution"),
TrackingNumber: square.String("TRACK123456789"),
CreatedByTeamMemberID: square.String("EXAMPLE_TEAM_MEMBER_ID_789"),
LineItems: []*square.CreateTransferOrderLineData{
&square.CreateTransferOrderLineData{
ItemVariationID: "EXAMPLE_ITEM_VARIATION_ID_001",
QuantityOrdered: "5",
},
},
},
}
response, err := client.TransferOrders.Create(
context.TODO(),
request,
)
A unique string that identifies this CreateTransferOrder request.
transferOrder.sourceLocationID
The ID of the source location from which items will be transferred.
transferOrder.destinationLocationID
The ID of the destination location to which items will be transferred.
The expected delivery date and time in RFC 3339 format.
Notes about the transfer order.
transferOrder.trackingNumber
The tracking number for the shipment.
transferOrder.lineItems
[]CreateTransferOrderLineData
The items to transfer.
The created transfer order in DRAFT status.
Search Transfer Orders
Searches for transfer orders using filters and returns a paginated list.
request := &square.SearchTransferOrdersRequest{
Query: &square.TransferOrderQuery{
Filter: &square.TransferOrderFilter{
SourceLocationIDs: []string{"EXAMPLE_SOURCE_LOCATION_ID_123"},
DestinationLocationIDs: []string{"EXAMPLE_DEST_LOCATION_ID_456"},
Statuses: []square.TransferOrderStatus{
square.TransferOrderStatusStarted,
square.TransferOrderStatusPartiallyReceived,
},
},
Sort: &square.TransferOrderSort{
Field: square.TransferOrderSortFieldUpdatedAt.Ptr(),
Order: square.SortOrderDesc.Ptr(),
},
},
Limit: square.Int(10),
}
response, err := client.TransferOrders.Search(
context.TODO(),
request,
)
query.filter.sourceLocationIDs
Filter by source location IDs.
query.filter.destinationLocationIDs
Filter by destination location IDs.
Filter by transfer order statuses.
Sorting criteria for results.
Pagination cursor from a previous search response.
Maximum number of results to return (1-100).
The list of transfer orders matching the search criteria.
Get Transfer Order
Retrieves a specific transfer order by ID with complete details.
request := &square.GetTransferOrdersRequest{
TransferOrderID: "transfer_order_id",
}
response, err := client.TransferOrders.Get(
context.TODO(),
request,
)
The ID of the transfer order to retrieve.
The requested transfer order with all details.
Update Transfer Order
Updates an existing transfer order with sparse updates to specific fields.
request := &square.UpdateTransferOrderRequest{
TransferOrderID: "transfer_order_id",
IdempotencyKey: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
TransferOrder: &square.UpdateTransferOrderData{
ExpectedAt: square.String("2025-11-10T08:00:00Z"),
Notes: square.String("Updated: Priority transfer"),
LineItems: []*square.UpdateTransferOrderLineData{
&square.UpdateTransferOrderLineData{
UID: square.String("1"),
QuantityOrdered: square.String("7"),
},
},
},
Version: square.Int64(int64(1753109537351)),
}
response, err := client.TransferOrders.Update(
context.TODO(),
request,
)
The ID of the transfer order to update.
A unique string that identifies this UpdateTransferOrder request.
The transfer order fields to update.
Version for optimistic concurrency control.
The updated transfer order.
Start Transfer Order
Changes a DRAFT transfer order to STARTED status, decrementing inventory at the source location.
request := &square.StartTransferOrderRequest{
TransferOrderID: "transfer_order_id",
IdempotencyKey: "EXAMPLE_IDEMPOTENCY_KEY_789",
Version: square.Int64(int64(1753109537351)),
}
response, err := client.TransferOrders.Start(
context.TODO(),
request,
)
The ID of the transfer order to start. Must be in DRAFT status.
A unique string for idempotency.
Version for optimistic concurrency control.
The transfer order now in STARTED status.
Receive Transfer Order
Records receipt of items for a transfer order, supporting partial receiving.
request := &square.ReceiveTransferOrderRequest{
TransferOrderID: "transfer_order_id",
IdempotencyKey: "EXAMPLE_IDEMPOTENCY_KEY_101",
Receipt: &square.TransferOrderGoodsReceipt{
LineItems: []*square.TransferOrderGoodsReceiptLineItem{
&square.TransferOrderGoodsReceiptLineItem{
TransferOrderLineUID: "1",
QuantityReceived: square.String("3"),
QuantityDamaged: square.String("1"),
QuantityCanceled: square.String("1"),
},
},
},
Version: square.Int64(int64(1753118664873)),
}
response, err := client.TransferOrders.Receive(
context.TODO(),
request,
)
The ID of the transfer order to receive items for.
A unique key to make this request idempotent.
receipt.lineItems
[]TransferOrderGoodsReceiptLineItem
required
The line items being received with quantities.
receipt.lineItems[].quantityReceived
Quantity received in good condition (added to destination inventory as IN_STOCK).
receipt.lineItems[].quantityDamaged
Quantity damaged during transit (added to destination inventory as WASTE).
receipt.lineItems[].quantityCanceled
Quantity canceled (returned to source location’s inventory).
Version for optimistic concurrency control.
The updated transfer order with received quantities.
Cancel Transfer Order
Cancels a transfer order in STARTED or PARTIALLY_RECEIVED status.
request := &square.CancelTransferOrderRequest{
TransferOrderID: "transfer_order_id",
IdempotencyKey: "65cc0586-3e82-4d08-b524-3885cffd52",
Version: square.Int64(int64(1753117449752)),
}
response, err := client.TransferOrders.Cancel(
context.TODO(),
request,
)
The ID of the transfer order to cancel.
A unique string for idempotency.
Version for optimistic concurrency control.
The canceled transfer order.
Delete Transfer Order
Deletes a transfer order in DRAFT status.
request := &square.DeleteTransferOrdersRequest{
TransferOrderID: "transfer_order_id",
Version: square.Int64(int64(1000000)),
}
response, err := client.TransferOrders.Delete(
context.TODO(),
request,
)
The ID of the transfer order to delete.
Version for optimistic concurrency control.
Transfer Order Lifecycle
- DRAFT - Initial state when created. Can be edited or deleted.
- STARTED - Order is in transit. Inventory is decremented from source.
- PARTIALLY_RECEIVED - Some items have been received.
- COMPLETED - All items have been received, damaged, or canceled.
- CANCELED - Order was canceled before completion.
Use Cases
Create and Start Transfer
Create a transfer order and immediately start it:
// Create transfer order
createReq := &square.CreateTransferOrderRequest{
IdempotencyKey: uuid.New().String(),
TransferOrder: &square.CreateTransferOrderData{
SourceLocationID: "SOURCE_LOC_ID",
DestinationLocationID: "DEST_LOC_ID",
LineItems: []*square.CreateTransferOrderLineData{
&square.CreateTransferOrderLineData{
ItemVariationID: "ITEM_VAR_ID",
QuantityOrdered: "10",
},
},
},
}
createResp, err := client.TransferOrders.Create(context.TODO(), createReq)
if err != nil {
log.Fatal(err)
}
// Start the transfer
startReq := &square.StartTransferOrderRequest{
TransferOrderID: *createResp.TransferOrder.ID,
IdempotencyKey: uuid.New().String(),
Version: createResp.TransferOrder.Version,
}
startResp, err := client.TransferOrders.Start(context.TODO(), startReq)
Receive Items with Damage
Record receipt with some damaged items:
request := &square.ReceiveTransferOrderRequest{
TransferOrderID: "transfer_order_id",
IdempotencyKey: uuid.New().String(),
Receipt: &square.TransferOrderGoodsReceipt{
LineItems: []*square.TransferOrderGoodsReceiptLineItem{
&square.TransferOrderGoodsReceiptLineItem{
TransferOrderLineUID: "line_item_uid",
QuantityReceived: square.String("8"), // 8 in good condition
QuantityDamaged: square.String("2"), // 2 damaged
},
},
},
Version: square.Int64(currentVersion),
}
response, err := client.TransferOrders.Receive(context.TODO(), request)
Search Active Transfers
Find all in-progress transfers for a location:
request := &square.SearchTransferOrdersRequest{
Query: &square.TransferOrderQuery{
Filter: &square.TransferOrderFilter{
SourceLocationIDs: []string{"LOCATION_ID"},
Statuses: []square.TransferOrderStatus{
square.TransferOrderStatusStarted,
square.TransferOrderStatusPartiallyReceived,
},
},
},
}
response, err := client.TransferOrders.Search(context.TODO(), request)
Best Practices
- Use idempotency keys: Prevent duplicate transfers with unique keys
- Track versions: Use version numbers for optimistic concurrency control
- Handle partial receives: Support receiving items in multiple batches
- Monitor damaged goods: Track damaged quantities separately
- Add tracking numbers: Include shipment tracking for visibility
- Document with notes: Add context about why transfers are happening
- Start when ready: Keep orders in DRAFT until ready to ship
Error Handling
response, err := client.TransferOrders.Create(context.TODO(), request)
if err != nil {
if apiErr, ok := err.(*square.APIError); ok {
for _, e := range apiErr.Errors {
switch e.Code {
case "INSUFFICIENT_INVENTORY":
// Source location doesn't have enough inventory
case "INVALID_VALUE":
// Check source and destination locations are different
case "VERSION_MISMATCH":
// Reload and retry with current version
}
}
}
}