> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.taxcloud.com/api-v-3/guides/workflows/processing-returns/standard-returns/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.taxcloud.com/_mcp/server. # Standard returns The [Refund API](https://docs.taxcloud.com/api-reference/api-reference/sales-tax-api/refunds/refund-order) lets you reverse part or all of an existing order's tax liability. When you issue a return, TaxCloud automatically references the original order's tax calculation, including rates, TICs, and exemption status, and adjusts the appropriate amounts. TaxCloud supports both full and partial returns, as well as multiple returns against the same order. Each return reduces the remaining returnable balance, and you can continue issuing returns until the cumulative total equals the original order amount. For tax timing implications, backdated returns, and compliance considerations, see the [Returns & Credits Overview](https://docs.taxcloud.com/guides/workflows/processing-returns/overview). For credits not tied to an existing order, see [Standalone Credits](https://docs.taxcloud.com/guides/workflows/processing-returns/standalone-credits). ## Before You Begin To issue a return, you need: * The `connectionID` for your TaxCloud connection. * The `orderID` of the order you want to return against. * The order must be in a completed state (i.e., it has a `completedDate`). ## Step 1: Retrieve the order Before processing a return, retrieve the order to verify its current state, confirm which items are eligible for return, and check whether any previous returns have been issued. ```shell curl -X GET "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/{orderId}?expand=refunds" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" ``` A successful response returns the order, including each line item's `index`. When you pass `expand=refunds`, the response adds a `refunds` array only if the order has returns; the field is omitted entirely when there are none, as in this example: ```json { "connectionId": "25eb9b97-5acb-492d-b720-c03e79cf715a", "orderId": "order-789", "completedDate": "2025-02-01T00:00:00Z", "lineItems": [ { "index": 0, "itemId": "item-1", "originalPrice": 12, "price": 10.8, "quantity": 1, "tax": { "rate": 0.08125, "amount": 0.88 }, "tic": 0 }, { "index": 1, "itemId": "item-2", "originalPrice": 24.99, "price": 24.99, "quantity": 2, "tax": { "rate": 0.08125, "amount": 4.06 }, "tic": 0 } ] } ``` Review the response to confirm: * The order exists and has a `completedDate`. * The items you intend to return are present in `lineItems`. * If the order has previous returns, the `refunds` array lists them, but only when you request `expand=refunds`. On an `expand=refunds` request, an absent `refunds` array means no returns have been issued; on a bare `GET`, the field is always absent and says nothing about returns. ## Step 2: Issue a return Submit a return request to the [Refund API](https://docs.taxcloud.com/api-reference/api-reference/sales-tax-api/refunds/refund-order) endpoint. ```shell POST /tax/connections/{connectionId}/orders/refunds/{orderId} ``` If your system may retry this call, include an `idempotencyKey` in the request body so a retry does not create a duplicate. See [Idempotent Returns](#idempotent-returns). ### Full Return To return the entire order, send an empty request body or omit the `items` array. TaxCloud will return all line items at their original quantities. ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{}' ``` ### Partial Return To return specific items, include only the items being returned with their `itemId` and `quantity`. TaxCloud calculates the tax adjustment based on the original tax rate applied to those items. ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "items": [ { "itemId": "item-1", "quantity": 1 } ] }' ``` ### Response The API returns an array containing all returns issued against this order, not just the current one. This gives you a complete view of the order's return history in every response. ```json [ { "connectionId": "25eb9b97-5acb-492d-b720-c03e79cf715a", "items": [ { "index": 0, "itemId": "item-1", "price": 10.8, "quantity": 1, "tax": { "amount": 0.88 }, "tic": 0 } ], "createdDate": "2025-02-15T14:30:00Z", "returnedDate": "2025-02-15T14:30:00Z" } ] ``` Each return object in the array includes: * **`items`** — The line items included in that specific return, with the tax amount that was reversed. * **`createdDate`** — When the return was created in TaxCloud. * **`returnedDate`** — The effective date of the return, if provided. See [Backdated returns](https://docs.taxcloud.com/guides/workflows/processing-returns/standard-returns#backdated-returns) below. * **`idempotencyKey`** — Echoed back when the return was created with an idempotency key. See [Idempotent Returns](https://docs.taxcloud.com/guides/workflows/processing-returns/standard-returns#idempotent-returns) below. ## Step 3: Issue additional returns You can issue multiple returns against the same order. Each subsequent return request follows the same format, specifying the items and quantities being returned. For example, if a customer initially returns one item and later returns a second item from the same order: **First return** — return `item-1`: ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "items": [ { "itemId": "item-1", "quantity": 1 } ] }' ``` **Second return** — return `item-2`: ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "items": [ { "itemId": "item-2", "quantity": 2 } ] }' ``` The response to the second return includes both returns: ```json [ { "connectionId": "25eb9b97-5acb-492d-b720-c03e79cf715a", "items": [ { "index": 0, "itemId": "item-1", "price": 10.8, "quantity": 1, "tax": { "amount": 0.88 }, "tic": 0 } ], "createdDate": "2025-02-10T14:30:00Z", "returnedDate": "2025-02-10T14:30:00Z" }, { "connectionId": "25eb9b97-5acb-492d-b720-c03e79cf715a", "items": [ { "index": 1, "itemId": "item-2", "price": 24.99, "quantity": 2, "tax": { "amount": 4.06 }, "tic": 0 } ], "createdDate": "2025-02-15T10:00:00Z", "returnedDate": "2025-02-15T10:00:00Z" } ] ``` ### Cumulative Limit TaxCloud enforces that the total returned amount across all returns cannot exceed the original order total. If a return request would push the cumulative total over the order amount, the API returns an error. You do not need to track this limit yourself, TaxCloud validates it on every request. ## Backdated Returns The `returnedDate` parameter is optional and should only be used when the return actually occurred on a date different from when you're submitting it to TaxCloud. ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "items": [ { "itemId": "item-1", "quantity": 1 } ], "returnedDate": "2025-01-05T00:00:00Z" }' ``` > **Important** > > If the `returnedDate` falls within a previously filed tax period, this may trigger the need for an amended sales tax return. TaxCloud does not currently generate automatic alerts for this, you are responsible for tracking these cases and contacting TaxCloud support if an amendment is required. ## Idempotent Returns Pass an `idempotencyKey` to make retries safe. Creating a new return responds with `201 Created`. A repeat request with the same key, for the same connection and order, returns `200 OK` with the existing return history instead of creating a new one. The status code tells you whether the request created anything, which protects you when a request times out, or when an extract, transform, load (ETL) pipeline or message queue redelivers an event. Reusing a key never amends the original return. The request is still validated, but once a matching key is found TaxCloud returns the existing return history — the full array — without applying the new `items`, quantities, or `returnedDate`. To record a genuinely different return, use a new `idempotencyKey`. > **Tip** > > Use a stable identifier from your source system, such as a Shopify refund ID or an order management system's refund ID, rather than a per-request UUID. A key that changes on each attempt makes every retry look like a new return, which is the duplicate this feature prevents. An `idempotencyKey` may be 1 to 200 characters. ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "idempotencyKey": "gid://shopify/Refund/12345", "items": [ { "itemId": "item-1", "quantity": 1 } ] }' ``` A replayed request returns the existing history unchanged, with the key echoed on the return the original request created: ```json [ { "connectionId": "25eb9b97-5acb-492d-b720-c03e79cf715a", "idempotencyKey": "gid://shopify/Refund/12345", "items": [ { "index": 0, "itemId": "item-1", "price": 10.8, "quantity": 1, "tax": { "amount": 0.88 }, "tic": 0 } ], "createdDate": "2025-02-15T14:30:00Z", "returnedDate": "2025-02-15T14:30:00Z" } ] ``` ## Edge Cases ### Returns on Tax-Exempt Orders If the original order was fully tax-exempt (e.g., covered by an exemption certificate), no tax adjustment is processed since no tax was collected. The return is still recorded for transaction accuracy, but the tax amount in the response will be zero. ### Returns on Discounted Items When the original order included discounts, TaxCloud returns based on the actual post-discount price and tax that was calculated. If you need to return a prorated portion of a discounted item, submit the request with the fractional quantity that represents the discounted amount. ### Returns on Repeated Item IDs If the original order used the same `itemId` on more than one line, `itemId` alone cannot identify which line to return against. Pair it with `cartItemIndex` to target the exact line. `cartItemIndex` is the zero-based `index` you assign to each line item when you create the order; together, `(itemId, index)` identifies a line: * If you supply `cartItemIndex`, the return applies to the line matching that exact `(itemId, index)` pair. The index does not override `itemId`: if no line matches both, the request is rejected with `400 Bad Request`. * If you omit `cartItemIndex` and exactly one line matches the `itemId`, that line is used. * If you omit `cartItemIndex` and multiple lines share the `itemId`, the request is rejected with `400 Bad Request`. Store both the `itemId` and the `index` you assigned on the original order if you may later return an individual line. For example, if the original order lists `sku-123` at `index` 0 and again at `index` 2, this request returns only the second of those lines: ```shell curl -X POST "https://api.v3.taxcloud.com/tax/connections/{connectionId}/orders/refunds/{orderId}" \ -H "X-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "items": [ { "itemId": "sku-123", "cartItemIndex": 2, "quantity": 1 } ] }' ``` ### Returning the Remaining Balance After one or more partial returns, you can return the remaining balance by sending an empty `items` array (just as you would for a full return). TaxCloud will return whatever items and quantities have not yet been returned. ## Error Handling | Error | Cause | Resolution | | ----- | ----- | ----- | | `400` Bad Request | Malformed request body or invalid item data; an item not found on the order; an ambiguous `itemId` sent without `cartItemIndex`; or a `cartItemIndex` that does not match the line | Verify the `itemId` exists on the order; when an `itemId` appears on more than one line, include its `cartItemIndex`. Check the request format against the [API reference](https://docs.taxcloud.com/api-reference/api-reference/sales-tax-api/refunds/refund-order) | | `404` Not Found | Order does not exist or does not belong to this connection | Confirm the `orderID` and `connectionID` are correct | | `422` Unprocessable Entity | Return exceeds the remaining refundable amount | Check the cumulative return total against the original order | For the complete list of error responses, see the [Refund API reference](https://docs.taxcloud.com/api-reference/api-reference/sales-tax-api/refunds/refund-order#response.error). ## Best Practices * **Always retrieve the order first** with `?expand=refunds` to confirm its state and any existing returns before issuing a new one. * **Use the response array** to track return history rather than maintaining your own ledger. Each response gives you the complete picture. * **Omit `returnedDate`** unless the return genuinely occurred on a different date. Including it unnecessarily can complicate your filing timeline. * **Prefer standard returns** over standalone credits whenever you have the original order ID. This maintains the strongest audit trail for compliance. * **Set an `idempotencyKey`** when your system may retry a return. A repeat with the same key returns the existing return instead of creating a duplicate.