---
title: "Convert a product table into a Shopify, Google, WooCommerce or custom import file"
method: POST
path: "/v1/schema/normalize"
tags: ["schema"]
---

# Convert a product table into a Shopify, Google, WooCommerce or custom import file

`POST /v1/schema/normalize`

## Request

- Base URL: `https://api.relaex-engineers.de`
- URL: `https://api.relaex-engineers.de/v1/schema/normalize`
- Auth: none declared

Converts a product table into an import file for a target format.

**Input:** multipart `file` (CSV, TSV or XLSX up to 20 MiB, 250,000 rows), `target` as form field
or in `options` (`shopify_products_csv`, `google_merchant`, `woocommerce_products_csv`,
`json_schema`) and optional `options` as a JSON string following
`/v1/schemas/schema-normalize-options`: `json_schema` (for target `json_schema`: an object with
`properties` of type string, number, integer or boolean, optional `enum`, `title`, `x-aliases`,
`x-canonical` and `required`), `column_overrides` (product field or property → column header),
`defaults` (e.g. `{"brand": "Acme", "condition": "new"}`), `default_currency`, `weight_unit`,
`availability_from_stock`, `max_output_rows`, `output` (`json` or `csv`).

**Behaviour:** the header row and columns are recognised via a versioned multilingual alias set
of 22 product fields (SKU, title, description, prices, currency, GTIN, brand, stock, weight,
images, …). Number formats are inferred per column, currencies from a column or the price
text, weights converted from the unit in the header, GTINs checked for length (a lost leading
zero is restored only for numeric cells), availability mapped from local words or derived
from the stock quantity. Each target column reports its source (`column`, `derived`,
`default`, `constant`, `missing`). Shopify and Google outputs are validated with the feed
rules of `/v1/merchant/validate`; `summary.import_ready` is true only without errors.

**Output:** `ApiResponse` with `NormalizeResult` (mapping, issues, summary, output CSV), or with
`output=csv` the CSV file itself with headers `X-Import-Ready` and `X-Confidence`.

**Errors:** 400 invalid file, 413 too large, 422 no header row, invalid options or schema, 429
rate limit, 504 timeout.

**Languages:** responses are in English. Error, warning and rule codes are stable and
language-neutral; agents may translate messages for the user. Column headers and common cell words are recognised in English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Czech, Turkish, Swedish, Danish, Norwegian, Finnish, Korean, Japanese and Chinese; numbers in both 1.234,56 and 1,234.56 style; any ISO 4217 currency (no conversion).

**Access:** open, rate-limited per IP and per MCP session; an `X-API-Key` header raises the
limit. Uploaded files are processed in memory and never stored. Also available as MCP tool
`schema_normalize` at `/mcp` (Streamable HTTP).

## Response `200`

ApiResponse with NormalizeResult, or text/csv with output=csv

- unknown

## Other responses

- `400`: INVALID_FILE, EMPTY_FILE, UNSUPPORTED_FORMAT, INVALID_ENCODING
- `413`: FILE_TOO_LARGE, ROW_LIMIT_EXCEEDED
- `422`: HEADER_NOT_FOUND, SHEET_NOT_FOUND, INVALID_OPTIONS
- `429`: RATE_LIMITED
- `504`: ANALYSIS_TIMEOUT

---

[API](https://skmtc.dev/relaex-engineers/apis/boring-api.md) · [All operations](https://skmtc.dev/relaex-engineers/apis/boring-api/llms.txt) · [OpenAPI document](https://skmtc.dev/relaex-engineers/apis/boring-api/revisions/269481105eb2?raw)
