curl --request POST \
--url https://app.polygon-one.com/api/ppwr/units \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
[
{
"name": "<string>",
"notes": "<string>",
"internalRef": "<string>",
"supplierName": "<string>",
"format": "<string>",
"gtin": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123,
"sizeReference": "<string>",
"sizeLabel": "<string>",
"marketMemberStates": [
"<string>"
],
"placedUnderOwnBrand": true,
"modifiesConformity": true,
"reusable": true,
"articleNumbers": [
"<string>"
],
"componentCodes": [
"<string>"
],
"sizes": [
{
"reference": "<string>",
"gtin": "<string>",
"label": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123
}
]
}
]
'import requests
url = "https://app.polygon-one.com/api/ppwr/units"
payload = [
{
"name": "<string>",
"notes": "<string>",
"internalRef": "<string>",
"supplierName": "<string>",
"format": "<string>",
"gtin": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123,
"sizeReference": "<string>",
"sizeLabel": "<string>",
"marketMemberStates": ["<string>"],
"placedUnderOwnBrand": True,
"modifiesConformity": True,
"reusable": True,
"articleNumbers": ["<string>"],
"componentCodes": ["<string>"],
"sizes": [
{
"reference": "<string>",
"gtin": "<string>",
"label": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123
}
]
}
]
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify([
{
name: '<string>',
notes: '<string>',
internalRef: '<string>',
supplierName: '<string>',
format: '<string>',
gtin: '<string>',
widthMm: 123,
heightMm: 123,
depthMm: 123,
sizeReference: '<string>',
sizeLabel: '<string>',
marketMemberStates: ['<string>'],
placedUnderOwnBrand: true,
modifiesConformity: true,
reusable: true,
articleNumbers: ['<string>'],
componentCodes: ['<string>'],
sizes: [
{
reference: '<string>',
gtin: '<string>',
label: '<string>',
widthMm: 123,
heightMm: 123,
depthMm: 123
}
]
}
])
};
fetch('https://app.polygon-one.com/api/ppwr/units', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.polygon-one.com/api/ppwr/units",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
[
'name' => '<string>',
'notes' => '<string>',
'internalRef' => '<string>',
'supplierName' => '<string>',
'format' => '<string>',
'gtin' => '<string>',
'widthMm' => 123,
'heightMm' => 123,
'depthMm' => 123,
'sizeReference' => '<string>',
'sizeLabel' => '<string>',
'marketMemberStates' => [
'<string>'
],
'placedUnderOwnBrand' => true,
'modifiesConformity' => true,
'reusable' => true,
'articleNumbers' => [
'<string>'
],
'componentCodes' => [
'<string>'
],
'sizes' => [
[
'reference' => '<string>',
'gtin' => '<string>',
'label' => '<string>',
'widthMm' => 123,
'heightMm' => 123,
'depthMm' => 123
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.polygon-one.com/api/ppwr/units"
payload := strings.NewReader("[\n {\n \"name\": \"<string>\",\n \"notes\": \"<string>\",\n \"internalRef\": \"<string>\",\n \"supplierName\": \"<string>\",\n \"format\": \"<string>\",\n \"gtin\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123,\n \"sizeReference\": \"<string>\",\n \"sizeLabel\": \"<string>\",\n \"marketMemberStates\": [\n \"<string>\"\n ],\n \"placedUnderOwnBrand\": true,\n \"modifiesConformity\": true,\n \"reusable\": true,\n \"articleNumbers\": [\n \"<string>\"\n ],\n \"componentCodes\": [\n \"<string>\"\n ],\n \"sizes\": [\n {\n \"reference\": \"<string>\",\n \"gtin\": \"<string>\",\n \"label\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123\n }\n ]\n }\n]")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.polygon-one.com/api/ppwr/units")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("[\n {\n \"name\": \"<string>\",\n \"notes\": \"<string>\",\n \"internalRef\": \"<string>\",\n \"supplierName\": \"<string>\",\n \"format\": \"<string>\",\n \"gtin\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123,\n \"sizeReference\": \"<string>\",\n \"sizeLabel\": \"<string>\",\n \"marketMemberStates\": [\n \"<string>\"\n ],\n \"placedUnderOwnBrand\": true,\n \"modifiesConformity\": true,\n \"reusable\": true,\n \"articleNumbers\": [\n \"<string>\"\n ],\n \"componentCodes\": [\n \"<string>\"\n ],\n \"sizes\": [\n {\n \"reference\": \"<string>\",\n \"gtin\": \"<string>\",\n \"label\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123\n }\n ]\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.polygon-one.com/api/ppwr/units")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "[\n {\n \"name\": \"<string>\",\n \"notes\": \"<string>\",\n \"internalRef\": \"<string>\",\n \"supplierName\": \"<string>\",\n \"format\": \"<string>\",\n \"gtin\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123,\n \"sizeReference\": \"<string>\",\n \"sizeLabel\": \"<string>\",\n \"marketMemberStates\": [\n \"<string>\"\n ],\n \"placedUnderOwnBrand\": true,\n \"modifiesConformity\": true,\n \"reusable\": true,\n \"articleNumbers\": [\n \"<string>\"\n ],\n \"componentCodes\": [\n \"<string>\"\n ],\n \"sizes\": [\n {\n \"reference\": \"<string>\",\n \"gtin\": \"<string>\",\n \"label\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123\n }\n ]\n }\n]"
response = http.request(request)
puts response.read_body{
"imported": 123,
"updated": [
"<string>"
],
"skipped": [
"<string>"
],
"failed": [
{
"identifier": "<string>",
"error": "<string>"
}
],
"invalid": [
{
"index": 123,
"identifier": "<string>",
"error": "<string>"
}
],
"sizesCreated": 123,
"articleNumbersUnmatched": 123,
"articleLinksCreated": 123,
"componentLinksCreated": 123,
"componentStubsCreated": 123
}{
"error": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"details": "<unknown>"
}{
"error": "overwriteRequired",
"confirmUpdateCount": 123
}{
"error": "<string>",
"details": "<unknown>"
}Verpackungseinheiten anlegen & aktualisieren
Bulk upsert of packaging units, keyed on internalRef. A row may carry its additional sizes (sizes[]) and the additive articleNumbers / componentCodes directives in the same call. A row without internalRef is always a create — the server assigns the next PU-<n>, and there is currently no read endpoint for those generated references: read them back from the Packaging units list or its export before importing links or article links. Same fill-only column policy and overwrite gate as the component intake. At most 1000 rows per request (400 otherwise). A request may additionally carry at most 1000 sizes entries across all its rows. Requires packaging:write; customer workspace with the PPWR module enabled — see the guide.
curl --request POST \
--url https://app.polygon-one.com/api/ppwr/units \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
[
{
"name": "<string>",
"notes": "<string>",
"internalRef": "<string>",
"supplierName": "<string>",
"format": "<string>",
"gtin": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123,
"sizeReference": "<string>",
"sizeLabel": "<string>",
"marketMemberStates": [
"<string>"
],
"placedUnderOwnBrand": true,
"modifiesConformity": true,
"reusable": true,
"articleNumbers": [
"<string>"
],
"componentCodes": [
"<string>"
],
"sizes": [
{
"reference": "<string>",
"gtin": "<string>",
"label": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123
}
]
}
]
'import requests
url = "https://app.polygon-one.com/api/ppwr/units"
payload = [
{
"name": "<string>",
"notes": "<string>",
"internalRef": "<string>",
"supplierName": "<string>",
"format": "<string>",
"gtin": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123,
"sizeReference": "<string>",
"sizeLabel": "<string>",
"marketMemberStates": ["<string>"],
"placedUnderOwnBrand": True,
"modifiesConformity": True,
"reusable": True,
"articleNumbers": ["<string>"],
"componentCodes": ["<string>"],
"sizes": [
{
"reference": "<string>",
"gtin": "<string>",
"label": "<string>",
"widthMm": 123,
"heightMm": 123,
"depthMm": 123
}
]
}
]
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify([
{
name: '<string>',
notes: '<string>',
internalRef: '<string>',
supplierName: '<string>',
format: '<string>',
gtin: '<string>',
widthMm: 123,
heightMm: 123,
depthMm: 123,
sizeReference: '<string>',
sizeLabel: '<string>',
marketMemberStates: ['<string>'],
placedUnderOwnBrand: true,
modifiesConformity: true,
reusable: true,
articleNumbers: ['<string>'],
componentCodes: ['<string>'],
sizes: [
{
reference: '<string>',
gtin: '<string>',
label: '<string>',
widthMm: 123,
heightMm: 123,
depthMm: 123
}
]
}
])
};
fetch('https://app.polygon-one.com/api/ppwr/units', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.polygon-one.com/api/ppwr/units",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
[
'name' => '<string>',
'notes' => '<string>',
'internalRef' => '<string>',
'supplierName' => '<string>',
'format' => '<string>',
'gtin' => '<string>',
'widthMm' => 123,
'heightMm' => 123,
'depthMm' => 123,
'sizeReference' => '<string>',
'sizeLabel' => '<string>',
'marketMemberStates' => [
'<string>'
],
'placedUnderOwnBrand' => true,
'modifiesConformity' => true,
'reusable' => true,
'articleNumbers' => [
'<string>'
],
'componentCodes' => [
'<string>'
],
'sizes' => [
[
'reference' => '<string>',
'gtin' => '<string>',
'label' => '<string>',
'widthMm' => 123,
'heightMm' => 123,
'depthMm' => 123
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.polygon-one.com/api/ppwr/units"
payload := strings.NewReader("[\n {\n \"name\": \"<string>\",\n \"notes\": \"<string>\",\n \"internalRef\": \"<string>\",\n \"supplierName\": \"<string>\",\n \"format\": \"<string>\",\n \"gtin\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123,\n \"sizeReference\": \"<string>\",\n \"sizeLabel\": \"<string>\",\n \"marketMemberStates\": [\n \"<string>\"\n ],\n \"placedUnderOwnBrand\": true,\n \"modifiesConformity\": true,\n \"reusable\": true,\n \"articleNumbers\": [\n \"<string>\"\n ],\n \"componentCodes\": [\n \"<string>\"\n ],\n \"sizes\": [\n {\n \"reference\": \"<string>\",\n \"gtin\": \"<string>\",\n \"label\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123\n }\n ]\n }\n]")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.polygon-one.com/api/ppwr/units")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("[\n {\n \"name\": \"<string>\",\n \"notes\": \"<string>\",\n \"internalRef\": \"<string>\",\n \"supplierName\": \"<string>\",\n \"format\": \"<string>\",\n \"gtin\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123,\n \"sizeReference\": \"<string>\",\n \"sizeLabel\": \"<string>\",\n \"marketMemberStates\": [\n \"<string>\"\n ],\n \"placedUnderOwnBrand\": true,\n \"modifiesConformity\": true,\n \"reusable\": true,\n \"articleNumbers\": [\n \"<string>\"\n ],\n \"componentCodes\": [\n \"<string>\"\n ],\n \"sizes\": [\n {\n \"reference\": \"<string>\",\n \"gtin\": \"<string>\",\n \"label\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123\n }\n ]\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.polygon-one.com/api/ppwr/units")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "[\n {\n \"name\": \"<string>\",\n \"notes\": \"<string>\",\n \"internalRef\": \"<string>\",\n \"supplierName\": \"<string>\",\n \"format\": \"<string>\",\n \"gtin\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123,\n \"sizeReference\": \"<string>\",\n \"sizeLabel\": \"<string>\",\n \"marketMemberStates\": [\n \"<string>\"\n ],\n \"placedUnderOwnBrand\": true,\n \"modifiesConformity\": true,\n \"reusable\": true,\n \"articleNumbers\": [\n \"<string>\"\n ],\n \"componentCodes\": [\n \"<string>\"\n ],\n \"sizes\": [\n {\n \"reference\": \"<string>\",\n \"gtin\": \"<string>\",\n \"label\": \"<string>\",\n \"widthMm\": 123,\n \"heightMm\": 123,\n \"depthMm\": 123\n }\n ]\n }\n]"
response = http.request(request)
puts response.read_body{
"imported": 123,
"updated": [
"<string>"
],
"skipped": [
"<string>"
],
"failed": [
{
"identifier": "<string>",
"error": "<string>"
}
],
"invalid": [
{
"index": 123,
"identifier": "<string>",
"error": "<string>"
}
],
"sizesCreated": 123,
"articleNumbersUnmatched": 123,
"articleLinksCreated": 123,
"componentLinksCreated": 123,
"componentStubsCreated": 123
}{
"error": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"details": "<unknown>"
}{
"error": "<string>",
"details": "<unknown>"
}{
"error": "overwriteRequired",
"confirmUpdateCount": 123
}{
"error": "<string>",
"details": "<unknown>"
}Autorisierungen
API key generated in Settings > API Keys. Include as Authorization: Bearer <key>.
Body
- object[]
- object
One packaging-unit row for POST /api/ppwr/units. Upsert key: internalRef. A row without internalRef can match nothing and is therefore ALWAYS a create — the server names the unit with the next generated PU-<n>; replaying such a row creates another unit. Cells are coerced exactly as the in-app CSV/Excel importer coerces them, so a JSON-native value and its string spelling are equivalent (12 = "12", ["plastic"] = "plastic;paper_board", true = "yes"/"ja"/"1"). An empty or omitted field is a no-op — it never clears a stored value.
Name of the packaging unit.
sales, grouped, transport, ecommerce, service manufacturer, importer, distributor, authorised_representative, supplier, fulfilment_service_provider Required — description and intended use of the packaging. A row without it fails as descriptionRequired, including fill-only updates.
1Your reference for the unit — the upsert key, unique within your company. Omit it only for rows you never intend to replay (see the schema description).
120Resolved to one of your suppliers by fuzzy name match (case, umlauts, punctuation and legal-form tokens are ignored). A name that matches two or more distinct suppliers fails the row with ambiguousSupplierName — the import never guesses. A name that matches none (and a blank cell) resolves to no supplier: the record lands in your own bucket without a row error, and the supplier is never auto-created.
Packaging form (free text).
A supplied grade is stored as supplier-declared.
A, B, C, non_recyclable, null GTIN of the unit's PRIMARY size.
^(\d{8}|\d{12}|\d{13}|\d{14})$Width of the primary size, in mm.
Height of the primary size, in mm.
Depth of the primary size, in mm.
The flat spelling of a size: several rows sharing one internalRef, each with its own sizeReference, fold into ONE unit with N sizes. Blank (or equal to internalRef) marks the UNIT row. Prefer sizes[].
120Human name of the size. Only a SIZE row may carry it — on a unit row it fails as conflictingSizeRow.
120ISO alpha-2 codes (case-insensitive, stored upper-case). A blank column imports as an empty list and is NOT back-filled from your PPWR default.
^[A-Za-z]{2}$Blank = false; on an update a blank/absent value leaves the stored value unchanged.
Blank = false; on an update a blank/absent value leaves the stored value unchanged.
Art. 11 reusable packaging. Blank = false; on an update a blank/absent value leaves the stored value unchanged.
Links the unit to existing articles by internal article number. On a SIZE row the link is to that size. An unmatched number is skipped silently (counted in articleNumbersUnmatched), never created and never a row error — unlike POST /api/ppwr/article-links, which errors.
Builds the bill of materials with quantity 1. An unknown code auto-creates a minimal stub component (other, name = code, counted in componentStubsCreated). A code naming two or more live components fails the whole row with ambiguousComponentMatch — the cell has no supplier column to disambiguate with, and the oldest match is never picked. POST /api/ppwr/links reports the same key, so it is not an escape hatch: make the code unique instead.
The unit's ADDITIONAL sizes — the primary way to send sizes. On a CREATE the row is one transaction: a refused size (duplicateFormatReference, formatCapReached) rolls the unit back too. On a row matching an EXISTING unit each size is upserted on its own; sizes the payload omits are never deleted.
49Show child attributes
Show child attributes
Antwort
Intake result (partial accept — see the schema).
Result of a synchronous PPWR intake. Partial accept: valid rows commit even when other rows are invalid or failed — the one exception is the 409 overwrite gate, which is all-or-nothing. Idempotent: replaying an identical request changes nothing (matched rows return as skipped), except unit rows without internalRef, which are always creates.
ENTITIES created (units, components, links) — never sizes.
Identifiers of rows whose existing match changed. A size created on an existing unit appears as <unit ref> / <size ref>.
Identifiers of rows that matched with nothing to change.
Rows the upsert engine rejected (unknown reference, ambiguous match, …). Its error values are stable machine keys.
Show child attributes
Show child attributes
Rows rejected by schema validation before the engine ran. Most error values are stable machine keys, but a field with no custom message falls back to the validator's own English text — match on the key, fall back to displaying the string.
Show child attributes
Show child attributes
Unit intake only: sizes created for the rows' units.
Unit intake only: distinct articleNumbers no live article matched. Skipped, never a row error.
Unit intake only: unit⇄article links created from articleNumbers.
Unit intake only: unit⇄component links created from componentCodes.
Unit intake only: minimal placeholder components created for unknown componentCodes.