For the complete documentation index, see llms.txt. This page is also available as Markdown.

Products

List products

get

Returns products in the tenant, paginated. Only non-deleted drafts are returned in this iteration β€” published versions and soft-deleted records are excluded.

Query

  • search β€” case-insensitive substring on name.

  • category_id β€” direct-parent category filter.

  • is_active β€” filter by activation state.

  • page / limit β€” defaults page = 1, limit = 25, max limit = 100.

Authorizations
x-api-keystringRequired
Query parameters
searchstring Β· max: 100Optional

Case-insensitive substring match on name.

category_idstring Β· uuidOptional
is_activebooleanOptional
pagenumber Β· min: 1OptionalDefault: 1
limitnumber Β· min: 1 Β· max: 100OptionalDefault: 25
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
get/api/v1/public/products
GET /api/v1/public/products HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
{
  "meta": {
    "total": 1,
    "lastPage": 1,
    "currentPage": 1,
    "perPage": 1,
    "prev": 1,
    "next": 1
  },
  "data": [
    {
      "id": "text",
      "name": "text",
      "category": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "name": "text"
      },
      "type": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "name": "text"
      },
      "vendors": [
        {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "name": "text"
        }
      ],
      "status": "draft",
      "is_active": true,
      "created_at": "text",
      "modified_at": "text"
    }
  ]
}

Create product (optionally publish in one call)

post

Creates a fully-formed product in a single POST. Everything the internal editor would create piece-by-piece β€” configurations, options β†’ auto-generated variants, workflow templates + task templates + responsibilities, links, BOM β€” can be supplied in one nested body. Anything omitted is filled with sensible defaults (a "Default" configuration, one default variant, one default workflow with a "Default" task, one "Responsibility 1"). Set publish: true to publish the product in the same request; a draft Product row is always created and, when publishing, a mirrored published row is created alongside it.

Response is a flat record (see PublicCreatedProductDto): the draft id, resolved reference ids (category_id, type_id, vendor_ids, tag_ids), status, and (when publishing) the mirror's published_id. No enrichment β€” no category breadcrumb, no tag rehydration, no hasPublishedVersion post-lookup. If you need the fully-hydrated shape (with breadcrumb path, tag names, etc.) hit GET /:id after create.

Top-level fields

  • name β€” required (1..255 chars).

  • category_id β€” required UUID. Must reference an existing (non-deleted) category.

  • type β€” optional name string. Server finds (case-insensitive) or creates a matching product_type row. Preserves the caller's original casing on create.

  • vendors β€” optional array of name strings (max 50). Server finds-or-creates each vendor and links them via product_meta_vendor_relation (many-to-many).

  • tags β€” optional array of tag name strings (max 20). Server finds-or-creates and links via product_tag_relations.

  • configurations β€” optional array of nested configurations (see below). Omit to get one default configuration seeded.

  • publish β€” optional boolean, default false. When true, an in-memory publish-readiness check runs (every configuration must have β‰₯1 active variant, every variant must have a non-empty SKU); if it passes, the whole product is built as both draft and published in one Kysely transaction.

Configurations

Each entry:

  • name β€” required (1..255 chars).

  • sku β€” optional fallback SKU for auto-generated variants that aren't overridden per-combination.

  • description β€” optional (max 2000 chars).

  • order β€” optional integer (defaults to array index).

  • options β€” optional array of { name, order?, values: [{ value, order? }] }, capped at 3 per configuration. When provided, the server computes the cartesian product of the option values and generates one variant per combination. Every generated variant inherits sku = configuration.sku and empty barcode unless overridden by an entry in variants[].

  • variants β€” optional sparse list of per-combination customizations. Each entry has { combination: [{ option_name, value }], sku?, barcode?, is_active? } β€” only the fields you send are overridden. Unmatched or duplicate combinations return 400. For configs without options, send at most one entry and omit combination β€” the entry overrides the auto-seeded Default variant.

  • workflow_templates β€” optional array (see below), capped at 9 per configuration. Omit to get one default workflow with a single default task.

Workflow templates

Each entry:

  • name β€” required.

  • order β€” optional integer.

  • items β€” array of nodes. Each item is exactly one of:

    • { task: { name, description?, time_limit?, responsibilities? } } β€” the server creates a new workflow_task_template and links it. If responsibilities is omitted, one Responsibility 1 is auto-created with no relations.

    • { nested_workflow_template_id: uuid } β€” references an existing workflow_template. Items are auto-positioned vertically on the canvas (position_x = 100, position_y = 100 + index * 150); edges are not accepted in this iteration.

  • bom β€” optional array of BOM entries { variant_combination?, items: [{ material_id, quantity? }] }. When the enclosing configuration has options, variant_combination is required to identify which auto-generated variant the BOM attaches to. material_id must reference an existing material.

Responsibilities on a task

Each responsibility supports:

  • name β€” optional (defaults to "Responsibility 1").

  • responsibility_count β€” optional integer, defaults to 1.

  • assigment_type β€” optional enum (Manual / Auto / Self_Assignment), defaults to Manual.

  • department_ids, position_type_ids, user_ids β€” optional UUID arrays; each id must exist in the tenant.

Uniqueness rules enforced up-front

  • SKUs: a configuration owns a SKU namespace (its own sku plus every one of its variants'). Two configurations in the same request can't share any SKU. Any SKU already used on another product's configuration or variant β†’ 409.

  • Barcodes: two variants can share a barcode only if they're the same logical variant across versions. Any duplicate barcode within the request, or one already used on another product's variant β†’ 409.

Validation error catalogue

  • 400 β€” missing required field, invalid enum, unmatched variants[].combination, duplicate variant combination, workflow item with neither task nor nested_workflow_template_id (or both), a configuration with more than 3 options, or a configuration with more than 9 workflow templates.

  • 404 β€” unknown category_id, nested_workflow_template_id, material_id, department_id, position_type_id, or user_id.

  • 409 β€” SKU collision (within the request or against the tenant), barcode collision, or publish-readiness failure (missing SKU / configuration without an active variant).

Authorizations
x-api-keystringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Required
category_idstring Β· uuidRequired
typestring Β· min: 1 Β· max: 255Optional

Product type NAME. Server finds (case-insensitive) or creates a ProductType.

vendorsstring[] Β· max: 50Optional

Product vendor NAMES. Server finds (case-insensitive) or creates each vendor and links them all to the product meta.

tagsstring[] Β· max: 20Optional

Tag names β€” server finds-or-creates.

publishbooleanOptional

When true, publish the product in the same call. Creates a published Product row alongside the draft; readiness validated in-memory (each variant needs a non-empty SKU + β‰₯1 active variant per config).

Default: false
Responses
201Success
application/json
idstringRequired

Draft product id β€” the canonical id the caller uses on every subsequent call.

namestringRequired
category_idstringRequired
type_idstring Β· nullableRequired

Resolved product_type id or null.

vendor_idsstring[]Required
tag_idsstring[]Required
statusstring Β· enumRequiredPossible values:
is_activebooleanRequired
has_published_versionbooleanRequired
published_idstring Β· nullableRequired

When publish=true was set on create, the id of the published Product row (mirror). Null otherwise.

created_atstring Β· nullableRequired
post/api/v1/public/products
POST /api/v1/public/products HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 1002

{
  "name": "text",
  "category_id": "123e4567-e89b-12d3-a456-426614174000",
  "type": "text",
  "vendors": [
    "text"
  ],
  "tags": [
    "text"
  ],
  "configurations": [
    {
      "name": "text",
      "sku": "text",
      "description": "text",
      "order": 0,
      "options": [
        {
          "name": "text",
          "order": 0,
          "values": [
            {
              "value": "text",
              "order": 0
            }
          ]
        }
      ],
      "variants": [
        {
          "combination": [
            {
              "option_name": "text",
              "value": "text"
            }
          ],
          "sku": "text",
          "barcode": "text",
          "is_active": true
        }
      ],
      "workflow_templates": [
        {
          "name": "text",
          "order": 0,
          "items": [
            {
              "task": {
                "name": "text",
                "description": "text",
                "time_limit": 0,
                "responsibilities": [
                  {
                    "name": "text",
                    "responsibility_count": 1,
                    "assigment_type": "Manual",
                    "department_ids": [
                      "123e4567-e89b-12d3-a456-426614174000"
                    ],
                    "position_type_ids": [
                      "123e4567-e89b-12d3-a456-426614174000"
                    ],
                    "user_ids": [
                      "123e4567-e89b-12d3-a456-426614174000"
                    ]
                  }
                ]
              },
              "nested_workflow_template_id": "123e4567-e89b-12d3-a456-426614174000"
            }
          ],
          "bom": [
            {
              "variant_combination": [
                {
                  "option_name": "text",
                  "value": "text"
                }
              ],
              "items": [
                {
                  "material_id": "123e4567-e89b-12d3-a456-426614174000",
                  "quantity": 1
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "publish": false
}
{
  "id": "text",
  "name": "text",
  "category_id": "text",
  "type_id": "text",
  "vendor_ids": [
    "text"
  ],
  "tag_ids": [
    "text"
  ],
  "status": "draft",
  "is_active": true,
  "has_published_version": true,
  "published_id": "text",
  "created_at": "text"
}

Get product by id

get

Returns the draft product record with related entities: category (with breadcrumb path), type, vendors (all linked via the M2M relation, sorted by name), tags, and has_published_version β€” true once a publish has happened for this meta (either via publish=true on create or a future publish endpoint). 404 if the id is unknown or the record has been soft-deleted.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
namestringRequired
statusstring Β· enumRequiredPossible values:
is_activebooleanRequired
has_published_versionbooleanRequired

True when at least one published version exists for this product.

created_atstring Β· nullableRequired
modified_atstring Β· nullableRequired
get/api/v1/public/products/{id}
GET /api/v1/public/products/{id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
{
  "id": "text",
  "name": "text",
  "category": {
    "id": "text",
    "name": "text",
    "path": [
      {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "name": "text"
      }
    ]
  },
  "type": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "name": "text"
  },
  "vendors": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "name": "text"
    }
  ],
  "tags": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "name": "text"
    }
  ],
  "status": "draft",
  "is_active": true,
  "has_published_version": true,
  "created_at": "text",
  "modified_at": "text"
}

Soft-delete product

delete

Marks the draft product as deleted by setting is_deleted = true. Non-cascading β€” configurations, meta, and any published sibling versions remain untouched (they simply become unreachable from the public API list/get). 204 on success; 404 if the id is unknown or already deleted.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
204Success

No content

delete/api/v1/public/products/{id}
DELETE /api/v1/public/products/{id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*

No content

Update product

patch

Updates any subset of the base product fields. Configurations, workflows, media, variants, and BOM live under separate endpoints (not exposed yet).

Body semantics

  • name, category_id β€” value update. Category must exist.

  • type β€” vendor name string. Server finds (case-insensitive) or creates the type. Pass null to clear; omit to leave unchanged.

  • vendors β€” full-reconcile: the product ends up linked to exactly the supplied vendor names (M2M via product_meta_vendor_relation). Missing names are created; existing rows are reused (case-insensitive match); rows not listed are unlinked. Send [] to clear all vendors.

  • tags β€” full-reconcile: the product ends up linked to exactly the supplied tag names. Missing names are created; existing rows are reused (case-insensitive match); rows not listed are unlinked from the product (the underlying product_tag row is left intact for reuse).

  • is_active β€” toggles the Product.is_active flag.

Returns the refreshed product DTO with vendors as an array. 404 if unknown or soft-deleted.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Optional
category_idstring Β· uuidOptional
typestring Β· min: 1 Β· max: 255 Β· nullableOptional

Product type NAME. Server finds (case-insensitive) or creates a ProductType. Send null to clear.

vendorsstring[] Β· max: 50Optional

Full-reconcile: exactly these vendor NAMES will be linked to the product meta after the call. Server finds-or-creates each vendor. Send [] to clear all vendor links.

tagsstring[] Β· max: 20Optional

Full-reconcile: exactly these tag names will be on the product.

is_activebooleanOptional
Responses
200Success
application/json
idstringRequired
namestringRequired
statusstring Β· enumRequiredPossible values:
is_activebooleanRequired
has_published_versionbooleanRequired

True when at least one published version exists for this product.

created_atstring Β· nullableRequired
modified_atstring Β· nullableRequired
patch/api/v1/public/products/{id}
PATCH /api/v1/public/products/{id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 134

{
  "name": "text",
  "category_id": "123e4567-e89b-12d3-a456-426614174000",
  "type": "text",
  "vendors": [
    "text"
  ],
  "tags": [
    "text"
  ],
  "is_active": true
}
{
  "id": "text",
  "name": "text",
  "category": {
    "id": "text",
    "name": "text",
    "path": [
      {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "name": "text"
      }
    ]
  },
  "type": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "name": "text"
  },
  "vendors": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "name": "text"
    }
  ],
  "tags": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "name": "text"
    }
  ],
  "status": "draft",
  "is_active": true,
  "has_published_version": true,
  "created_at": "text",
  "modified_at": "text"
}

Publish product draft

post

Publishes an existing draft: creates a new published Product row that shares the draft's product_meta_id and clones its configurations onto the new row via the internal duplicate flow. Idempotent-safe against concurrent invocations β€” while a publish is in flight the draft is flagged is_publish_in_progress and a second call returns 409.

Validation runs before the snapshot: every configuration must have β‰₯1 active variant, every variant must have a non-empty SKU, and every workflow template must be internally valid. A failure returns 409 with the offending detail in the message; on success the draft's version is bumped so subsequent edits happen against the next version cycle.

Errors

  • 404 β€” draft not found, or the id belongs to something that isn't a draft.

  • 409 β€” publish already in progress, or the draft fails a publish-readiness check.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
messagestringRequired

Message returned from API confirming the operation

Example: The operation was done successfully
post/api/v1/public/products/{id}/publish
POST /api/v1/public/products/{id}/publish HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
{
  "message": "The operation was done successfully"
}

List configurations for a draft product

get

Returns the configurations attached to the draft in order ascending. Only the draft's own configurations are returned; published versions of the product are not exposed here.

Errors

  • 404 β€” draft not found (or the id belongs to something that isn't a draft).

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
namestringRequired
skustringRequired
descriptionstringRequired
ordernumberRequired
is_activebooleanRequired
created_atstring Β· nullableRequired
modified_atstring Β· nullableRequired
get/api/v1/public/products/{id}/configurations
GET /api/v1/public/products/{id}/configurations HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "name": "text",
    "sku": "text",
    "description": "text",
    "order": 1,
    "is_active": true,
    "created_at": "text",
    "modified_at": "text"
  }
]

Add a configuration to a product draft

post

Creates a new configuration under the draft product and seeds one default variant so the configuration is publishable-ready. If order is omitted the server appends after the current configurations.

Body

  • name β€” required (1..255).

  • sku β€” required (1..255).

  • description β€” optional (max 2000).

  • order β€” optional integer β‰₯ 0. Defaults to current configuration count.

  • is_active β€” optional boolean. Defaults to true.

Errors

  • 400 β€” validation failure on the body.

  • 404 β€” draft not found.

  • 409 β€” product already has the maximum of 25 configurations, or the supplied sku collides with another configuration/variant in the tenant.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Required
skustring Β· max: 255Required
descriptionstring Β· max: 2000Optional
ordernumberOptional
is_activebooleanOptional
Responses
201Success
application/json
idstringRequired
namestringRequired
skustringRequired
descriptionstringRequired
ordernumberRequired
is_activebooleanRequired
created_atstring Β· nullableRequired
modified_atstring Β· nullableRequired
post/api/v1/public/products/{id}/configurations
POST /api/v1/public/products/{id}/configurations HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 76

{
  "name": "text",
  "sku": "text",
  "description": "text",
  "order": 1,
  "is_active": true
}
{
  "id": "text",
  "name": "text",
  "sku": "text",
  "description": "text",
  "order": 1,
  "is_active": true,
  "created_at": "text",
  "modified_at": "text"
}

Update a configuration (name / sku / description)

put

Partial-update of a configuration. Any subset of name, sku, description may be supplied.

  • update_name_in_all_versions β€” when true and name is provided, the rename is broadcast to every configuration with the same current name across every published version of the product. When false or omitted, only the addressed configuration row is renamed.

  • sku and description always update just the addressed configuration β€” they are per-version snapshots and are never broadcast, even with update_name_in_all_versions set.

Errors

  • 400 β€” validation failure on the body.

  • 404 β€” draft or configuration not found (configuration must belong to the given product).

  • 409 β€” SKU collision.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Optional
skustring Β· max: 255Optional
descriptionstring Β· max: 2000Optional
update_name_in_all_versionsbooleanOptional

When true and name is provided, the rename is broadcast to every configuration with the same current name across all published versions of the product. sku and description are always applied only to the addressed configuration (they are per-version snapshots).

Default: false
Responses
200Success
application/json
idstringRequired
namestringRequired
skustringRequired
descriptionstringRequired
ordernumberRequired
is_activebooleanRequired
created_atstring Β· nullableRequired
modified_atstring Β· nullableRequired
put/api/v1/public/products/{id}/configurations/{config_id}
PUT /api/v1/public/products/{id}/configurations/{config_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 85

{
  "name": "text",
  "sku": "text",
  "description": "text",
  "update_name_in_all_versions": false
}
{
  "id": "text",
  "name": "text",
  "sku": "text",
  "description": "text",
  "order": 1,
  "is_active": true,
  "created_at": "text",
  "modified_at": "text"
}

Delete a configuration

delete

Hard-deletes the configuration together with its variants, workflow templates, and BOMs.

Blocked in two situations, both returning 409:

  • The configuration is the last remaining one on the product.

  • Any production_workflow references one of the configuration's variants (regardless of status).

Errors

  • 404 β€” draft or configuration not found.

  • 409 β€” last configuration on the product, or a production workflow references its variants.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*

No content

List workflow templates for a configuration

get

Returns the workflow templates attached to the configuration, ordered by order ascending. Only the draft configuration's own workflow templates are returned; workflow templates on published versions are not exposed here.

Errors

  • 404 β€” draft or configuration not found (configuration must belong to the given product).

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
namestringRequired
ordernumberRequired
is_activebooleanRequired
prefer_auto_assign_users_with_prior_experiencebooleanRequired

Prefer auto-assigning users with prior experience on this workflow.

created_atstring Β· nullableRequired
get/api/v1/public/products/{id}/configurations/{config_id}/workflows
GET /api/v1/public/products/{id}/configurations/{config_id}/workflows HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "name": "text",
    "order": 1,
    "is_active": true,
    "prefer_auto_assign_users_with_prior_experience": true,
    "created_at": "text"
  }
]

Add a workflow template to a configuration

post

Creates a bare workflow template row on the configuration. Task templates, template items, and edges are not seeded here β€” callers will wire those via a future set of endpoints.

Body

  • name β€” required (1..255).

  • order β€” optional integer β‰₯ 0. Defaults to the current workflow count.

  • is_active β€” optional boolean. Defaults to true.

  • prefer_auto_assign_users_with_prior_experience β€” optional boolean. Defaults to true (matches the DB column default).

Errors

  • 400 β€” validation failure on the body.

  • 404 β€” draft or configuration not found.

  • 409 β€” configuration already has the maximum of 9 workflow templates.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Required
ordernumberOptional
is_activebooleanOptional
prefer_auto_assign_users_with_prior_experiencebooleanOptional
Responses
201Success
application/json
idstringRequired
namestringRequired
ordernumberRequired
is_activebooleanRequired
prefer_auto_assign_users_with_prior_experiencebooleanRequired

Prefer auto-assigning users with prior experience on this workflow.

created_atstring Β· nullableRequired
post/api/v1/public/products/{id}/configurations/{config_id}/workflows
POST /api/v1/public/products/{id}/configurations/{config_id}/workflows HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 96

{
  "name": "text",
  "order": 1,
  "is_active": true,
  "prefer_auto_assign_users_with_prior_experience": true
}
{
  "id": "text",
  "name": "text",
  "order": 1,
  "is_active": true,
  "prefer_auto_assign_users_with_prior_experience": true,
  "created_at": "text"
}

Update a workflow template (name / order / flags)

put

Partial-update of a workflow template. Any subset of name, order, is_active, prefer_auto_assign_users_with_prior_experience may be supplied. Updates the addressed workflow template row only β€” no broadcast across product versions.

Errors

  • 400 β€” validation failure on the body.

  • 404 β€” draft, configuration, or workflow not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
workflow_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Optional
ordernumberOptional
is_activebooleanOptional
prefer_auto_assign_users_with_prior_experiencebooleanOptional
Responses
200Success
application/json
idstringRequired
namestringRequired
ordernumberRequired
is_activebooleanRequired
prefer_auto_assign_users_with_prior_experiencebooleanRequired

Prefer auto-assigning users with prior experience on this workflow.

created_atstring Β· nullableRequired
put/api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}
PUT /api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 96

{
  "name": "text",
  "order": 1,
  "is_active": true,
  "prefer_auto_assign_users_with_prior_experience": true
}
{
  "id": "text",
  "name": "text",
  "order": 1,
  "is_active": true,
  "prefer_auto_assign_users_with_prior_experience": true,
  "created_at": "text"
}

Delete a workflow template

delete

Hard-deletes the workflow template together with its task templates, template items, workflow edges, and BOMs.

Blocked in two situations, both returning 409:

  • The workflow is the last remaining one on the configuration.

  • Any production_workflow references one of the configuration's variants (regardless of status) β€” same rule as configuration delete.

Errors

  • 404 β€” draft, configuration, or workflow not found.

  • 409 β€” last workflow on the configuration, or a production workflow references its variants.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
workflow_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*

No content

List tasks on a workflow

get

Returns the task templates attached to the workflow, ordered by order ascending. Component items (nested workflow references) are excluded β€” this endpoint is task-only. Use POST/DELETE on .../tasks to manage component items.

Query

  • search β€” optional case-insensitive substring match on task name.

Errors

  • 404 β€” product draft, configuration, or workflow not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
workflow_idstringRequired
Query parameters
searchstring Β· max: 100Optional

Case-insensitive substring match on task name.

Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
namestringRequired
descriptionstringRequired
ordernumberRequired
time_limitnumberRequired
basic_rewardnumberRequired
workflow_template_idstringRequired
created_atstring Β· nullableRequired
get/api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks
GET /api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "name": "text",
    "description": "text",
    "order": 1,
    "time_limit": 1,
    "basic_reward": 1,
    "workflow_template_id": "text",
    "created_at": "text"
  }
]

Add a task or component to a workflow

post

Creates a new canvas node on the addressed workflow. The endpoint runs in two modes, distinguished by the presence of nested_workflow_template_id in the body.

Task mode

Send name (+ optional description, order, time_limit, basic_reward, responsibilities). The server creates a fresh workflow_task_template, its workflow_template_item canvas node, and either the responsibilities you supply or a default Responsibility 1 (no relations).

Component mode

Send only nested_workflow_template_id (must reference an existing workflow template in the tenant). The server creates a workflow_template_item that references that workflow as a nested component; no new task template is created.

The new item is positioned at (position_x = 100, position_y = MAX(existing position_y on this workflow) + 150) β€” items never share coordinates, even after prior deletes.

Errors

  • 400 β€” validation failure, body specifies both modes (name + nested_workflow_template_id), or specifies neither.

  • 404 β€” draft, configuration, workflow, nested_workflow_template_id, or any department_id / position_type_id / user_id inside a responsibility not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
workflow_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Optional
descriptionstring Β· max: 2000Optional
ordernumberOptional
time_limitnumberOptional
basic_rewardnumberOptional
nested_workflow_template_idstring Β· uuidOptional

Component-mode discriminator. When present, the endpoint creates a workflow_template_item referencing this workflow template as a nested component; task-mode fields (name/description/…) are ignored. Exactly one of name or nested_workflow_template_id must be provided.

Responses
201Success
application/json
idstringRequired

ID of the workflow_template_item (canvas node).

typestring Β· enumRequiredPossible values:
task_template_idstring Β· nullableRequired
namestring Β· nullableRequired
descriptionstring Β· nullableRequired
ordernumber Β· nullableRequired
time_limitnumber Β· nullableRequired
basic_rewardnumber Β· nullableRequired
nested_workflow_template_idstring Β· nullableRequired
position_xnumberRequired
position_ynumberRequired
created_atstring Β· nullableRequired
post/api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks
POST /api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 406

{
  "name": "text",
  "description": "text",
  "order": 1,
  "time_limit": 1,
  "basic_reward": 1,
  "responsibilities": [
    {
      "name": "text",
      "responsibility_count": 1,
      "assigment_type": "Manual",
      "department_ids": [
        "123e4567-e89b-12d3-a456-426614174000"
      ],
      "position_type_ids": [
        "123e4567-e89b-12d3-a456-426614174000"
      ],
      "user_ids": [
        "123e4567-e89b-12d3-a456-426614174000"
      ]
    }
  ],
  "nested_workflow_template_id": "123e4567-e89b-12d3-a456-426614174000"
}
{
  "id": "text",
  "type": "task",
  "task_template_id": "text",
  "name": "text",
  "description": "text",
  "order": 1,
  "time_limit": 1,
  "basic_reward": 1,
  "nested_workflow_template_id": "text",
  "position_x": 1,
  "position_y": 1,
  "created_at": "text"
}

Update a task item (name / order / basic_reward)

put

Partial-update of a task item. Any subset of name, order, basic_reward may be supplied. Empty body is a no-op returning the current state.

  • update_in_all_versions β€” when true, every supplied field is broadcast to matching tasks (same current name, same workflow position across versions) on every published version's matching workflow. When false or omitted, only the addressed task row is updated.

Only applies to task-mode items. Component items return 400 (components own no fields on the item itself β€” the referenced workflow is authoritative).

Errors

  • 400 β€” validation failure, or the addressed item is a component.

  • 404 β€” draft, configuration, workflow, or task item not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
workflow_idstringRequired
task_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Optional
ordernumberOptional
basic_rewardnumberOptional
update_in_all_versionsbooleanOptional

When true, every supplied field (name / order / basic_reward) is broadcast to matching tasks (same current name) on every published version's matching workflow. When false or omitted, only the addressed task row is updated.

Default: false
Responses
200Success
application/json
idstringRequired

ID of the workflow_template_item (canvas node).

typestring Β· enumRequiredPossible values:
task_template_idstring Β· nullableRequired
namestring Β· nullableRequired
descriptionstring Β· nullableRequired
ordernumber Β· nullableRequired
time_limitnumber Β· nullableRequired
basic_rewardnumber Β· nullableRequired
nested_workflow_template_idstring Β· nullableRequired
position_xnumberRequired
position_ynumberRequired
created_atstring Β· nullableRequired
put/api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks/{task_id}
PUT /api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks/{task_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 73

{
  "name": "text",
  "order": 1,
  "basic_reward": 1,
  "update_in_all_versions": false
}
{
  "id": "text",
  "type": "task",
  "task_template_id": "text",
  "name": "text",
  "description": "text",
  "order": 1,
  "time_limit": 1,
  "basic_reward": 1,
  "nested_workflow_template_id": "text",
  "position_x": 1,
  "position_y": 1,
  "created_at": "text"
}

Delete a task or component from a workflow

delete

Removes the canvas node.

  • Task item β€” deletes the workflow_template_item, then cascades the task template (bonuses, files, tags, responsibilities). Blocked (409) when any task row (production task) references this template β€” i.e. a production launched from a published version already picked it up.

  • Component item β€” deletes only the workflow_template_item row. The referenced nested workflow template is untouched.

Errors

  • 404 β€” draft, configuration, workflow, or item not found.

  • 409 β€” task item is referenced by a production task.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
workflow_idstringRequired
task_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks/{task_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id}/workflows/{workflow_id}/tasks/{task_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*

No content

Upload a media file to a configuration

post

Downloads the image at url server-side (HTTPS, max 10 MB, Content-Type must start with image) and attaches it to the configuration's photo set.

Body

  • url β€” required HTTPS URL.

  • file_name β€” optional; used when persisting the downloaded file.

  • is_primary β€” optional, default false. When true, marks this photo as the configuration's default photo.

  • apply_to_all_versions β€” optional, default false. When true, the same file is linked into every published version's matching configuration too. When false or omitted, only the draft configuration receives the new relation and Product.modified_at on the draft is bumped.

Errors

  • 400 β€” missing/invalid url, wrong content type, or exceeds size limit.

  • 404 β€” draft or configuration not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
urlstringRequired

HTTPS URL of the image to download.

Example: https://cdn.example.com/img.png
file_namestringOptional

Optional filename to store the file as.

is_primarybooleanOptional

When true, marks this new photo as the configuration default.

Default: false
apply_to_all_versionsbooleanOptional

When true, mirror this add across every published version of the product (same file linked into each version's matching configuration). Default false β€” draft-only.

Default: false
Responses
201Success
application/json
idstringRequired
file_idstringRequired
product_configuration_idstringRequired
is_show_by_defaultbooleanRequired
post/api/v1/public/products/{id}/configurations/{config_id}/media
POST /api/v1/public/products/{id}/configurations/{config_id}/media HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 109

{
  "url": "https://cdn.example.com/img.png",
  "file_name": "text",
  "is_primary": false,
  "apply_to_all_versions": false
}
{
  "id": "text",
  "file_id": "text",
  "product_configuration_id": "text",
  "is_show_by_default": true
}

Delete a media file from a configuration

delete

Removes the photo relation from the configuration. Any variant that pointed at the removed relation has its configuration_photo_relation_id cleared. If the underlying file has no remaining references, it is removed from the bucket.

Body

  • apply_to_all_versions β€” optional, default false. When true, matching relations (same file_id) across every version's configuration are removed too. When false, only the draft configuration's relation is removed and Product.modified_at on the draft is bumped.

Errors

  • 404 β€” draft, configuration, or media relation not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
media_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
apply_to_all_versionsbooleanOptional

When true, remove every matching relation (same file id) across all versions of the product too. Default false β€” draft-only.

Default: false
Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}/media/{media_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id}/media/{media_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 31

{
  "apply_to_all_versions": false
}

No content

Set a variant's primary photo (uploads a new image)

post

Downloads the image at url server-side, attaches it to the configuration's photo set, and points the addressed variant at the new relation. Always draft-only β€” variants do not carry a cross-version link. To broadcast, upload the file via POST .../media with apply_to_all_versions=true first.

Bumps Product.modified_at on the draft.

Errors

  • 400 β€” missing/invalid url, wrong content type, or exceeds size limit.

  • 404 β€” draft, configuration, or variant not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
variant_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
urlstringRequired

HTTPS URL of the image to download.

Example: https://cdn.example.com/img.png
file_namestringOptional

Optional filename to store the file as.

Responses
200Success
application/json
messagestringRequired

Message returned from API confirming the operation

Example: The operation was done successfully
post/api/v1/public/products/{id}/configurations/{config_id}/variants/{variant_id}/photo
POST /api/v1/public/products/{id}/configurations/{config_id}/variants/{variant_id}/photo HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 60

{
  "url": "https://cdn.example.com/img.png",
  "file_name": "text"
}
{
  "message": "The operation was done successfully"
}

Upload a document to a configuration

post

Downloads the document at url server-side (HTTPS, max 25 MB, Content-Type must be in the shared public-attachment allow-list β€” pdf, doc/docx, xls/xlsx, plain text, png/jpeg/webp, model/obj, hp-hpgl) and attaches it to the configuration.

Body

  • url β€” required HTTPS URL.

  • file_name β€” optional; used when persisting the downloaded file.

  • apply_to_all_versions β€” optional, default false. When true, the same file is linked into every published version's matching configuration too. When false or omitted, only the draft configuration receives the new relation and Product.modified_at on the draft is bumped.

Response

Returns the draft's relation row with the stored file's metadata: url (signed download URL), file_name, mime_type, size.

Errors

  • 400 β€” invalid url or exceeds size limit.

  • 404 β€” draft or configuration not found.

  • 409 β€” content type not in the accepted document set.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
urlstringRequired

HTTPS URL of the document to download.

Example: https://cdn.example.com/spec.pdf
file_namestringOptional

Optional filename to store the file as.

apply_to_all_versionsbooleanOptional

When true, mirror the upload across every published version of the product (same file linked into each version's matching configuration). Default false β€” draft-only.

Default: false
Responses
201Success
application/json
idstringRequired

ID of the attachment relation row.

product_configuration_idstringRequired
file_idstringRequired
urlstringRequired

Signed URL for downloading the file.

file_namestringRequired
mime_typestringRequired
sizenumberRequired
post/api/v1/public/products/{id}/configurations/{config_id}/documents
POST /api/v1/public/products/{id}/configurations/{config_id}/documents HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 91

{
  "url": "https://cdn.example.com/spec.pdf",
  "file_name": "text",
  "apply_to_all_versions": false
}
{
  "id": "text",
  "product_configuration_id": "text",
  "file_id": "text",
  "url": "text",
  "file_name": "text",
  "mime_type": "text",
  "size": 1
}

Delete a document from a configuration

delete

Removes the attachment relation. If the underlying file has no remaining references anywhere, it is removed from the bucket too.

Body

  • apply_to_all_versions β€” optional, default false. When true, every matching relation (same file_id) across every version's configuration is removed too. When false or omitted, only the draft's relation is removed and Product.modified_at on the draft is bumped.

Errors

  • 404 β€” draft, configuration, or document not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
document_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
apply_to_all_versionsbooleanOptional

When true, remove every matching relation (same file id) across all versions of the product too. Default false β€” draft-only.

Default: false
Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}/documents/{document_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id}/documents/{document_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 31

{
  "apply_to_all_versions": false
}

No content

get

Returns the links attached to the configuration, ordered by created_at ascending. Only the draft configuration's own links are returned.

Errors

  • 404 β€” draft or configuration not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
product_configuration_idstringRequired
titlestring Β· max: 255Required
urlstring Β· max: 2048Required
created_atstringRequired
get/api/v1/public/products/{id}/configurations/{config_id}/links
GET /api/v1/public/products/{id}/configurations/{config_id}/links HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "product_configuration_id": "text",
    "title": "text",
    "url": "text",
    "created_at": "text"
  }
]

Add a link to a configuration

post

Adds a { url, title } link row to the configuration.

Body

  • url β€” required (1..2048).

  • title β€” required (1..255).

  • apply_to_all_versions β€” optional, default false. When true, the same { url, title } is added to every version's matching configuration too. When false or omitted, only the draft's configuration receives the link and Product.modified_at on the draft is bumped.

Errors

  • 400 β€” validation failure on the body.

  • 404 β€” draft or configuration not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
urlstring Β· min: 1 Β· max: 2048Required
titlestring Β· min: 1 Β· max: 255Required
apply_to_all_versionsbooleanOptional

When true, add the same link into every published version's matching configuration too. Default false β€” draft-only.

Default: false
Responses
201Success
application/json
idstringRequired
product_configuration_idstringRequired
titlestring Β· max: 255Required
urlstring Β· max: 2048Required
created_atstringRequired
post/api/v1/public/products/{id}/configurations/{config_id}/links
POST /api/v1/public/products/{id}/configurations/{config_id}/links HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 59

{
  "url": "text",
  "title": "text",
  "apply_to_all_versions": false
}
{
  "id": "text",
  "product_configuration_id": "text",
  "title": "text",
  "url": "text",
  "created_at": "text"
}
put

Partial-update of a link. Any subset of title, url may be supplied. Empty body is a no-op returning the current state.

  • apply_to_all_versions β€” when true, the change is broadcast to every sibling link (matched by current URL) on every published version's matching configuration. If a configuration has two links with the same URL, both are updated together. When false or omitted, only the addressed link row is updated and Product.modified_at on the draft is bumped.

Errors

  • 400 β€” validation failure on the body.

  • 404 β€” draft, configuration, or link not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
link_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
urlstring Β· min: 1 Β· max: 2048Optional
titlestring Β· min: 1 Β· max: 255Optional
apply_to_all_versionsbooleanOptional

When true, apply the change to every sibling link (matched by current URL) on every published version too. Default false β€” draft-only.

Default: false
Responses
200Success
application/json
idstringRequired
product_configuration_idstringRequired
titlestring Β· max: 255Required
urlstring Β· max: 2048Required
created_atstringRequired
put/api/v1/public/products/{id}/configurations/{config_id}/links/{link_id}
PUT /api/v1/public/products/{id}/configurations/{config_id}/links/{link_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 59

{
  "url": "text",
  "title": "text",
  "apply_to_all_versions": false
}
{
  "id": "text",
  "product_configuration_id": "text",
  "title": "text",
  "url": "text",
  "created_at": "text"
}
delete

Removes the link row.

Body

  • apply_to_all_versions β€” optional, default false. When true, every sibling link (matched by URL) on every published version's matching configuration is removed too. When false or omitted, only the draft's link is removed and Product.modified_at on the draft is bumped.

Errors

  • 404 β€” draft, configuration, or link not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
link_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
apply_to_all_versionsbooleanOptional

When true, remove every sibling link (matched by URL) on every published version too. Default false β€” draft-only.

Default: false
Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}/links/{link_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id}/links/{link_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 31

{
  "apply_to_all_versions": false
}

No content

List parameters on a configuration

get

Returns the parameters (internally: product options) attached to the draft configuration, sorted by order ascending. Each parameter carries its ordered list of values. Published versions of the product are not exposed here β€” parameters are per-version and each version's option/value/variant tree is independent.

Errors

  • 404 β€” draft or configuration not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
product_configuration_idstringRequired
namestringRequired
ordernumberRequired
get/api/v1/public/products/{id}/configurations/{config_id}/parameters
GET /api/v1/public/products/{id}/configurations/{config_id}/parameters HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "product_configuration_id": "text",
    "name": "text",
    "order": 1,
    "values": [
      {
        "id": "text",
        "value": "text",
        "order": 1
      }
    ]
  }
]

Add a parameter to a configuration

post

Creates a new parameter under the draft configuration and expands the variant matrix (cartesian product of every parameter's values). The new parameter is appended (order = current parameter count). Product.modified_at on the draft is bumped.

Body

  • name β€” required (1..255).

  • values β€” required array of unique non-empty value strings (each 1..255). At least one entry.

Cascade

  • First parameter on the config β€” replaces the existing default variant with N variants (one per value). Each variant inherits the configuration's SKU and is active.

  • Additional parameter β€” every existing variant gets the new parameter's first value attached and is renamed; new variants are created for each remaining combination.

Errors

  • 400 β€” validation failure (empty name, empty/duplicate values, missing values).

  • 404 β€” draft or configuration not found.

  • 409 β€” configuration already has the maximum of 3 parameters.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Required
valuesstring[] Β· min: 1Required

At least one value; each value is a non-empty string, unique within this parameter.

Responses
201Success
application/json
idstringRequired
product_configuration_idstringRequired
namestringRequired
ordernumberRequired
post/api/v1/public/products/{id}/configurations/{config_id}/parameters
POST /api/v1/public/products/{id}/configurations/{config_id}/parameters HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 33

{
  "name": "text",
  "values": [
    "text"
  ]
}
{
  "id": "text",
  "product_configuration_id": "text",
  "name": "text",
  "order": 1,
  "values": [
    {
      "id": "text",
      "value": "text",
      "order": 1
    }
  ]
}

Update a parameter (rename / edit value set)

put

Partial-update of a parameter. Any subset of name, values may be supplied.

  • name β€” rename only; leaves values / variants untouched.

  • values β€” full-replace by string match:

    • Existing values whose value appears in the incoming array are kept (variants and product_parameter wiring preserved).

    • Missing existing values are deleted (their variants + parameters are removed).

    • New strings become new values that expand the variant matrix.

    • Array order becomes the new value order.

Renaming a value string is not supported β€” sending values: ["Bilyi", "Kraft"] when the current set is ["Π‘Ρ–Π»ΠΈΠΉ", "ΠšΡ€Π°Ρ„Ρ‚"] deletes both existing rows (and their variants) and creates two new ones. Use the same string to keep the row.

Product.modified_at on the draft is bumped. Empty body is a no-op returning the current state.

Errors

  • 400 β€” validation failure (empty values, duplicates within values, empty name).

  • 404 β€” draft, configuration, or parameter not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
parameter_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
namestring Β· min: 1 Β· max: 255Optional
valuesstring[] Β· min: 1Optional

Full-replace of the value set. Existing values matched by string are kept (variants preserved); missing values are deleted (their variants + parameters are removed); new strings become new values that expand the variant matrix.

Responses
200Success
application/json
idstringRequired
product_configuration_idstringRequired
namestringRequired
ordernumberRequired
put/api/v1/public/products/{id}/configurations/{config_id}/parameters/{parameter_id}
PUT /api/v1/public/products/{id}/configurations/{config_id}/parameters/{parameter_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 33

{
  "name": "text",
  "values": [
    "text"
  ]
}
{
  "id": "text",
  "product_configuration_id": "text",
  "name": "text",
  "order": 1,
  "values": [
    {
      "id": "text",
      "value": "text",
      "order": 1
    }
  ]
}

Delete a parameter

delete

Removes the parameter, its values, and every variant that referenced it.

  • Non-last parameter β€” variants collapse to the remaining parameters' combinations; variant names are recomputed.

  • Last parameter on the config β€” the configuration is left with a single default variant named Default (SKU inherited from the configuration).

Product.modified_at on the draft is bumped.

Errors

  • 404 β€” draft, configuration, or parameter not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
parameter_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
204Success

No content

delete/api/v1/public/products/{id}/configurations/{config_id}/parameters/{parameter_id}
DELETE /api/v1/public/products/{id}/configurations/{config_id}/parameters/{parameter_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*

No content

List variants on a configuration

get

Returns every non-deleted variant of the draft configuration together with its parameter breakdown β€” each entry carries a stable list of { option_name, value } pairs sorted by option name. Callers use this list to identify which variant is which when batch-setting barcodes.

Configurations with no parameters return a single Default variant with has_parameters=false and an empty parameters array.

Errors

  • 404 β€” draft or configuration not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
product_configuration_idstringRequired
namestringRequired
skustringRequired
barcodestringRequired
is_activebooleanRequired
has_parametersbooleanRequired
get/api/v1/public/products/{id}/configurations/{config_id}/variants
GET /api/v1/public/products/{id}/configurations/{config_id}/variants HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "product_configuration_id": "text",
    "name": "text",
    "sku": "text",
    "barcode": "text",
    "is_active": true,
    "has_parameters": true,
    "parameters": [
      {
        "option_name": "text",
        "value": "text"
      }
    ]
  }
]

Batch-set variant barcodes

patch

Applies one barcode per variant in a single request. Payload cap: 500 items per call. An empty barcode string clears the field.

Body

  • items β€” array of { variant_id, barcode }. Every variant_id must belong to the addressed configuration; duplicate ids in one request are rejected.

  • apply_to_all_versions β€” optional, default false. When true, the same barcode also lands on the sibling variant on every published version of this product. Cross-version identity is matched by parameter signature β€” the sorted set of (option_name, value) pairs the variant carries. Sibling versions whose configuration doesn't carry a matching variant (e.g. because the parameter set was restructured after publish) are skipped silently. Draft-only writes bump Product.modified_at; broadcast writes don't.

Barcode uniqueness

Barcodes are enforced unique per tenant with one exception: the same barcode may live on multiple variants that are all siblings across versions of the same product (same product_meta_id + same parameter signature). Attempts to reuse a barcode elsewhere return 409.

Errors

  • 400 β€” empty items, duplicate variant_id, or the same barcode assigned to variants with different parameter combinations within one request.

  • 404 β€” draft, configuration, or any addressed variant not found on the config.

  • 409 β€” a barcode is already used by a non-sibling variant elsewhere in the tenant.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
config_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
apply_to_all_versionsbooleanOptional

When true, apply each barcode to the sibling variant on every published version of the product too (matched by parameter signature). Sibling versions whose config doesn't carry a matching variant are skipped. Draft-only writes bump Product.modified_at; broadcast writes don't.

Default: false
Responses
200Success
application/json
idstringRequired
product_configuration_idstringRequired
namestringRequired
skustringRequired
barcodestringRequired
is_activebooleanRequired
has_parametersbooleanRequired
patch/api/v1/public/products/{id}/configurations/{config_id}/variants
PATCH /api/v1/public/products/{id}/configurations/{config_id}/variants HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 112

{
  "items": [
    {
      "variant_id": "123e4567-e89b-12d3-a456-426614174000",
      "barcode": "text"
    }
  ],
  "apply_to_all_versions": false
}
[
  {
    "id": "text",
    "product_configuration_id": "text",
    "name": "text",
    "sku": "text",
    "barcode": "text",
    "is_active": true,
    "has_parameters": true,
    "parameters": [
      {
        "option_name": "text",
        "value": "text"
      }
    ]
  }
]

List BOMs for a product

get

Returns every non-empty BOM attached to the product (one per (product_variant, workflow_template) pair). Each entry carries its ordered items with the joined material_name + unit (from the material's measurement unit). Optional filters: variant_id, workflow_id.

BOMs are lazily created β€” a BOM row does not appear here until the first POST /bom/items call for that pair.

Errors

  • 404 β€” product not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Query parameters
variant_idstring Β· uuidOptional
workflow_idstring Β· uuidOptional
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
idstringRequired
product_variant_idstringRequired
workflow_template_idstringRequired
is_publishedbooleanRequired
get/api/v1/public/products/{id}/bom
GET /api/v1/public/products/{id}/bom HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "id": "text",
    "product_variant_id": "text",
    "workflow_template_id": "text",
    "is_published": true,
    "items": [
      {
        "id": "text",
        "bom_id": "text",
        "material_id": "text",
        "component_bom_id": "text",
        "material_name": "text",
        "unit": "text",
        "quantity": 1
      }
    ]
  }
]

List BOM versions (placeholder)

get

Returns a single-entry array while native BOM versioning is deferred. The entry reports the current BOM count for the product. This endpoint is stable so future versioning support can extend it without breaking the client contract.

Errors

  • 404 β€” product not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
200Success
application/json
versionnumberRequired

Placeholder version number; always 1 while versioning is deferred.

is_currentbooleanRequired
bom_countnumberRequired
created_atstring Β· nullableRequired
get/api/v1/public/products/{id}/bom/versions
GET /api/v1/public/products/{id}/bom/versions HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*
[
  {
    "version": 1,
    "is_current": true,
    "bom_count": 1,
    "created_at": "text"
  }
]

Add items to a BOM

post

Adds one or more items to the BOM identified by (variant_id, workflow_template_id). The BOM is auto-created if this is the first write for that pair.

Body

  • variant_id β€” required UUID. Must belong to the addressed product.

  • workflow_template_id β€” required UUID. Must live on a configuration of the addressed product.

  • items β€” non-empty array (up to 500). Each item sets exactly one of material_id or component_bom_id, plus a positive quantity (min 0.00001).

  • create_new_version β€” optional. Currently a no-op while versioning is deferred; when set to true the server logs a warning and processes the request in place. Accepted so future callers don't have to change the contract.

Bumps Product.modified_at on the addressed product.

Errors

  • 400 β€” empty items, or an item with both / neither of material_id / component_bom_id.

  • 404 β€” product / variant / workflow_template not found on this product.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
variant_idstring Β· uuidRequired
workflow_template_idstring Β· uuidRequired
create_new_versionbooleanOptional

Versioning is not implemented yet. Accepted for forward compatibility; when true the server logs a warning and processes the request in place.

Default: false
Responses
201Success
application/json
idstringRequired
product_variant_idstringRequired
workflow_template_idstringRequired
is_publishedbooleanRequired
post/api/v1/public/products/{id}/bom/items
POST /api/v1/public/products/{id}/bom/items HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 278

{
  "variant_id": "123e4567-e89b-12d3-a456-426614174000",
  "workflow_template_id": "123e4567-e89b-12d3-a456-426614174000",
  "items": [
    {
      "material_id": "123e4567-e89b-12d3-a456-426614174000",
      "component_bom_id": "123e4567-e89b-12d3-a456-426614174000",
      "quantity": 1
    }
  ],
  "create_new_version": false
}
{
  "id": "text",
  "product_variant_id": "text",
  "workflow_template_id": "text",
  "is_published": true,
  "items": [
    {
      "id": "text",
      "bom_id": "text",
      "material_id": "text",
      "component_bom_id": "text",
      "material_name": "text",
      "unit": "text",
      "quantity": 1
    }
  ]
}

Update a BOM item quantity

put

Updates the item's quantity. Other item fields are immutable in the current schema (item is either material_id or component_bom_id; those are set at create time).

  • create_new_version β€” no-op, same as POST.

Bumps Product.modified_at.

Errors

  • 400 β€” validation failure.

  • 404 β€” product or item not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
item_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Body
quantitynumber Β· min: 0.00001Required
create_new_versionbooleanOptional

No-op while versioning is deferred (same as POST).

Default: false
Responses
200Success
application/json
idstringRequired
bom_idstringRequired
material_idstring Β· nullableRequired
component_bom_idstring Β· nullableRequired
material_namestring Β· nullableRequired

Material display name; null when the item is a nested component.

unitstring Β· nullableRequired

Unit of measure name from the material's measurement_unit; null for component items.

quantitynumberRequired
put/api/v1/public/products/{id}/bom/items/{item_id}
PUT /api/v1/public/products/{id}/bom/items/{item_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 41

{
  "quantity": 1,
  "create_new_version": false
}
{
  "id": "text",
  "bom_id": "text",
  "material_id": "text",
  "component_bom_id": "text",
  "material_name": "text",
  "unit": "text",
  "quantity": 1
}

Delete a BOM item

delete

Removes the item and cascades the BOM closure (drops the parent β†’ component path when the item is a component). Marks the parent BOM's cost cache dirty. Bumps Product.modified_at.

Note: the parent BOM row remains after its last item is deleted (empty BOM). There's no public endpoint to delete the BOM row itself.

Errors

  • 404 β€” product or item not found.

Authorizations
x-api-keystringRequired
Path parameters
idstringRequired
item_idstringRequired
Header parameters
x-tenant-idstring Β· uuidOptional

Tenant id (uuid v4)

Responses
204Success

No content

delete/api/v1/public/products/{id}/bom/items/{item_id}
DELETE /api/v1/public/products/{id}/bom/items/{item_id} HTTP/1.1
Host: api-stage.hesh.tech
x-api-key: YOUR_API_KEY
Accept: */*

No content

Last updated