Naar de inhoud
Open Nexym

Create or update a product

POST
/api/connect/products
curl --request POST \
--url https://app.nexym.nl/api/connect/products \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "reference": "ACME-1234", "name": "Widget 40 mm, black", "sku": "ACME-1234", "status": "active", "is_online": true }'

Upserts a product by reference within the key’s project. An existing record is matched on (project_id, reference); only the fields present in the payload are written, and any key not listed in the request schema is ignored rather than rejected.

Requires products: write.

Media typeapplication/json

The write payload for a product. Only these five keys are read; anything else in the body is ignored.

object
reference
required

Matched against an existing product in this project.

string
name
required
string
sku
string | null
status
string | null
Allowed values: active inactive draft
is_online
boolean | null

An existing product was updated.

Media typeapplication/json

A universal article record.

object
id
integer
project_id
integer
reference

The canonical article key, unique within the project.

string
sku
string | null
name
string
type
string
Allowed values: simple configurable bundle grouped
parent_reference

The configurable, bundle or grouped parent this article belongs to.

string | null
attribute_set
string | null
description
string | null
short_description
string | null
url
string | null
meta_title
string | null
meta_description
string | null
labels

Per-store content overrides, keyed by store slot and then by field name — the value used when a record is pushed to that store instead of the hub’s own column.

object | null
pushed_store_labels

What was last pushed per store, so a re-run does not resend it.

object | null
brand
string | null
brand_name
string | null
category_reference
string | null
supplier_reference
string | null
vat_rate

Percentage, two decimals, serialised as a string.

string | null
is_online

Null means no connected system has said either way yet.

boolean | null
status
string
Allowed values: active inactive draft
source_connection_id

The connection this record was last imported from.

integer | null
meta

Free-form store for fields the universal schema does not define for everybody: a connector’s declared extension fields and a project’s own customer fields, each under its own name.

object | null
source_changed_at
string | null format: date-time
created_at
string | null format: date-time
updated_at
string | null format: date-time
variants
Array<object>

A variant as the products listing returns it. Only these columns are selected — the full variant record (barcodes, options, weight, labels, meta) is not exposed by this API.

object
id
integer
product_id
integer
reference
string
sku
string | null
barcode
string | null
related_skus

Related products, in the source’s order. The hub product’s SKU when that product is in the hub, otherwise the SKU the source gave.

Array<string>
upsell_skus

Up-sells, in the source’s order, as SKUs (see related_skus).

Array<string>
crosssell_skus

Cross-sells, in the source’s order, as SKUs (see related_skus).

Array<string>

Example

{
"id": 4821,
"project_id": 3,
"reference": "ACME-1234",
"sku": "ACME-1234",
"name": "Widget 40 mm, black",
"type": "simple",
"parent_reference": null,
"attribute_set": "default",
"description": "A 40 mm widget in powder-coated black.",
"short_description": "40 mm widget, black",
"url": "/widgets/acme-1234",
"meta_title": "Widget 40 mm, black",
"meta_description": "Buy the 40 mm black widget.",
"labels": {
"nl_main": {
"name": "Widget 40 mm, zwart"
}
},
"pushed_store_labels": {
"nl_main": {
"name": "Widget 40 mm, zwart"
}
},
"brand": "ACME",
"brand_name": "ACME Tools",
"category_reference": "CAT-WIDGETS",
"supplier_reference": "SUP-0042",
"vat_rate": "21.00",
"is_online": true,
"status": "active",
"source_connection_id": 7,
"meta": {
"service_code": "INSTALL-STD"
},
"source_changed_at": "2026-09-18T09:12:41.000000Z",
"created_at": "2026-08-01T11:03:27.000000Z",
"updated_at": "2026-09-18T09:12:41.000000Z",
"variants": [
{
"id": 90412,
"product_id": 4821,
"reference": "ACME-1234-BLK",
"sku": "ACME-1234-BLK",
"barcode": "8712345678906"
}
],
"related_skus": [
"ACME-2000",
"ACME-2001"
],
"upsell_skus": [
"ACME-1234-PRO"
],
"crosssell_skus": []
}

A new product was created.

Media typeapplication/json

A universal article record.

object
id
integer
project_id
integer
reference

The canonical article key, unique within the project.

string
sku
string | null
name
string
type
string
Allowed values: simple configurable bundle grouped
parent_reference

The configurable, bundle or grouped parent this article belongs to.

string | null
attribute_set
string | null
description
string | null
short_description
string | null
url
string | null
meta_title
string | null
meta_description
string | null
labels

Per-store content overrides, keyed by store slot and then by field name — the value used when a record is pushed to that store instead of the hub’s own column.

object | null
pushed_store_labels

What was last pushed per store, so a re-run does not resend it.

object | null
brand
string | null
brand_name
string | null
category_reference
string | null
supplier_reference
string | null
vat_rate

Percentage, two decimals, serialised as a string.

string | null
is_online

Null means no connected system has said either way yet.

boolean | null
status
string
Allowed values: active inactive draft
source_connection_id

The connection this record was last imported from.

integer | null
meta

Free-form store for fields the universal schema does not define for everybody: a connector’s declared extension fields and a project’s own customer fields, each under its own name.

object | null
source_changed_at
string | null format: date-time
created_at
string | null format: date-time
updated_at
string | null format: date-time
variants
Array<object>

A variant as the products listing returns it. Only these columns are selected — the full variant record (barcodes, options, weight, labels, meta) is not exposed by this API.

object
id
integer
product_id
integer
reference
string
sku
string | null
barcode
string | null
related_skus

Related products, in the source’s order. The hub product’s SKU when that product is in the hub, otherwise the SKU the source gave.

Array<string>
upsell_skus

Up-sells, in the source’s order, as SKUs (see related_skus).

Array<string>
crosssell_skus

Cross-sells, in the source’s order, as SKUs (see related_skus).

Array<string>

Example

{
"id": 4821,
"project_id": 3,
"reference": "ACME-1234",
"sku": "ACME-1234",
"name": "Widget 40 mm, black",
"type": "simple",
"parent_reference": null,
"attribute_set": "default",
"description": "A 40 mm widget in powder-coated black.",
"short_description": "40 mm widget, black",
"url": "/widgets/acme-1234",
"meta_title": "Widget 40 mm, black",
"meta_description": "Buy the 40 mm black widget.",
"labels": {
"nl_main": {
"name": "Widget 40 mm, zwart"
}
},
"pushed_store_labels": {
"nl_main": {
"name": "Widget 40 mm, zwart"
}
},
"brand": "ACME",
"brand_name": "ACME Tools",
"category_reference": "CAT-WIDGETS",
"supplier_reference": "SUP-0042",
"vat_rate": "21.00",
"is_online": true,
"status": "active",
"source_connection_id": 7,
"meta": {
"service_code": "INSTALL-STD"
},
"source_changed_at": "2026-09-18T09:12:41.000000Z",
"created_at": "2026-08-01T11:03:27.000000Z",
"updated_at": "2026-09-18T09:12:41.000000Z",
"variants": [
{
"id": 90412,
"product_id": 4821,
"reference": "ACME-1234-BLK",
"sku": "ACME-1234-BLK",
"barcode": "8712345678906"
}
],
"related_skus": [
"ACME-2000",
"ACME-2001"
],
"upsell_skus": [
"ACME-1234-PRO"
],
"crosssell_skus": []
}

No key, a key that does not match, a revoked key, or an expired one. The body says which, and nothing else — an unusable key is never described further.

Media typeapplication/json

Every error this API returns carries a single human-readable message.

object
message
required
string

Examples

No bearer token, or one too short to hold a prefix

{
"message": "Missing or invalid API key."
}

The key is valid but its abilities do not cover this resource at this right.

Media typeapplication/json

Every error this API returns carries a single human-readable message.

object
message
required
string

Examples

{
"message": "This API key lacks read access to orders."
}

The payload failed validation. The framework’s standard shape: a summary message plus an errors map of field to messages. Requires Accept: application/json — without it the response is a 302 redirect instead.

Media typeapplication/json
object
message
required
string
errors
required

Field name to the list of messages that field failed on.

object
key
additional properties
Array<string>

Examples

Exampleproduct
{
"message": "The reference field is required. (and 1 more error)",
"errors": {
"reference": [
"The reference field is required."
],
"name": [
"The name field is required."
]
}
}

The per-minute rate limit was exceeded. The limit is 120 requests per minute by default (CONNECT_API_RATE_PER_MIN), counted per API key — or per IP address for a request that never authenticated.

Media typeapplication/json

Every error this API returns carries a single human-readable message.

object
message
required
string

Examples

Examplelimited
{
"message": "Too many requests — slow down."
}
Retry-After
integer

Seconds until the limit resets.

X-RateLimit-Limit
integer

Requests allowed per minute.

X-RateLimit-Remaining
integer

Requests left in the current window.