1. Shipments
  2. Refund Shipments

Shipments

Refund Shipments

This endpoint allows you to request a refund for a previously purchased shipment. When a refund is requested, the shipment status is updated to canceled and the refund_status is set to requested. For asynchronous carriers (such as EasyPost), the status transitions to refunded once the carrier confirms the refund, or to rejected if the carrier denies it. For synchronous providers the confirmation typically arrives in the same call, so the transition to refunded appears immediate.

POST
`/v1/shipments/:shipment/refund`

The endpoint requires only the shipment ID as a URL parameter. No request body is needed.

Request Example

js
        const response = await fetch(`https://api.packagex.io/v1/shipments/${shipment_id}/refund`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json"
  }
});

const result = await response.json();

      

Provider Support

Not all shipping providers support refunds. The system automatically checks provider capabilities before processing the refund request. If a provider doesn't support refunds, the request will be rejected with an appropriate error message.

Refund Process

The refund process involves several automated steps:

  1. Validation

    • Verifies the shipment exists and has been purchased.
    • Confirms the shipping provider supports refunds.
    • Checks if the shipment is eligible for refund.
  2. Provider Integration

    • Processes the refund with the shipping provider.
    • Updates tracking information accordingly.
    • Cancels any pending pickup or delivery requests.
  3. Status Updates

    • Updates shipment status to canceled
    • Sets refund_status to requested
    • For asynchronous carriers: refund_status transitions to refunded once confirmed, or rejected if denied
    • Creates tracking update records.

Status Changes

When a refund is requested, the following status changes occur:

  • Shipment status: Changed to canceled
  • Refund status: Initially set to requested; transitions to refunded when the carrier confirms, or rejected if the carrier denies the refund
  • Tracking updates: New update created with canceled status

The possible values for refund_status are requested, refunded, and rejected. See the Statuses and Events page for descriptions of each.

For asynchronous carriers, refund_status starts at requested and later transitions to either refunded (the carrier confirmed the refund) or rejected (the carrier denied it). Synchronous providers resolve the transition within the original request, so refunded or rejected is returned immediately.

Webhook Events

The refund lifecycle publishes two shipment events. Which one fires depends on where the refund lands:

  • While the refund is still pending (refund_status: "requested"), the request publishes shipment__updated.
  • On any terminal outcome - both refunded AND rejected - a shipment__refunded event is published.

Because shipment__refunded fires for both terminal outcomes, consumers MUST inspect the shipment's refund_status to distinguish a completed refund (refunded) from a carrier rejection (rejected). For asynchronous carriers the terminal shipment__refunded event is emitted later by the reconciliation process once the carrier confirms or denies the refund.

Error Scenarios

The endpoint may return the following errors:

Error Code Description
400 Shipment has not been purchased yet.
400 Shipment cannot be refunded (provider doesn't support refunds).
400 The shipment has already been refunded.
400 A refund has already been requested for this shipment.
404 Shipment not found.
500 Internal server error during refund processing.