Collections

Collections group products for commercial purposes — storefronts, promotions, editorial curation — independently of taxonomic categorization (Categories). They support hierarchy (a collection can have child collections via parentId) and manual ordering of their products.

Base path different from /products

This domain lives under /collections, its own API Gateway resource (fenicia-collections-{stage}) — not a sub-resource of /products. Use https://api.fenicia.io/collections/... directly, not /products/collections/....

Authentication: same as the rest of the API — Authorization: Bearer fkapi_..., 401 if the tenant can't be resolved, 403 if the tenant is suspended. All write and read operations additionally require the corresponding collections:* permission.

List and query collections

Lists collections with pagination and filters

pagenumber

Page.

limitnumber

Items per page.

searchstring

Text search by name.

statusstring

Filters by collection status.

collectionTypestring

Filters by collection type.

scopestring

Filters by collection scope.

purposestring

Filters by collection purpose.

parentIdstring

Filters by parent collection.

200
{
  "items": [
    {
      "id": "65f5a1b2c4d5e6f7a8b9c1a1",
      "name": { "value": "Novedades verano" },
      "status": "active",
      "collectionType": "manual",
      "parentId": null,
      "sortOrder": 0
    }
  ],
  "total": 1,
  "page": 0,
  "limit": 20
}

Required permission: collections:read

Response shape not verified field by field

The filter parameters are confirmed against the source code (they're the same fields supported by CollectionsService.search). The exact pagination envelope (key names) was not verified field by field — confirm it against a real response before depending on its exact shape.

Returns the complete collections tree, or the subtree of a given root

rootIdstring

ID of the subtree's root collection. If omitted, returns the complete tree.

200
[
  {
    "id": "65f5a1b2c4d5e6f7a8b9c1a1",
    "name": { "value": "Novedades verano" },
    "parentId": null,
    "children": [
      { "id": "65f5a1b2c4d5e6f7a8b9c1a2", "name": { "value": "Playeras" }, "parentId": "65f5a1b2c4d5e6f7a8b9c1a1", "children": [] }
    ]
  }
]

Required permission: collections:read

Gets a collection by ID

idstringrequired

Collection ID.

200
{
  "id": "65f5a1b2c4d5e6f7a8b9c1a1",
  "name": { "value": "Novedades verano" },
  "status": "active",
  "collectionType": "manual",
  "scope": "storefront",
  "purpose": "merchandising",
  "parentId": null,
  "sortOrder": 0
}
404
{ "code": "not-found", "message": "Collection not found" }

Required permission: collections:read

Lists the direct child collections of a collection

idstringrequired

Parent collection ID.

200
[
  { "id": "65f5a1b2c4d5e6f7a8b9c1a2", "name": { "value": "Playeras" }, "parentId": "65f5a1b2c4d5e6f7a8b9c1a1" }
]

Required permission: collections:read

Create, update, and move collections

Creates a collection

nameobjectrequired

{ value: string } — collection name. It's the only field confirmed as required.

{ "name": { "value": "Novedades verano" } }
201
{
  "id": "65f5a1b2c4d5e6f7a8b9c1a1",
  "name": { "value": "Novedades verano" },
  "status": "active",
  "sortOrder": 0
}
400
{ "code": "bad-request", "message": "Collection name is required" }

Required permission: collections:create

Updates a collection (partial)

idstringrequired

Collection ID.

{ "name": { "value": "Novedades otoño" }, "status": "active" }
404
{ "code": "not-found", "message": "Collection not found" }
400
{ "code": "bad-request", "message": "Request body is required" }

Required permission: collections:update

Moves a collection to another parent and/or reorders its position among siblings

parentIdstringrequired

ID of the new parent collection. Accepts explicit `null` to move the collection to the root level.

sortOrdernumberrequired

New position among sibling collections.

{ "parentId": null, "sortOrder": 2 }
404
{ "code": "not-found", "message": "Collection not found" }
400
{ "code": "bad-request", "message": "Request body is required" }

Required permission: collections:update

Products within a collection

Adds products to a collection

idstringrequired

Collection ID.

skusarrayrequired

Array of SKUs to add.

{ "skus": ["CAM-ROJO-M", "PAN-AZUL-32"] }
200
{ "success": true }
400
{ "code": "bad-request", "message": "skus array is required" }

Required permission: collections:update

Manually reorders the products within a collection

idstringrequired

Collection ID.

skuOrderarrayrequired

Array of SKUs in the desired order.

{ "skuOrder": ["PAN-AZUL-32", "CAM-ROJO-M"] }
200
{ "success": true }
400
{ "code": "bad-request", "message": "skuOrder array is required" }

Required permission: collections:update

Removes products from a collection

idstringrequired

Collection ID.

skusarrayrequired

Array of SKUs to remove.

200
{ "success": true }
400
{ "code": "bad-request", "message": "skus array is required" }

Required permission: collections:update

Delete a collection

Deletes a collection

idstringrequired

Collection ID.

200
{ "success": true }
404
{ "code": "not-found", "message": "Collection not found" }
400
{ "code": "has-children", "message": "Cannot delete collection with children. Delete children first or move them." }

Required permission: collections:delete

Can't delete a collection with children

If the collection has child collections (parentId pointing to it), the deletion is rejected with 400 has-children. Move or delete the child collections first.

Example — add products to a collection

curl -X POST https://api.fenicia.io/collections/65f5a1b2c4d5e6f7a8b9c1a1/products \
  -H "Authorization: Bearer fkapi_tu_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "skus": ["CAM-ROJO-M", "PAN-AZUL-32"] }'

Errors

CodeStatusDescription
bad-request400Missing body, missing name.value on create, or skus/skuOrder is not an array.
not-found404No collection with that ID exists in your tenant.
has-children400Cannot delete a collection that has child collections.
permission-denied403The API key doesn't have the required permission. The response includes requiredPermission with the exact permission that was missing.
method-not-allowed405The HTTP method isn't supported for that route.
internal-error500Unhandled server error.
auth:invalid_token401The API key is invalid or has been revoked, or the tenant couldn't be resolved.

See the full error catalog for the rest of the possible codes.

Permissions independent from products

collections:* is its own permission group (read, create, update, delete), separate from products:*. A role with read access to products doesn't necessarily have read access to collections — check both if your integration touches both domains.

Next steps