# noon_content_UpsertProduct (https://sellersheetai.com/docs/mcp-api/tools/noon_content_UpsertProduct)

> Create or update a product listing on noon — new partner_skus create a product, known ones update the product they belong to.

Access: **DESTRUCTIVE** · toolset noon · family noon

Read noon_content_ListCategoryAttributes for the category first; save data.sku_parent and poll noon_content_GetContent until completeness reaches 100. noon API · ContentService_UpsertProduct · POST /content/v1/product/upsert Docs: https://noon-docs.noonpartners.dev/docs/api-reference/content/content-service-upsert-product Gate: approve — interactive: show the change (noon's preview first where one exists), wait for an explicit approve; autopilot: only when the seller's own words asked for this change; otherwise ask.

## Call it

MCP tool call:

```json
{
  "name": "noon_content_UpsertProduct",
  "arguments": {
    "store": "myStore-US",
    "skus": []
  }
}
```

Tool API (early access — contact us):

```bash
curl -X POST https://api.sellersheetai.com/api/v1/tools/noon_content_UpsertProduct \
  -H "Authorization: Bearer $SELLERSHEET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"store":"myStore-US","skus":[]}'
```

## Arguments

| Name | Type | Required | Description |
|---|---|---|---|
| `store` | string | yes | the noon account ref `<account>-<CC>` (name-country, e.g. 'myNoon-AE') — one of get_user_context's noon store_refs, verbatim. |
| `skus` | object[] | yes | the variations (required, non-empty) — partner_sku, unique across all your products, and size, required when there is more than one SKU (e.g. 'Large', '42', 'S'); on update every SKU must belong to the same parent product. |
| `brand` | string |  | the product's brand name. |
| `category` | string |  | a category code from noon_content_ListCategories. |
| `images` | object[] |  | optional [{url (a direct public URL), sort (1-based slot)}] — each sort is a slot: an image replaces that slot, a slot you leave out keeps noon's image. |
| `attributes` | object |  | optional attribute_code -> {values: [{value, language, sort}]} — language is noon's English or Arabic language value, as noon_content_GetContent lists it (one value per language on a localizable attribute), sort orders a multivalued list; a METRIC attribute travels with its '<code>_unit' attribute in the same call. An attribute you leave out keeps its value on noon — nothing is removed. A number may be sent as text. |

## Result

- `data.sku_parent` — the product's id — save it; noon_content_GetContent takes it.
- `data.variants[]` — every variant of the product (also those not sent) — sku, partner_sku, psku_code, size.
- `data.status` — {status_code, message}.

## Body (noon schema)

- skus*: [{partner_sku*, size}] brand*: string category*: string images*: [{url*, sort*}] attributes*: object

## Gotchas

- noon refuses an unknown attribute or a value outside its options as an error naming it. A missing is_mandatory attribute is NOT refused: noon saves the product and lists it in noon_content_GetContent's missing_attributes once it has processed the content.