Importing Size Charts
Brandmachine's Designer uses your size specs (the measurement tables you give a factory) to put real dimensions on a design. You bring them in with one REST call that takes a JSON file. This page describes that file and what happens to it.
If your specs live in Excel, PDF or a PLM system, you convert them to this JSON format first. Brandmachine does not read spreadsheets, images or PDFs, because every customer sheet is laid out differently and a guess at what a column means would end up as a wrong number on a design.
The Short Version
- Convert each size chart to the JSON format below. Measurements are whole numbers in hundredths of a centimetre, so 63.20 cm is
6320. - Use measurement names from the closed list in Measurement Codes. A name that is not on the list rejects the file.
- Send the file with
?dryRun=truefirst. Check that the report says"dryRun": true, because a misspelled parameter is ignored and the file is imported for real. Fix what the report lists. - Send it again without
dryRun. Nothing is saved unless the whole file is valid.
Send a File
POST https://production.api.brandmachine.shop/api/size-charts/import
The request is multipart/form-data with the JSON file in the file field. Authenticate with an API token, as for every file upload:
curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -F "file=@size-charts.json" \ "https://production.api.brandmachine.shop/api/size-charts/import?dryRun=true"
Who can import: the import changes your shared library, so it needs the Creator role or higher. This applies to an API token as well: a token only works if it was created with that role or a higher one. With a lower role the call fails with HTTP status 403 and the reason You do not have permission to do this. Reading charts back needs no more than a Viewer token.
The request body can be up to 32 MB. No smaller limit on charts, sizes or rows is enforced.
The Response
Once the file reaches the importer, the response is HTTP status 200, also when the file is invalid. A request without a file field is refused with an HTTP error before that. Problems are in the report, not in the status code.
{
"dryRun": true,
"imported": false,
"charts": [
{
"code": "BOY-TSS-BASIC-FIT",
"name": "TSS BASIC FIT",
"department": "boys",
"garmentType": "tee-short-sleeve",
"sizes": ["104", "116", "128", "140", "152", "164", "176"],
"baseSize": "140",
"rowCount": 1,
"incrementRowCount": 0,
"action": "CREATE"
}
],
"errors": [],
"warnings": []
}
| Field | Meaning |
|---|---|
dryRun | true when you sent ?dryRun=true. A dry run never saves anything. |
imported | true only when the charts were saved. Always false on a dry run, and whenever errors is not empty. |
charts | One summary per chart in the file. |
charts[].patternGroup | Present only when the chart has a pattern_group. Fields that have no value are left out of the report, not sent as null. |
charts[].action | CREATE for a new chart code, SUPERSEDE when the code already exists in your library (see Re-importing). |
charts[].incrementRowCount | Rows that have grade steps but no absolute value. See Rows. |
errors | Problems that stop the import. Each has kind (INVALID) and a message, plus chartCode and rowKey when the problem belongs to a chart or a row. |
warnings | Things worth a look that never block the import. |
The File Format
A file holds one or more charts. This is the smallest valid file:
{
"format_version": 1,
"source": { "file": "QC BOYS 26.xlsx" },
"charts": [
{
"code": "BOY-TSS-BASIC-FIT",
"name": "TSS BASIC FIT",
"garment_type": "tee-short-sleeve",
"product_group": "tops",
"department": "boys",
"pattern_group": null,
"sizes": ["104", "116", "128", "140", "152", "164", "176"],
"base_size": "140",
"rows": [
{
"code": "SLEEVE_LENGTH",
"origin": "CB",
"source_label": "Sleevelength from CB",
"convention": "full",
"base_hundredths": 3750,
"grade_deltas_hundredths": {
"104": -800,
"116": -500,
"128": -250,
"140": 0,
"152": 250,
"164": 500,
"176": 750
},
"tolerance": {
"minus_hundredths": -80,
"plus_hundredths": 80,
"raw": "-0,8/+0,8"
}
}
]
}
]
}
The value of a measurement at any size is the base value plus the grade step for that size. In the example, the sleeve length is 37.50 cm at size 140 and 45.00 cm at size 176.
File
| Field | Type | Required | Notes |
|---|---|---|---|
format_version | integer | Yes | Must be 1. |
source.file | string | No | The name of the sheet the charts came from. If you leave it out, the name of the uploaded file is stored. |
charts | array | Yes | At least one chart. |
Other keys in the file, such as a note about where the sheet came from, are ignored.
Charts
| Field | Type | Required | Notes |
|---|---|---|---|
code | string | Yes | Your identifier for the spec. Unique within the file. Importing the same code again replaces the chart (see Re-importing). |
name | string | Yes | A readable name shown in the app. |
department | string | Yes | Your target group, for example boys or women. Free text. Brandmachine suggests charts within one department only. |
garment_type | string | Yes | Your own word for the garment, for example tee-short-sleeve or trouser. Free text, not a fixed list. |
product_group | string | No | A broader grouping such as tops or bottoms. Free text. |
sizes | array of strings | Yes | The size labels in grading order, smallest to largest. No duplicates. |
base_size | string | Yes | The size the base values belong to. Must be one of sizes. |
pattern_group | string or null | No | Give charts that are readouts of one pattern (for example one tee finished with two trim widths) the same value. Use null when the chart has no siblings. An empty string is rejected. |
rows | array | Yes | At least one row. |
Rows
A row is one measurement across all sizes.
| Field | Type | Required | Notes |
|---|---|---|---|
code | string | Yes | A code from Measurement Codes. |
origin | string or null | No | Where the measurement is taken from, from the list in Origins. |
source_label | string | Yes | The row's name in your sheet, for example 1/2 Chest. Kept as written. |
convention | string | Yes | half if the value is half of the full girth (a flat-laid chest, for example), otherwise full. Lower case. Brandmachine does not check this against the measurement. |
base_hundredths | integer or null | No | The value at the base size. null makes an increment row that has grade steps only. |
grade_deltas_hundredths | object | Yes | The difference to the base value, one entry per size, keyed by size label. The entry for the base size must be 0. |
tolerance | object or null | No | See below. Leave it out when your sheet gives none. |
position | integer | No | Display order. Defaults to the row's place in the array. Unique within the chart. |
Row identity. A row is addressed by its code together with its origin, written CODE@origin, for example SLEEVE_LENGTH@CB. The same code with a different origin is a different measurement, and two rows in one chart cannot share a code and origin. If a design has two constructions of the same garment, put them in separate charts that share a pattern_group.
Increment rows. A row with base_hundredths: null is allowed. The chart then counts as incomplete: that row shows no values and cannot be adjusted in the app.
Tolerance.
| Field | Type | Notes |
|---|---|---|
minus_hundredths | integer | Zero or negative. |
plus_hundredths | integer | Zero or positive. |
raw | string | The tolerance as it appears in your sheet. Kept for reference. |
parse_failed | boolean | Optional. If you set it to true, both bounds must be null. |
Send both bounds or neither. A tolerance with no bounds and no raw text is rejected.
Units
Every number is an integer in hundredths of a centimetre. There is no inch input. If your sheet uses inches, convert to centimetres first. Round to two decimals of a centimetre before scaling, so 63.204 cm becomes 63.20 and then 6320. Brandmachine cannot detect a wrong rounding order, so the converter has to get this right.
Measurement Codes
Measurement names are a closed list, because rows have to be comparable between charts. Free-text names are exactly what makes two customers' charts impossible to line up. Map your own spellings to these codes in your converter. A code that is not on the list rejects the whole file, and the error names the code it did not recognise and suggests up to three close ones (Unknown POM code X (normalised: Y). Did you mean A, B, C?).
ARMHOLE_DEPTH, ARMHOLE_HALF, ARMHOLE_LEN_BACK, ARMHOLE_LEN_FRONT, ARMHOLE_RAGLAN_BACK, ARMHOLE_RAGLAN_FRONT, ARMHOLE_STRAIGHT, ARTWORK_HEIGHT, ARTWORK_POS_ARMHOLE, ARTWORK_POS_CB, ARTWORK_POS_CF, ARTWORK_POS_HSP, ARTWORK_POS_RIB, ARTWORK_POS_SS, ARTWORK_WIDTH, BACK_LENGTH, BACK_NECK_DROP, BACK_POCKET_HEIGHT, BACK_POCKET_POS_CB, BACK_POCKET_POS_WB, BACK_POCKET_WIDTH, BACK_RISE, BACK_WELT_POCKET_HEIGHT, BACK_YOKE, BICEP, BOTTOM_CUFF_HEIGHT, BOTTOM_WIDTH, BOTTOM_WIDTH_RELAXED, BOTTOM_WIDTH_STRETCHED, BUTTON_1_FROM_BOTTOM, BUTTON_1_FROM_TOP, BUTTON_SPACING, CHEST, COLLAR_HEIGHT, COLLAR_LENGTH, COLLAR_POINT, COLLAR_STAND, CORD_LENGTH, CUFF_HEIGHT, ELBOW, ELBOW_POSITION, FIRST_BUTTON, FLAP_HEIGHT, FLAP_LENGTH, FLY_LENGTH, FLY_WIDTH, FRONT_NECK_DROP, FRONT_POCKET_INSERT_LEN, FRONT_POCKET_INSERT_WB, FRONT_POCKET_LEN_INSIDE, FRONT_POCKET_LEN_SS, FRONT_POCKET_LEN_WB, FRONT_POCKET_WIDTH_SS, FRONT_POCKET_WIDTH_WB, FRONT_RISE, HIP, HIP_POSITION, HOOD_HEIGHT, HOOD_WIDTH, INSEAM, KNEE, KNEE_POSITION, LEG_OPENING, LEG_OPENING_RELAXED, LEG_OPENING_STRETCHED, LOWER_ARM, MIN_NECK_STRETCH, NECK_RIB_HEIGHT, NECK_WIDTH, OUTSEAM, PLACKET_LENGTH, PLACKET_WIDTH, POCKET_HEIGHT_CENTRE, POCKET_LENGTH, POCKET_POS_CF, POCKET_POS_HSP, POCKET_POS_SS_BOTTOM, POCKET_POS_SS_TOP, POCKET_WIDTH, POCKET_WIDTH_BOTTOM, POCKET_WIDTH_MIDDLE, POCKET_WIDTH_TOP, SHOULDER, SHOULDER_FORWARD, SIDE_POCKET_LENGTH, SIDE_POCKET_POS, SIDE_POCKET_WIDTH, SLEEVE_LENGTH, SLEEVE_LENGTH_INCL_CUFF, SLEEVE_OPENING, SLEEVE_OPENING_RELAXED, SLEEVE_OPENING_STRETCHED, SLIT_LENGTH, THIGH, TRIM_WIDTH, WAIST, WAISTBAND_HEIGHT, WAIST_HEIGHT, WAIST_RELAXED, WAIST_STRETCHED
New measurements are added when a customer's sheet needs one. If you need a code that is missing, contact support@brandmachine.shop.
Origins
origin says where a measurement is taken from. It is not interchangeable: a sleeve length from centre back includes half the shoulder, one from the shoulder point does not. Leave it null when the measurement has no such reference. The allowed values are case-sensitive:
CB, CF, HSP, armhole, armpit, bottom, crotch, cuff, neckline seam, ribbing seam, seam to seam, shoulder point, side seam, waistband
Validation
The import is all or nothing. If anything in the file produces an error, nothing is saved, including the charts that were fine. A file that is not valid JSON, or does not fit the format, comes back as one error: The file is not in the size chart upload format: followed by the reason.
Errors you may see, in the message of an entry in errors:
| Message | Fix |
|---|---|
Unsupported format_version N; this backend reads version 1. | Set format_version to 1. |
The file contains no charts. | Add at least one chart. |
Chart code appears more than once in this file. | Give each chart its own code. |
code is empty., name is empty., department is empty., garment_type is empty. | Fill the field. |
sizes is empty., sizes contains a size more than once. | List each size once. |
base_size X is not one of sizes [...]. | Use a label that appears in sizes. |
The chart has no rows. | Add rows. |
pattern_group is empty; leave it null when the chart has no siblings. | Use null instead of an empty string. |
Two rows share position N. Every row needs its own position. | Make positions unique, or leave them out. |
Unknown POM code X ... Did you mean ...? | Use a code from the list. |
Unknown origin X. Allowed: ... | Use one of the origins, spelled exactly. |
Two rows share the key K. ... | Split the constructions into separate charts with the same pattern_group. |
source_label is empty. | Fill the field. |
convention must be half or full, got X. | Use half or full, lower case. |
grade_deltas_hundredths must have exactly one entry per size in [...]. | Give one step per size, keyed by label. |
grade_deltas_hundredths must be 0 at the base size X. | Set the base size's step to 0. |
tolerance bounds have the wrong sign: minus must be ≤ 0 and plus ≥ 0. | Check the signs. |
tolerance bounds must be both set or both null. | Send both bounds or neither. |
tolerance is marked parse_failed but has bounds; an unreadable tolerance must have null bounds. | Remove the bounds or the flag. |
tolerance has neither bounds nor raw text; leave tolerance out when the source gives none. | Remove the empty tolerance. |
Warnings do not stop the import. They point at values that look like typos:
kind | When |
|---|---|
UNREADABLE_TOLERANCE | A tolerance has raw text but no bounds. It is stored as text and never used as a limit. |
IMPLAUSIBLE_TOLERANCE | A tolerance bound is wider than 1.00 cm and more than 10% of the base value. |
GRADING_REVERSES_DIRECTION | The values get smaller where they should get larger (or the other way round) between two sizes. The warning lists the values and the size where it turns. |
Re-importing
The chart code is the key. When you import a code that is already in your library, the new chart replaces it: the old one is marked as superseded and stays on the designs that were already made from it, and new designs use the new one. Charts that are not in the file are left alone, so you can send only the charts that changed.
The report shows SUPERSEDE for these charts, so a dry run tells you what will be replaced before anything changes.
What Happens After the Import
Imported charts are your library of standard specs. They are not matched to Shopify products by size label.
In the Designer, you pick a department for a design, and Brandmachine shortlists up to three candidates from that department based on the design description (charts that share a pattern_group count as one candidate). You choose one, and the design gets its own copy of the rows. You can then adjust values on that copy, and the Designer draws the base-size measurements onto the technical drawings. Your uploaded charts stay untouched, because they are your standard specs.
The chart operations are in the GraphQL reference: sizeCharts and sizeChart to read, matchSizeChart, createDesignerSizeChart, setSizeChartAdjustments and annotateSizeChart on a design, and deleteSizeChart.
Checklist for Your Converter
- Output centimetres as integers in hundredths, rounded to two decimals first.
- Map every measurement name to a code from the list, and keep the original name in
source_label. - Set
conventiontohalffor flat-laid girths. - Include
grade_deltas_hundredthsfor every size, with0at the base size. - Keep the same
codefor a chart across imports so it supersedes the old one. - Build each
codefrom what makes the chart different (for example the trim width), never from its position in the sheet. Otherwise a reordered sheet swaps the data between sibling charts. - Run with
?dryRun=truein your pipeline and fail on a non-emptyerrorsarray.