# SKU mappings

Orders from your store or from files use your own SKUs. A mapping tells us which of your products a SKU is, so order lines match by themselves. An order line whose SKU isn't mapped, and that has no `productId`, makes the order need attention (problem `UNBOUND_LINE`).

- A SKU maps to one product. To move it to another product, send `move: true`; without it you get `409 library_sku_taken`.
- The product must be in My products, otherwise you get `422 library_not_in_library`.
- Orders waiting for this SKU are matched again straight away, and the response says how many. They go through the same checks as saving an order, so they can move on: stock reserved, shipping fee held, auto purchase may run. If `moreOrders` is `true`, save the remaining orders again with [`PATCH /v1/orders/{id}`](https://docs.rephut.com/developers/reference/orders#change-an-order-that-needs-attention) to match them.
- A product's mapped SKUs are in `customerSkus` from [`GET /v1/products`](https://docs.rephut.com/developers/reference/products#list-your-products). Mappings can't be removed through the API; remove them in the portal.

## Map your SKU to one of your products

`POST /v1/sku-mappings`

Adds your SKU to a product in My products, like adding a SKU on the portal's My products page. Orders that need attention because of this SKU are matched again right away. A product that isn't in My products returns 422 library_not_in_library.

| Property | Value |
|---|---|
| URL | `https://api.rephut.com/v1/sku-mappings` |
| Permission | `catalog:write` |
| Access | Write: counts towards the write limits and is refused with `account_on_hold` while your account is on hold |
| Idempotency-Key | Optional, recommended |
| Success | 201 Created |

### Headers

| Header | Required | Value |
|---|---|---|
| `Authorization` | Yes | `Bearer <your API key>`. See [Authentication](https://docs.rephut.com/developers/authentication). |
| `Content-Type` | Yes | `application/json` |
| `Idempotency-Key` | No | 1 to 255 visible ASCII characters, new for each new request. See [Idempotency](https://docs.rephut.com/developers/idempotency). |

### Request body

A JSON object. Fields not listed here are ignored.

| Field | Type | Required | Description |
|---|---|---|---|
| `customerSku` | string | Yes | Your SKU, as it appears on your orders. 1 to 100 characters. |
| `productId` | string | Yes | Our product id from GET /v1/products (a product in My products). 1 to 64 characters. |
| `move` | boolean | No | Your SKU is already mapped to another product: send true to move it to this product. Otherwise you get 409 library_sku_taken. Default: `false`. |

### Response

`201` with `data`, an object with the fields below.

| Field | Type | Description |
|---|---|---|
| `customerSku` | string | Your SKU, as saved. |
| `productId` | string | The product the SKU now maps to. |
| `rematchedOrders` | integer | Orders waiting on this SKU that now use the product. |
| `ordersStillNeedingAttention` | integer | Of those orders, how many still need other fixes. |
| `moreOrders` | boolean | More waiting orders use this SKU than we updated now; save them again with PATCH /v1/orders/{id} to match them. |

### Errors

| Code | HTTP status | Meaning |
|---|---|---|
| `invalid_idempotency_key` | 400 | Idempotency-Key must be 1 to 255 visible ASCII characters. |
| `invalid_json` | 400 | The request body is not valid JSON. |
| `invalid_api_key` | 401 | The API key is missing, malformed, revoked or no longer valid. |
| `account_action_required` | 403 | Sign in to the portal and finish the required account steps first. |
| `account_on_hold` | 403 | The account is on hold. Writes are refused; reads still work. |
| `api_not_enabled` | 403 | API access is not enabled for this account. |
| `insufficient_scope` | 403 | The API key does not have the permission this call needs. |
| `library_sku_taken` | 409 | This SKU is already used for another product. |
| `request_in_progress` | 409 | A request with this Idempotency-Key is still running or its result is unknown. |
| `payload_too_large` | 413 | The request body is larger than 1 MB. |
| `unsupported_media_type` | 415 | The request body must be sent as application/json. |
| `idempotency_key_reused` | 422 | This Idempotency-Key was already used with a different request. |
| `library_not_in_library` | 422 | This product is not in My products. Please refresh the page. |
| `request_rejected` | 422 | The request was rejected by a business rule. |
| `validation_failed` | 422 | The input is not valid. `details` lists each field and the reason. |
| `rate_limited` | 429 | Too many requests. Wait for the number of seconds in Retry-After. |
| `internal_error` | 500 | Unexpected error. Quote X-Request-Id when you contact support. |

Handle errors by `code`. See [Errors](https://docs.rephut.com/developers/errors).

```bash example=curl
curl -X POST 'https://api.rephut.com/v1/sku-mappings' \
  -H "Authorization: Bearer $FULFILLBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -H 'Idempotency-Key: 0b7e2d8c-5a14-4f3b-9c61-2d8e7f1a4b90' \
  -d '{
  "customerSku": "MUG-WHT",
  "productId": "cm3p4r0d0002xyz7k2m9q8w2"
}'
```

```js example=node
const response = await fetch("https://api.rephut.com/v1/sku-mappings", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.FULFILLBOT_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "0b7e2d8c-5a14-4f3b-9c61-2d8e7f1a4b90",
  },
  body: JSON.stringify({
    "customerSku": "MUG-WHT",
    "productId": "cm3p4r0d0002xyz7k2m9q8w2"
  }),
});
const result = await response.json();
console.log(response.status, result);
```

```python example=python
import os

import requests

response = requests.post(
    "https://api.rephut.com/v1/sku-mappings",
    headers={
        "Authorization": f"Bearer {os.environ['FULFILLBOT_API_KEY']}",
        "Idempotency-Key": "0b7e2d8c-5a14-4f3b-9c61-2d8e7f1a4b90",
    },
    json={
        "customerSku": "MUG-WHT",
        "productId": "cm3p4r0d0002xyz7k2m9q8w2",
    },
    timeout=30,
)
print(response.status_code, response.json())
```

```json example=response status=201
{
  "success": true,
  "data": {
    "customerSku": "MUG-WHT",
    "productId": "cm3p4r0d0002xyz7k2m9q8w2",
    "rematchedOrders": 2,
    "ordersStillNeedingAttention": 0,
    "moreOrders": false
  }
}
```
