> For the complete documentation index, see [llms.txt](https://docs.parcellab.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.parcellab.com/docs/developers/v2/returns/rma-actions-api/process-return-api.md).

# Process Return API

Production endpoint URL:

```
https://returns-api.parcellab.com/prod/closeById
```

For details on access, view the overview here:

{% content-ref url="/pages/ECzngWMawj0hRD9NBSDr" %}
[RMA Actions API](/docs/developers/v2/returns/rma-actions-api.md)
{% endcontent-ref %}

For API v4 return registration integrations, use [Process Return Mutations](https://github.com/parcelLab/gitbook-documentation/blob/main/developers-v4/returns/process-return-mutations.md). That page documents the `close_return` mutation and batch receive-status update patterns.

### What This Endpoint Achieves

When successful, the API closes the return in parcelLab and can trigger Shopify return processing actions.

Depending on request flags and merchant configuration, it can:

* Mark the return as `closed`
* Issue a refund for eligible Shopify return line items
* Refund original shipping costs
* Release an exchange draft order
* Apply accepted/rejected article decisions
* Store the scanner identifier in `customFields.scanAs`
* Update return tracking status and Shopify order tags in parcelLab backend systems

### Request

#### Headers

<table><thead><tr><th width="181">Header</th><th width="129">Required</th><th>Type</th></tr></thead><tbody><tr><td><code>user</code></td><td>yes</td><td>string</td></tr><tr><td><code>Content-Type</code></td><td>yes</td><td>string (<code>application/json</code>)</td></tr></tbody></table>

#### JSON Body

<table><thead><tr><th width="246">Field</th><th width="118.5">Required</th><th width="136">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>returnId</code></td><td>yes</td><td>string</td><td>24-character return ID.</td></tr><tr><td><code>lang</code></td><td>yes</td><td>string</td><td>Language context.</td></tr><tr><td><code>country</code></td><td>yes</td><td>string</td><td>Country/market context.</td></tr><tr><td><code>draft</code></td><td>no</td><td>string</td><td>Set to <code>true</code> for draft config.</td></tr><tr><td><code>isRefundEligible</code></td><td>no</td><td>boolean</td><td>Controls whether eligible Shopify return line items should be refunded.</td></tr><tr><td><code>isOriginalShippingRefundEligible</code></td><td>no</td><td>boolean</td><td>Controls whether original shipping costs should be refunded during Shopify refund processing.</td></tr><tr><td><code>isCompleteDraftOrderEligible</code></td><td>no</td><td>boolean</td><td>Controls whether an exchange draft order should be released.</td></tr><tr><td><code>acceptedArticles</code></td><td>no</td><td>array</td><td>Article-level processing decisions. See accepted article fields below.</td></tr><tr><td><code>scanAs</code></td><td>no</td><td>string</td><td>Scanner or operator identifier to store on the return.</td></tr></tbody></table>

#### `acceptedArticles` fields

Each `acceptedArticles` item is a return article object. The endpoint accepts existing article fields from the return document and the processing fields below.

Minimum required fields for each item:

| Field                | Required | Type   | Description                                                   |
| -------------------- | -------- | ------ | ------------------------------------------------------------- |
| `articleNo`          | yes      | string | Article number/SKU used for matching.                         |
| `articleName`        | yes      | string | Article display name.                                         |
| `articleImageUrl`    | yes      | string | Article image URL.                                            |
| `quantity`           | yes      | number | Quantity to process. Must be an integer for close processing. |
| `returnReason`       | yes      | string | Return reason code or text.                                   |
| `prettyProductId`    | yes      | string | Display product identifier.                                   |
| `prettyReturnReason` | yes      | string | Display return reason.                                        |

These fields are enforced by the request schema when `acceptedArticles` is sent. After schema validation, the endpoint performs an additional processing guard that rejects `acceptedArticles` when it is `null`, when it is not an array, or when any item does not have a non-empty `articleNo` and integer `quantity`.

Additional processing fields:

| Field              | Required | Type    | Description                                           |
| ------------------ | -------- | ------- | ----------------------------------------------------- |
| `accepted`         | no       | boolean | Marks the article as accepted.                        |
| `rejected`         | no       | boolean | Marks the article as rejected.                        |
| `rejectionReason`  | no       | string  | Reason for rejecting the article.                     |
| `rejectionDetails` | no       | string  | Additional rejection details.                         |
| `acceptedQuantity` | no       | number  | Quantity accepted for processing.                     |
| `originalQuantity` | no       | number  | Original returned quantity before processing changes. |
| `updatedCondition` | no       | string  | Updated article condition recorded during processing. |

### Example Request

```bash
curl \
  -X POST "https://returns-api.parcellab.com/prod/closeById" \
  -H "user: 1612198" \
  -H "Content-Type: application/json" \
  -d '{
    "returnId": "af0000000000000000000001",
    "lang": "en",
    "country": "us",
    "isRefundEligible": true,
    "isOriginalShippingRefundEligible": false,
    "isCompleteDraftOrderEligible": true,
    "scanAs": "scanner-123",
    "acceptedArticles": [
      {
        "articleNo": "SKU-1001",
        "articleName": "T-Shirt",
        "articleImageUrl": "https://example.com/t-shirt.jpg",
        "quantity": 1,
        "returnReason": "fit",
        "prettyProductId": "SKU-1001",
        "prettyReturnReason": "Did not prefer fit",
        "accepted": true,
        "acceptedQuantity": 1
      }
    ]
  }'
```

### Success Responses (`200 OK`)

#### Processed

```json
{
  "returnId": "af0000000000000000000001"
}
```

#### Skipped

```json
{
  "returnId": "af0000000000000000000001",
  "action": "skipped",
  "reason": "return_already_closed"
}
```

Common `reason` values:

* `return_already_closed`
* `shopify_return_already_closed`
* `concurrent_close_in_progress`

### Business Rules

* This endpoint is intended for Shopify-backed returns.
* If refund or exchange flags are disabled, the return can still be closed without issuing the corresponding refund or exchange action.
* `acceptedArticles` can reduce or exclude refunded quantities. For example, an article with `quantity: 0` is not refunded.
* If Shopify already reports the return as closed, cancelled, or declined, parcelLab updates the local return status and returns a skipped response.
* Concurrent requests for the same return are guarded so only one close process runs at a time.

### Error Responses

<table><thead><tr><th width="108.5">Status</th><th>Error value</th><th>Meaning</th></tr></thead><tbody><tr><td><code>400</code></td><td><code>Payload schema validation failed.</code></td><td>Missing/invalid request input, including required fields inside <code>acceptedArticles</code> items.</td></tr><tr><td><code>400</code></td><td><code>Invalid request body format.</code></td><td>Body is not valid JSON.</td></tr><tr><td><code>400</code></td><td><code>One or more payload fields failed validation. Fields: acceptedArticles</code></td><td><code>acceptedArticles</code> is <code>null</code>, not an array, or contains an item that fails the additional <code>articleNo</code> and integer <code>quantity</code> processing guard.</td></tr><tr><td><code>400</code></td><td><code>FORBIDDEN</code></td><td>The configured returns order API interface does not support this processing action.</td></tr><tr><td><code>400</code></td><td><code>No modifiers to update is set</code></td><td>No valid state change could be applied.</td></tr><tr><td><code>400</code></td><td><code>Shopify draft order could not be completed.</code></td><td>Exchange draft-order completion failed.</td></tr><tr><td><code>400</code></td><td><code>Shopify return could not be closed.</code></td><td>Shopify return processing failed.</td></tr><tr><td><code>400</code></td><td><code>Update return failed.</code></td><td>Return update could not be persisted.</td></tr><tr><td><code>403</code></td><td><code>FORBIDDEN</code></td><td><code>returnId</code> is not accessible in caller context.</td></tr><tr><td><code>404</code></td><td><code>User not found.</code></td><td>Merchant context not found.</td></tr><tr><td><code>404</code></td><td><code>Order does not exist.</code></td><td><code>returnId</code> not found.</td></tr><tr><td><code>500</code></td><td>implementation-defined</td><td>Unexpected server error.</td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.parcellab.com/docs/developers/v2/returns/rma-actions-api/process-return-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
