# Japan-Ready Supplier CSV to Shopify Preflight (`gwave-aso/supplier-csv-shopify-preflight-japan-ready`) Actor

Upload a supplier CSV or provide CSV text to get a draft Shopify import CSV and preflight report. Supports UTF-8, Shift-JIS, CP932, Japanese headers, JAN/EAN, and leading-zero IDs. Pay per event: $0.001 per successfully processed row. No start, summary, or error-row charges.

- **URL**: https://apify.com/gwave-aso/supplier-csv-shopify-preflight-japan-ready.md
- **Developed by:** [ジーウェイブ阿蘇合同会社](https://apify.com/gwave-aso) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 processed rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Japan-Ready Supplier CSV to Shopify Preflight

Upload a messy supplier CSV to get a **draft Shopify product import CSV** and a row-by-row preflight report. This Actor prepares new, simple products for review. It does not publish or import them into Shopify.

### What it does

- Maps common Japanese supplier headers to Shopify fields; normalizes full-width text and spacing; preserves leading zeros in SKUs and barcodes.
- Checks GTIN-8/GTIN-13 check digits, clear prices, and integer inventory quantities. A valid check digit does **not** prove a barcode was officially issued or belongs to the product.
- Removes a small set of promotional phrases and records each removal in the report.
- Writes `shopify_import.csv`, `preflight_report.json`, and `SUMMARY` to the run's Apify key-value store. Every imported product is `Status=draft` and `Published on online store=false`.

### Who it is for

Shopify merchants and operators receiving supplier CSVs, especially files with Japanese headers, full-width characters, JAN/EAN values, or identifiers that start with zero. It is useful for any supplier CSV that fits this simple-product workflow; the supplier need not be Japanese.

### Why use it instead of fixing a CSV by hand?

Spreadsheet software can silently convert `00123` to `123`. Hand edits also make it easy to miss a broken barcode, a currency mismatch, or a variant column. This tool applies the same rules to every row and leaves an audit trail of warnings, errors, original prices, and removed sales text. **Review the report and Shopify import preview before using the output.**

### Japan-ready features and input

Upload a CSV file directly in Apify Console. The file route passes its original bytes to strict, deterministic UTF-8 BOM, UTF-8, Shift-JIS, then CP932 detection. Unknown encodings produce a report error; the Actor does not continue with garbled text. The bundled local CLI uses the same byte-level converter. For API and AI agents, `csvText` remains available for an already decoded Unicode CSV string. Provide **exactly one** of `csvFile` or `csvText`.

Apify's `fileupload` editor saves the file in Apify Key-value Store and passes the Actor an Apify record reference. The Actor accepts only an `api.apify.com` key-value record reference and reads it through Apify's SDK/client; it does not fetch arbitrary URLs or send the file to another service.

Japanese header mappings include 商品名/商品タイトル, 商品説明/説明, メーカー/ブランド, SKU/品番/商品コード, JAN/EAN/バーコード, 売価/販売価格/価格, and 在庫/在庫数. Unicode NFKC handles characters such as `ＳＯＮＹ` and `１２３４`. The output keeps SKU and barcode cells as strings.

### Quick start in Apify

1. Upload a supplier CSV with the **CSV file** field. Alternatively, API/AI users can provide the complete decoded CSV body in `csvText`. Include the header row and use only one input route.
2. Set `sourceCurrency` to the supplier price currency and `targetCurrency` to the Shopify store currency, using three uppercase letters such as `JPY` and `USD`.
3. Run privately, download `preflight_report.json`, and review every warning and error. Download `shopify_import.csv` only after the report looks right.
4. Import one or two test products into a Shopify store you control. Keep **Overwrite products with matching handles** off, inspect Shopify's preview, and verify the products remain drafts. The Actor itself never connects to Shopify.

API/AI text input example:

```json
{
  "csvText": "商品名,品番,JAN,価格,在庫,メーカー\n【送料無料】架空サンプル商品Ａ,00123,01234565,\"￥1,980\",10個,架空メーカー\n",
  "sourceCurrency": "JPY",
  "targetCurrency": "JPY"
}
```

For the upload field, choose [`sample_supplier_utf8.csv`](sample_supplier_utf8.csv) or the same fictional data as [`sample_supplier_shiftjis.csv`](sample_supplier_shiftjis.csv). Apify supplies `csvFile` as its own key-value record reference; do not enter a third-party URL. `01234565` is a mathematical GTIN-8 test value, **not** a claim that a real product uses it.

### Output example

The example output is generated from `sample_supplier_utf8.csv` with JPY → JPY. The real CSV includes a UTF-8 BOM and Shopify's full set of emitted columns; see [`sample_shopify_import.csv`](sample_shopify_import.csv).

```csv
Title,Description,Vendor,Status,Published on online store,Option1 name,Option1 value,SKU,Barcodes,Price,Inventory tracker,Inventory quantity
架空サンプル商品A,,架空メーカー,draft,false,Default Title,Default Title,00123,gtin:01234565,1980,shopify,10
```

The corresponding [`sample_preflight_report.json`](sample_preflight_report.json) records one input and exported row, the Japanese header mapping, the original `￥1,980` price, removal of `送料無料`, and `INVENTORY_SINGLE_LOCATION_ONLY`. It has row-level `warnings` and `errors`. `SUMMARY` exposes `input_count`, `exported_count`, `warning_count`, `error_count`, and `detected_encoding`. Rows with errors or blocking ambiguity are not exported. Unmapped supplier columns are listed in the report and are never silently added to the Shopify CSV.

### Try a fictional 10-row Japanese supplier CSV

Copy the entire block into **Supplier CSV text** (`csvText`), leave **CSV file** empty, and set both currencies to `JPY`. It contains one header plus 10 data rows. All product and manufacturer names are fictional. Barcode numbers are synthetic mathematical test strings, not issued JAN/EAN identifiers or real-product claims; never use them on live merchandise.

```csv
商品名,品番,JAN,価格,在庫,メーカー
【送料無料】架空検証商品Ａ,00001,01234565,"￥1,980",10個,架空検証メーカー
架空検証商品Ｂ,00002,0000000000000,1200,5,架空検証メーカー
架空検証商品Ｃ,00003,,500,0,架空検証メーカー
架空検証商品Ｄ,00004,01234565,１０００,３,架空検証メーカー
架空検証商品Ｅ,00005,01234565,750,2,架空検証メーカー
架空検証商品Ｆ,00006,01234566,900,4,架空検証メーカー
架空検証商品Ｇ,00007,1234567,800,1,架空検証メーカー
架空検証商品Ｈ,00008,01234565,要相談,2,架空検証メーカー
架空検証商品Ｉ,00009,01234565,600,1.5,架空検証メーカー
,00010,01234565,400,1,架空検証メーカー
```

For Shift-JIS / CP932 files, save the CSV in the intended encoding and upload it through **CSV file**, leaving `csvText` empty. Pasting text does not test byte-level encoding detection. The result below was verified with `csvText` (reported as UTF-8); it is not a claim of a separate Shift-JIS / CP932 run for this sample.

#### Example result — verified on public build 0.1.3

Actual run on 2026-09-29 with JPY → JPY: **10 input rows, 6 exported draft rows, 4 withheld rows**. Report summary excerpt:

```json
{"input_count":10,"ok_count":0,"warning_count":9,"error_count":1,"exported_count":6,"detected_encoding":"UTF-8"}
```

`ok_count` is not the exported-row count: exported rows can carry warnings. Row numbers below exclude the header.

| Input rows | Actual result |
| --- | --- |
| 1–5 | Exported as drafts. Japanese headers mapped to Shopify fields. Full-width A–E, price `１０００`, and stock `３` normalized. Row 1 removed `送料無料`, retained original price `￥1,980` in the report, and emitted price `1980`. |
| 6 | Exported as a draft with an empty barcode and warning `GTIN_CHECK_DIGIT_INVALID`; `01234566` was reported as GTIN-8, `valid: false`. This is a warning, not a row error. |
| 7 | Withheld; `BARCODE_UNRECOGNIZED` for the seven-digit test string. |
| 8 | Withheld; `PRICE_AMBIGUOUS` for `要相談`. |
| 9 | Withheld; `INVENTORY_AMBIGUOUS` for `1.5`. |
| 10 | Withheld; error `TITLE_MISSING`. |

Rows 1–8 and 10 include `INVENTORY_SINGLE_LOCATION_ONLY`. The report recognizes `01234565` as GTIN-8 and `0000000000000` as GTIN-13 with `valid: true` **for the check digit only**; this does not validate issuance or product identity. The missing barcode on row 3 stays blank.

Draft output excerpt (actual rows 1, 2 and 6; the full file contains six rows):

```csv
Title,Description,Vendor,Status,Published on online store,Option1 name,Option1 value,SKU,Barcodes,Price,Inventory tracker,Inventory quantity
架空検証商品A,,架空検証メーカー,draft,false,Default Title,Default Title,00001,gtin:01234565,1980,shopify,10
架空検証商品B,,架空検証メーカー,draft,false,Default Title,Default Title,00002,gtin:0000000000000,1200,shopify,5
架空検証商品F,,架空検証メーカー,draft,false,Default Title,Default Title,00006,,900,shopify,4
```

All six exported rows have `Status=draft` and `Published on online store=false`. SKU leading zeros and valid barcode leading zeros remain intact. Under the pricing below, six successfully exported rows correspond to $0.006 in processed-row event fees; withheld rows, Actor start and the dataset summary add no event charge.

### Pricing

Pay per event: **$0.001 per successfully processed row** (`processed-row`), or **$1.00 per 1,000 rows**. Only rows successfully exported to the draft Shopify CSV are charged. Rows with errors or blocking ambiguity are not charged. There is no Actor-start charge and no charge for the dataset summary. Platform usage is included in this price and is not separately charged to the user.

### Important limits and safety

- **No currency conversion.** Confirm both the supplier price currency and the Shopify store currency. If they differ, `Price` stays blank and the report records `CURRENCY_CONVERSION_REQUIRED` plus the original price. Shopify may treat an empty price as 0.00; set a verified store-currency price before publishing the product.
- **Drafts only.** `Status=draft` and `Published on online store=false` prevent accidental immediate publication from this CSV. Do not change those fields until you have reviewed the import.
- **No automatic variants.** Variant-like columns or repeated titles trigger `VARIANT_REVIEW_REQUIRED`; the affected rows are withheld. Shopify variant fields depend on each other, so a guessed option layout is unsafe.
- **Single-location inventory only.** `Inventory quantity` in this product CSV is suitable for one Shopify location. Exported inventory rows carry `INVENTORY_SINGLE_LOCATION_ONLY`. For multiple locations, use Shopify's separate inventory workflow after review.
- **No web scraping, URL fetching, third-party API calls, OpenAI API, or Gemini API.** The Actor does not send product data to third-party sites or services. **On Apify cloud, the CSV input and generated files necessarily pass through and are stored on Apify's platform**; the SDK uses Apify's own storage and charging APIs.
- No translation, SEO generation, existing-product update, automatic product merge, image URL check, or Shopify publication.
- Spreadsheet formula protection prefixes suspicious text beginning with `=`, `+`, `-`, or `@` with an apostrophe. Preserve identifiers as text if you open the CSV in spreadsheet software.

### Local CLI and tests

Python 3.11+ is required for the Actor adapter. The CLI converter itself uses the standard library. From this folder:

```text
python -m src sample_supplier_utf8.csv --out output --source-currency JPY --target-currency JPY
python -m src sample_supplier_shiftjis.csv --out output-shiftjis --source-currency JPY --target-currency JPY
python -m pip install -r requirements.txt
python -m unittest discover -s tests -v
```

The only direct SDK dependency is pinned at `apify==4.0.2`. The local Actor runs with `python -m src.actor_main` using `storage/key_value_stores/default/INPUT.json`. A no-billing PPE test uses `ACTOR_TEST_PAY_PER_EVENT=true`. The adapter charges only exported rows in deterministic source order and respects the SDK charge limit. Local Docker build was not verified on the original PC because virtualization was unavailable; private Apify cloud build `0.1.3` and file-upload runs were verified.

### 日本語での概要

仕入先CSVを直接アップロードし、Shopifyの**下書き商品CSV**と事前検査レポートに変換できます。UTF-8 BOM・UTF-8・Shift-JIS・CP932、日本語見出し、全角文字、JAN/EAN、先頭ゼロのSKUに対応します。API/AI利用向けの`csvText`本文入力も残しています。**通貨換算はせず、複雑なバリエーションや複数拠点の在庫も自動処理しません。** 取り込み前に警告とShopifyのプレビューを確認してください。

Shopify product CSV guidance: [format](https://help.shopify.com/en/manual/products/import-export/using-csv) and [import steps](https://help.shopify.com/en/manual/products/import-export/import-products).

# Actor input Schema

## `csvFile` (type: `string`):

Upload one supplier CSV file to Apify storage. UTF-8 BOM, UTF-8, Shift-JIS and CP932 bytes are supported. Use this or CSV text, not both. External URLs are rejected.

## `csvText` (type: `string`):

For API and AI use: complete decoded CSV body, including a Title or 商品名 header. Use this or CSV file, not both.

## `sourceCurrency` (type: `string`):

Three-letter currency code of the input prices, such as JPY.

## `targetCurrency` (type: `string`):

Three-letter currency code configured in the target Shopify store.

## Actor input object example

```json
{
  "csvText": "商品名,SKU,価格\n阿蘇サンプル商品,000123,1000\n",
  "sourceCurrency": "JPY",
  "targetCurrency": "JPY"
}
```

# Actor output Schema

## `shopifyCsv` (type: `string`):

No description

## `preflightReport` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "csvText": `商品名,SKU,価格
阿蘇サンプル商品,000123,1000`,
    "sourceCurrency": "JPY",
    "targetCurrency": "JPY"
};

// Run the Actor and wait for it to finish
const run = await client.actor("gwave-aso/supplier-csv-shopify-preflight-japan-ready").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "csvText": """商品名,SKU,価格
阿蘇サンプル商品,000123,1000
""",
    "sourceCurrency": "JPY",
    "targetCurrency": "JPY",
}

# Run the Actor and wait for it to finish
run = client.actor("gwave-aso/supplier-csv-shopify-preflight-japan-ready").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "csvText": "商品名,SKU,価格\\n阿蘇サンプル商品,000123,1000\\n",
  "sourceCurrency": "JPY",
  "targetCurrency": "JPY"
}' |
apify call gwave-aso/supplier-csv-shopify-preflight-japan-ready --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gwave-aso/supplier-csv-shopify-preflight-japan-ready"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/cn4G4IFJI4F92eFeY/builds/wHt9XniJ502izPJJz/openapi.json
