References

Reference entities and their records — brands, manufacturers and any other domain a product points at by attribute value instead of duplicating on every row.

A brand is not a string on nine thousand products. It is a record the catalog points at, so it is edited once.

Two entities do this:

EntityBase pathIs
reference_entities/v1/products/reference_entitiesThe domain — "brand", "manufacturer", "certification"
reference_entity_records/v1/products/reference_entity_recordsThe rows inside it — "acme", "globex"

GET /v1/products/reference_entities and GET /v1/products/reference_entity_records also filter on active. active is true unless the entry is inactive (false). A list returns both unless you filter, so use ?active=true for a picker. Records that already carry an inactive entry keep it; a write cannot newly assign one (409 entry_inactive). active is also an optional boolean on POST and PUT of a reference entity and of a reference entity record, default true: send false to make it inactive, and anything that is not a boolean answers 400 invalid_active.

The entity

Reference entity
{
  "code": "brand",
  "labels": { "en": "Brand", "de": "Marke" },
  "image": null
}

Label keys follow the tenant's locale policy: de and en in a tenant that keeps text per language, as in these examples, de-DE and en-GB in one that keeps text per region. See Languages and locale codes.

code is unique per tenant and is the stable identifier. labels is the heading over its record list. image is a delivery path or URL for the entity's own icon and is cosmetic — nothing in this app resolves it.

The records

Reference entity record
{
  "reference_entity_id": "…",
  "code": "acme",
  "labels": { "en": "ACME Tools", "de": "ACME Werkzeuge" },
  "attribute_values": {
    "common": { "founded": 1946, "website": "https://example.com" }
  }
}

code is unique within the entity, and it is the value a product stores when it points at this record — the same way a select stores an option code, never a label.

A record carries attribute_values with the same four-bucket structure a product does, so a reference domain can be modelled as richly as the catalog itself. See Products for the bucket rules.

How a product points at one

An attribute of type: "reference_entity" names the domain in its config.reference_entity, and the product then stores the record's code in attribute_values:

attribute_values
{ "common": { "brand": "acme" } }

Reference-entity attributes are declared exactly like any other attribute — see Data model.

Attributes on a reference domain

Attributes are not products-only. An attribute row carries entity_type (product, reference_entity, asset, category) and, for the reference and asset cases, an entity_ref naming one domain by code — the attributes of brand rather than of every reference entity.

Reference records have attributes but no family, so read their shape without a family:

Request
curl "https://api.revenexx.com/v1/products/attribute-schema?entity_type=reference_entity&entity_ref=brand" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..."

That returns every attribute declared for that domain, ready to render. See Completeness.

Create

OperationWhat it does
POST /v1/products/reference_entitiesCreates an entity. code is required. A code already taken answers 409.
POST /v1/products/reference_entity_recordsCreates a record of an entity. reference_entity_id and code are required. A code already taken within the entity answers 409, and so does an inactive reference entity (entry_inactive).

Each create answers 201 with the stored row. A body whose active is not true or false answers 400.

Read, change or delete one entry

GET returns the whole row as stored. PUT is a partial patch: only the named columns change. A body that names no column answers 400, and so does an active that is not true or false (invalid_active). A locale key in labels or attribute_values that is not one of the tenant's write keys answers 422. DELETE is a hard delete, with no trash and no restore. An unknown id answers 404, and so does another tenant's id.

OperationWhat it does
GET /v1/products/reference_entities/{id}Reads one reference entity.
PUT /v1/products/reference_entities/{id}Changes the named columns. A code already taken answers 409.
DELETE /v1/products/reference_entities/{id}Deletes the entity, and with it its records (reference_entity_id).
GET /v1/products/reference_entity_records/{id}Reads one record, its attribute_values included.
PUT /v1/products/reference_entity_records/{id}Changes the named columns. A clash on reference_entity_id + code answers 409, and so does moving it to an inactive reference entity (entry_inactive).
DELETE /v1/products/reference_entity_records/{id}Deletes the record. Nothing else changes.

Where to go next

  • Data model — declaring the attribute that points here.
  • Assets — the other entity kind with attributes and no family.
  • Products — the attribute document a reference code is stored in.
Was this page helpful?