References

Overview

References are the buyer's article master data: the list of articles the buyer purchases, with their category, packaging options and commercial attributes. Suppliers' products are then matched to these references.

This endpoint enables buyers to:

  • Push article master data from an ERP or PIM into a buyer workspace
  • Keep it in sync with incremental, idempotent updates
  • Describe each packaging option (logistics unit) of an article: box type, box weight, pieces per box, boxes per pallet
  • Deactivate articles that are no longer purchased, without losing their history

Endpoints

Method Endpoint Description
POST /v2/partner/{workspaceID}/references Create or update references in bulk
DELETE /v2/partner/{workspaceID}/references Soft-delete references in bulk, by code

Authentication

References use a workspace API token issued by Consentio during onboarding, with the references:write permission. Send it directly on every request; no /login call is needed:

Authorization: Bearer ctio_ws_xxxxxxxxxxxxx

A token without the references:write permission, or used on a different workspace, gets 403 Forbidden. Contact your integration manager to obtain or rotate the token.

Data Model

One reference, several logistics units

On the wire, you send one object per article, and list all its packaging options in logistics_units[].

In Consentio, each logistics unit becomes its own reference, identified by the composite code <code>-<logistics unit code>. For example, article 00027598 with logistics units 01 and 03 creates two references, 00027598-01 and 00027598-03. This composite code is the identifier you use later to delete a reference.

An article sent without any logistics_units creates or changes nothing.

Idempotency

The composite code <code>-<logistics unit code> is the idempotency key:

  • A composite code seen for the first time creates a reference
  • A composite code that already exists updates that reference
  • Logistics units you do not send are left unchanged

Retrying the same request is safe and does not create duplicates.

Fields

Field Type Required Description
code string Yes Your identifier for the article. Combined with each logistics unit code into the composite code (max 256 characters in total).
name string(256) Yes Article name. See Stored name.
product_kinds array Yes Category hierarchy, root to leaf. At least one entry. See below.
attributes array Yes Must contain at least price_unit. See below.
logistics_units array No Packaging options. Each one becomes a reference. Without it, nothing is created or changed. See below.
status enum No active or inactive. See Status.
organic boolean No Organic-certified article. Defaults to false.
description string No Free text.
deleted_at datetime No RFC 3339 timestamp. Soft-delete signal. See Soft delete.
metadata object No Any key-value pairs for your own traceability. Stored as-is, not interpreted by Consentio.
group_code string No Accepted and ignored.

product_kinds[]

The article's category hierarchy as an ordered array, always root to leaf. Each entry is { "code": "<code>", "name": "<label>" }, and both values must be non-empty.

  • The position in the array is the hierarchy level, so always send the same number of levels in the same order.
  • Each category is identified by its code and its parent. Unknown categories are created automatically with the name you send, and if a known category arrives with a different name, the name is updated.
  • The reference is linked to the last entry (the leaf).

Example of a 4-level hierarchy:

"product_kinds": [
  { "code": "46", "name": "LEGUMES FRAIS TRAD" },
  { "code": "795", "name": "CONCOMBRE" },
  { "code": "60", "name": "VERT" },
  { "code": "00004593", "name": "CONCOMBRE PIECE" }
]

attributes[]

Each item is { "attribute": "<key>", "value": <string or number> }. Numeric values may be sent as a string ("5.5") or a number (5.5).

Key Value Required Description
price_unit enum Yes Unit the article is priced in: kg, box, piece or pallet.
sale_unit enum No Unit the article is sold in: kg, box, piece or pallet. Defaults to box.
vat_rate number No VAT rate, e.g. 5.5.
net_weight number No Net weight of one piece, in kg. Not the box weight.
origin text No Country of origin, e.g. FR.
ean13 text No EAN-13 barcode. Send it as a string to keep leading zeros.
brand text No Brand.
packaging text No Packaging description.
size_label text No Size or caliber.
production_zone text No Production zone.
tag text No Free tag.

Rules:

  • Any other key is accepted but not stored. This includes variety, size (use size_label) and unit_measure_code.
  • Attributes with an empty value are skipped.
  • The list replaces the stored attributes. On update, a stored attribute that is missing from the request is removed from the reference. Always send the complete list.
  • Box weight, pieces per box and boxes per pallet belong in logistics_units[], not here.

logistics_units[]

Field Type Required Description
code string(32) Yes Your logistics unit code, e.g. 01, 03. Unique within the article. If the same code appears twice, the last one is used.
box_weight string or number Yes Weight of one box, in kg, e.g. "4.20" or 4.2.
pieces_per_box string or integer Yes Number of pieces in one box, e.g. 12.
box_per_pallet string or integer No Average number of boxes per pallet, e.g. 144.
box_type_code string(32) No Your code for the physical box type, e.g. CRT, COL, 2PL. Unknown codes are created automatically in the workspace's box types. Omit it when there is no physical container.
box_type_label string No Display name of the box type. When sent, it becomes the box type's name, also for an existing box type. When never sent, the name is the code.

Stored name

Each reference's name is built from the article name, so that the logistics units of one article can be told apart:

price_unit Stored name Example
piece <name> - <box_type_code>-<pieces_per_box>piece CONCOMBRE PIECE - CRT-12piece
kg <name> - <box_type_code>-<box_weight>kg CONCOMBRE PIECE - CRT-4.2kg
box or pallet <name> - <box_type_code> CONCOMBRE PIECE - CRT

Without a box_type_code (or with a code made only of dashes, such as -), the - <box_type_code> part is left out. Numbers are written in their shortest form (4.20 becomes 4.2).

Creating and Updating References

Send a batch of 1 to 500 articles with POST /references. Only JSON is accepted.

Request

POST /v2/partner/{workspaceID}/references
Content-Type: application/json
Authorization: Bearer {token}
{
  "references": [
    {
      "code": "00027598",
      "name": "CONCOMBRE PIECE",
      "status": "active",
      "product_kinds": [
        { "code": "46", "name": "LEGUMES FRAIS TRAD" },
        { "code": "795", "name": "CONCOMBRE" },
        { "code": "60", "name": "VERT" },
        { "code": "00004593", "name": "CONCOMBRE PIECE" }
      ],
      "attributes": [
        { "attribute": "price_unit", "value": "piece" },
        { "attribute": "origin", "value": "FR" },
        { "attribute": "vat_rate", "value": 5.5 },
        { "attribute": "ean13", "value": "3355750001621" }
      ],
      "logistics_units": [
        {
          "code": "01",
          "box_type_code": "CRT",
          "box_type_label": "Carton",
          "box_weight": "4.20",
          "pieces_per_box": 12,
          "box_per_pallet": 144
        },
        {
          "code": "03",
          "box_type_code": "COL",
          "box_weight": "8.40",
          "pieces_per_box": 24
        }
      ],
      "metadata": { "source": "ERP" }
    }
  ]
}

This request creates or updates two references: 00027598-01, named CONCOMBRE PIECE - CRT-12piece, and 00027598-03, named CONCOMBRE PIECE - COL-24piece.

Response

200 OK with the references that were saved (one per logistics unit sent) and the rows that failed. Trimmed for readability:

{
  "references": [
    {
      "id": 1048213,
      "name": "CONCOMBRE PIECE - CRT-12piece",
      "buyer_tag": "00027598-01",
      "status": "active",
      "workspace_id": 123,
      "product_kind_id": 52114,
      "metadata": { "source": "ERP" },
      "created_at": "2026-10-30T09:12:44Z",
      "updated_at": "2026-10-30T09:12:44Z"
    },
    {
      "id": 1048214,
      "name": "CONCOMBRE PIECE - COL-24piece",
      "buyer_tag": "00027598-03",
      "status": "active",
      "workspace_id": 123,
      "product_kind_id": 52114,
      "metadata": { "source": "ERP" },
      "created_at": "2026-10-30T09:12:44Z",
      "updated_at": "2026-10-30T09:12:44Z"
    }
  ],
  "errors": []
}

buyer_tag is the composite code. The response only contains the references from the request, not other logistics units already stored for the same article. See the API Reference for every response field.

What an update changes

When a composite code already exists, the reference is updated with the values in the request:

  • name, description, organic, product_kinds, metadata and deleted_at are overwritten. A field you leave out is reset (for example, a missing metadata clears it).
  • attributes are replaced by the list you send.
  • The box type is replaced by box_type_code.
  • status is the only field kept when you leave it out.

Always send the complete article, not only the fields that changed.

Status

  • On create: a reference is inactive unless you send "status": "active".
  • On update: "active" or "inactive" sets the status. If status is left out, the current status is kept.

Soft delete

deleted_at deactivates the references of the logistics units included in the request:

  • A past or current timestamp deactivates them immediately.
  • A future timestamp keeps them active until that moment, then they are treated as inactive automatically.
  • Leaving deleted_at out on a later request reactivates them.
  • An article with deleted_at whose composite code does not exist yet is skipped: nothing is created, and it does not appear in the response.

The timestamp must be RFC 3339 (e.g. 2026-11-01T00:00:00Z). Data is never physically deleted, so a reference keeps its ID and history when reactivated.

Partial success

Each article and each logistics unit is checked independently. Rows that fail are left out of references and reported in errors, and the rest of the batch is saved:

{
  "references": [ { "id": 1048213, "buyer_tag": "00027598-01", "...": "..." } ],
  "errors": [
    {
      "index": 1,
      "code": "00030114",
      "logistics_unit_code": "01",
      "message": "Attribute 'price_unit' is required and must be one of: kg, box, piece, pallet."
    },
    {
      "index": 2,
      "code": "00030200",
      "message": "product_kinds is required and must contain at least one entry"
    }
  ]
}
Field Description
code code of the failing article.
logistics_unit_code The failing logistics unit, when the error concerns one logistics unit only.
message What went wrong.
index Position of the row. Use code and logistics_unit_code to match an error to your data: index is not always the article's position in your request.

Common row errors:

Message Cause
product_kinds is required and must contain at least one entry product_kinds missing or empty.
product_kinds entries must have a non-empty code and name A category without code or name.
name exceeds 256 characters name too long.
deleted_at must be RFC3339 deleted_at in another date format.
box_weight is required / pieces_per_box is required Missing logistics unit value.
logistics_unit code exceeds 32 characters Logistics unit code too long.
composite code exceeds 256 characters code plus logistics unit code too long.
Attribute 'price_unit' is required and must be one of: kg, box, piece, pallet. price_unit missing or empty.
Attribute '<key>' must be one of: kg, box, piece, pallet (got '...'). Invalid price_unit or sale_unit.
Attribute '<key>' must be a number, but got '...'. Non-numeric value for a numeric attribute or logistics unit field, e.g. vat_rate or box_weight.

Deleting References

DELETE /references deactivates a list of references immediately, by composite code. It has the same effect as sending deleted_at with the current time.

Request

DELETE /v2/partner/{workspaceID}/references
Content-Type: application/json
Authorization: Bearer {token}
{
  "codes": ["00027598-01", "00027598-03"]
}
  • Each entry is a composite code <code>-<logistics unit code>. A bare article code is not recognized.
  • Send 1 to 500 codes per request. Duplicates are ignored.
  • References not listed are left unchanged.
  • A reference that already has a deleted_at keeps its existing date, and is still reported as deleted.
  • To reactivate a reference, send it again with POST without deleted_at.

Response

{
  "deleted": ["00027598-01"],
  "errors": [
    { "index": 1, "code": "00027598-03", "message": "unknown code" }
  ]
}

Here index is the position of the code in your codes array.

Integration Workflow

sequenceDiagram
    participant ERP as Buyer ERP / PIM
    participant API as Consentio API

    ERP->>API: POST /references (initial load, batches of up to 500)
    API-->>ERP: 200 OK (references + errors)

    loop On every change, or a scheduled refresh
        ERP->>API: POST /references (complete articles)
        API-->>ERP: 200 OK (only the logistics units sent are touched)
    end

    ERP->>API: DELETE /references { codes: ["-"] }
    API-->>ERP: 200 OK (deleted + errors)

Error Handling

HTTP Code Meaning
200 Request processed. Check errors for rows that failed.
400 Empty or malformed JSON body, or a batch outside 1 to 500 items. Nothing is saved.
401 Missing, invalid or revoked token.
403 The token lacks the references:write permission, or belongs to another workspace.
5xx Unexpected server error. No reference is saved: retry the same request.

Best Practices

  1. Always send price_unit: an article without it is rejected.

  2. One object per article: list all its packaging options in logistics_units[] instead of sending the article several times.

  3. Send complete articles: every update overwrites the reference, including attributes and metadata.

  4. Keep codes stable: code, logistics unit codes and box_type_code are the keys that connect your data to Consentio.

  5. Keep the category tree consistent: always send the same levels, root to leaf.

  6. Check errors on every response: a 200 can still contain rows that failed.

  7. Retry safely: requests are idempotent, so resending a batch after a timeout or a 5xx creates no duplicates.