Categories

This domain covers three related but distinct layers:

  1. Fenicia category tree — your catalog's own taxonomy.
  2. Automatic classification — endpoints that, given a product title/description, suggest a category or tax code using AI: SAT (CFDI), T1/Sears/Sanborns, Walmart, and TikTok Shop each have their own classifier.
  3. Category mappings — the persisted relationship between a Fenicia category and its equivalent in a specific marketplace, with usage metrics and an approval flow.

Base path different from /products

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

No single envelope

Just like the rest of the Products API, there is no uniform {data, meta} envelope here — each endpoint returns its own shape. We document the actual shape of each one; where it wasn't verified field by field in the audit, we flag it explicitly.

Authentication: Authorization: Bearer fkapi_..., except for the one endpoint explicitly marked as public below (GET /categories/sat/search). The rest require a resolved tenantId (401 if missing) and, on most routes, a specific RBAC permission — see the note on the four exceptions below.

Returns the complete category tree for your tenant (also accessible at GET /categories, without the suffix)

localestring

Language of the labels. Default 'es'.

200
[
  {
    "id": "cat-ropa",
    "name": "Ropa",
    "children": [
      { "id": "cat-ropa-playeras", "name": "Playeras", "children": [] }
    ]
  }
]
500
{ "success": false, "error": "Failed to load category tree", "code": "INTERNAL_ERROR" }

Required permission: products:read

Searches your tenant's categories by text

qstringrequired

Search term.

localestring

Language of the labels.

limitnumber

Result limit. Default 20.

400
{ "success": false, "error": "Search query is required", "code": "MISSING_PARAMETER" }

Required permission: products:read

SAT (CFDI) classification

Suggests the appropriate SAT code (product/service key) for electronic invoicing based on a product's title and data.

Searches SAT product/service keys by text

qstringrequired

Search term.

limitnumber

Result limit.

400
{ "success": false, "error": "Search query is required", "code": "MISSING_PARAMETER" }

Public endpoint — no authentication

Unlike all the other endpoints on this page (and the API in general), GET /categories/sat/search does not require Authorization. It's the only public endpoint in this domain, consistent with the fact that the SAT catalog is public information from the Mexican SAT catalog, not your tenant's data.

Suggests the SAT code for a product based on its title/data

titlestringrequired

Product title.

{ "title": "Camisa de algodón manga larga" }
200
{
  "satCode": "53101600",
  "description": "Camisas",
  "confidence": 0.92,
  "method": "ai",
  "processingTimeMs": 340
}
400
{ "code": "MISSING_PARAMETER", "message": "Product title is required" }

Required permission: products:read

Side effect: emits an event

Every successful call to POST /categories/sat/suggest emits a sat-categorization event to EventBridge — useful if you need to react to SAT classifications from another system, but it also means the endpoint isn't a purely read operation despite not persisting visible changes on the product.

SAT cache and classification metrics

200
{
  "success": true,
  "data": {
    "service": {
      "version": "2.7.0",
      "architecture": "global_rag",
      "description": "Global RAG - works for ANY product from ANY industry"
    },
    "cache": {
      "enabled": true,
      "size": 128,
      "maxSize": 5000,
      "hitRate": "42.3%"
    },
    "metrics": {
      "enabled": true,
      "classification": {
        "total": 340,
        "successful": 332,
        "failed": 8,
        "avgConfidence": "88.5%",
        "avgProcessingTimeMs": 410
      },
      "methods": {
        "globalRagLlm": 210,
        "globalRagOnly": 122
      },
      "tokens": {
        "input": 42000,
        "output": 21000,
        "estimatedCostUsd": "$0.6300"
      }
    }
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:read

Resets SAT metrics and, optionally, clears the classification cache

clearCacheboolean

If `true`, also clears the SAT classification cache.

{ "clearCache": true }
200
{ "success": true, "message": "Stats reset" }

Required permission: settings:manage

T1 / Sears / Sanborns classification

Classifies a product in T1's taxonomy (T1/Sears/Sanborns channel)

titlestringrequired

Product title and other data relevant to classification.

{ "title": "Camisa de algodón manga larga" }
200
{
  "t1CategoryId": "T1-12345",
  "t1CategoryPath": "Ropa > Playeras",
  "t1CategoryName": "Playeras",
  "segment": "ropa",
  "segmentName": "Ropa y Accesorios",
  "confidence": 0.91,
  "method": "global_rag_llm",
  "processingTimeMs": 480
}
400
{ "code": "MISSING_PARAMETER", "message": "Product title is required" }

Required permission: products:read

Side effect: emits an event

Emits a t1-categorization event to EventBridge on every successful classification.

T1 classification metrics

200
{
  "success": true,
  "data": {
    "service": {
      "version": "2.6.0",
      "architecture": "global_rag",
      "description": "Global RAG - works for ANY product from ANY industry"
    },
    "cache": {
      "enabled": true,
      "size": 96,
      "maxSize": 5000,
      "hitRate": "38.1%"
    },
    "metrics": {
      "enabled": true,
      "classification": {
        "total": 214,
        "successful": 208,
        "failed": 6,
        "avgConfidence": "86.2%",
        "avgProcessingTimeMs": 465
      },
      "methods": {
        "globalRagLlm": 150,
        "globalRagOnly": 58
      },
      "tokens": {
        "input": 30000,
        "output": 15000,
        "estimatedCostUsd": "$0.4500"
      }
    }
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:read

Resets T1 metrics, optionally clearing the cache

clearCacheboolean

Clears the T1 classification cache.

{ "clearCache": true }
200
{ "success": true, "message": "Metrics reset, cache cleared" }
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:manage

Walmart categories and classification

Returns the complete Walmart category catalog (79 categories)

200
{
  "total": 79,
  "categories": [
    { "id": "4044", "name": "Athletic Shoes", "segment": "shoes", "segmentName": "Calzado" },
    { "id": "5438", "name": "Shirts", "segment": "clothing", "segmentName": "Ropa y Accesorios" }
  ]
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: products:read

Searches the Walmart category catalog

qstringrequired

Search term.

limitnumber

Result limit.

400
{ "success": false, "error": "Search query is required", "code": "MISSING_PARAMETER" }

Required permission: products:read

Classifies a product in Walmart's taxonomy (classification engine v5)

titlestringrequired

Product title and other relevant data.

{ "title": "Tenis Nike Air Max 270" }
200
{
  "walmartCategoryId": "4044",
  "walmartCategoryName": "Athletic Shoes",
  "segment": "shoes",
  "segmentName": "Calzado",
  "visibleSectionMX": "Tenis deportivos",
  "productTypeName": "Athletic Shoes",
  "productTypeGroup": "Shoes",
  "category": "Clothing, Shoes & Accessories",
  "fullPath": "Clothing, Shoes & Accessories > Shoes > Athletic Shoes",
  "taxonomyVersion": "v5.0",
  "categoryStatus": "active",
  "requiredAttributes": ["brand", "size", "color"],
  "aiInferableAttributes": ["brand", "color"],
  "confidence": 0.89,
  "method": "global_rag_llm",
  "processingTimeMs": 520
}
400
{ "code": "MISSING_PARAMETER", "message": "Product title is required" }

Required permission: products:read

Side effect: emits an event

Emits an internal categorization event to EventBridge on every successful classification.

Resolves, with AI, the attribute values required by a Walmart category for a given product

categoryIdstringrequired

ID of the target Walmart category.

titlestringrequired

Product title.

descriptionstring

Product description.

brandstring

Brand.

categorystring

Fenicia category of the product, as additional context.

existingAttributesobject

Already-known attributes, to avoid resolving them again.

resolveVariantAttributestring

Name of the variant attribute to resolve specifically (for example, size or color).

allowedValuesarray

Restricts resolution to this set of allowed values.

attributeTypestring

Type of attribute to resolve.

{
  "categoryId": "4044",
  "title": "Playera de algodón manga larga",
  "description": "Playera 100% algodón, cuello redondo",
  "brand": "Fenicia Basics",
  "category": "Ropa > Playeras"
}
200Standard mode: resolves every attribute required by the category
{
  "success": true,
  "categoryId": "4044",
  "resolvedAttributes": {
    "brand": { "name": "brand", "value": "Fenicia Basics", "confidence": 0.95, "source": "existing" },
    "color": { "name": "color", "value": "Azul", "confidence": 0.8, "source": "ai_inferred" }
  },
  "missingAttributes": ["size"],
  "processingTimeMs": 610
}
200Variant attribute mode (resolveVariantAttribute=true)
{
  "success": true,
  "categoryId": "4044",
  "variantAttributeName": "Talla",
  "confidence": 0.93,
  "reasoning": "El producto tiene variantes por talla numérica.",
  "processingTimeMs": 340
}
400
{ "code": "MISSING_PARAMETER", "message": "categoryId is required" }

Required permission: products:read

resolvedAttributes is an object, not an array

Unlike POST /categories/generic/resolve-attributes and POST /categories/mercadolibre/resolve-attributes (which return resolvedAttributes as an array), here it is an object of attribute→detail pairs (Record<string, WalmartResolvedAttribute>), indexed by attribute name. source is one of ai_inferred, default, or existing.

Walmart classification metrics

200
{
  "success": true,
  "data": {
    "service": {
      "version": "2.8.0",
      "architecture": "global_rag",
      "description": "Global RAG - 79 Walmart categories",
      "totalCategories": 79
    },
    "cache": {
      "enabled": true,
      "size": 210,
      "maxSize": 5000,
      "hitRate": "51.4%"
    },
    "metrics": {
      "enabled": true,
      "classification": {
        "total": 512,
        "successful": 498,
        "failed": 14,
        "avgConfidence": "90.1%",
        "avgProcessingTimeMs": 530
      },
      "methods": {
        "globalRagLlm": 340,
        "globalRagOnly": 158
      },
      "tokens": {
        "input": 68000,
        "output": 34000,
        "estimatedCostUsd": "$1.0200"
      }
    }
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:read

Resets Walmart classification metrics

clearCacheboolean

If `true`, also clears the Walmart classification cache.

{ "clearCache": true }
200
{ "success": true, "message": "Metrics reset, cache cleared" }
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:manage

TikTok Shop classification

Classifies a product in TikTok Shop's taxonomy

titlestringrequired

Product title and other relevant data.

{ "title": "Blusa floral manga corta" }
200
{
  "tiktokCategoryId": "601001",
  "tiktokCategoryPath": "Ropa > Blusas y Camisas",
  "tiktokCategoryName": "Blusas y Camisas",
  "segment": "ropa",
  "segmentName": "Ropa y Accesorios",
  "confidence": 0.87,
  "method": "global_rag_llm",
  "processingTimeMs": 455
}
400
{ "code": "MISSING_PARAMETER", "message": "Product title is required" }

Required permission: products:read

Side effect: emits an event

Emits an internal categorization event to EventBridge on every successful classification.

TikTok Shop classification metrics

200
{
  "success": true,
  "data": {
    "service": {
      "version": "2.12.4",
      "architecture": "global_rag",
      "description": "Global RAG - ~2,700 TikTok Shop categories",
      "totalCategories": 2723
    },
    "cache": {
      "enabled": true,
      "size": 74,
      "maxSize": 5000,
      "hitRate": "29.6%"
    },
    "metrics": {
      "enabled": true,
      "classification": {
        "total": 130,
        "successful": 122,
        "failed": 8,
        "avgConfidence": "83.4%",
        "avgProcessingTimeMs": 490
      },
      "methods": {
        "globalRagLlm": 95,
        "globalRagOnly": 27
      },
      "tokens": {
        "input": 19000,
        "output": 9500,
        "estimatedCostUsd": "$0.2850"
      }
    }
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:read

Resets TikTok Shop classification metrics

clearCacheboolean

If `true`, also clears the TikTok Shop classification cache.

{ "clearCache": true }
200
{ "success": true, "message": "Metrics reset, cache cleared" }
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:manage

Unified classification and cache

No explicit RBAC permission

The four endpoints in this section do not call requirePermission() in the audited source code — unlike practically every other route in this domain, they only validate that a resolved tenantId exists (a valid authenticated session), without requiring an additional permission. This isn't an error in this documentation: it's the actual confirmed behavior in the code. If your organization needs to restrict these operations by role, report it to support.

Classifies a product by trying the available classification strategies in cascade (up to 5), until obtaining a result

titlestringrequired

Product title.

descriptionstring

Product description.

brandstring

Brand.

feniciaCategoryIdstring

Already-known Fenicia category of the product, as context.

skustring

Product SKU.

categorystring

Additional context category.

{
  "title": "Playera de algodón manga larga",
  "description": "Playera 100% algodón, cuello redondo",
  "brand": "Fenicia Basics",
  "feniciaCategoryId": "cat-ropa-playeras",
  "sku": "PLA-001",
  "category": "Ropa > Playeras"
}
401
{ "success": false, "error": "Tenant ID required", "code": "UNAUTHORIZED" }
400
{ "success": false, "error": "Product title is required", "code": "MISSING_PARAMETER" }

Required permission: none explicit — authenticated session with resolved tenantId only.

Looks up an already-cached classification result, without re-running the classifier

titlestringrequired

Product title.

descriptionstring

Product description.

brandstring

Brand.

marketplacestring

Restricts the cache lookup to a specific marketplace.

{
  "title": "Playera de algodón manga larga",
  "description": "Playera 100% algodón, cuello redondo",
  "brand": "Fenicia Basics",
  "marketplace": "walmart"
}
200Found in cache
{
  "success": true,
  "data": {
    "found": true,
    "classification": {
      "marketplace": "walmart",
      "categoryId": "4044",
      "categoryPath": "Clothing, Shoes & Accessories > Shoes > Athletic Shoes",
      "confidence": 0.89,
      "method": "global_rag_llm",
      "classifiedAt": "2026-07-10T15:22:00.000Z"
    }
  }
}
200No result in cache
{ "success": true, "data": { "found": false } }
401
{ "success": false, "error": "Tenant ID required", "code": "UNAUTHORIZED" }
400
{ "success": false, "error": "Product title is required", "code": "MISSING_PARAMETER" }

Required permission: none explicit — authenticated session only.

Classification cache statistics

200
{
  "success": true,
  "data": {
    "service": {
      "version": "2.13.0",
      "description": "Persistent classification cache with confidence-based TTL"
    },
    "stats": {
      "totalEntries": 812,
      "totalHits": 2140,
      "avgHitCount": 2.64,
      "methodDistribution": { "binding": 40, "cache": 0, "mapping": 120, "rag": 380, "rag_llm": 272 },
      "marketplaceDistribution": { "walmart": 310, "mercadolibre": 260, "tiktok": 180 },
      "publicationSuccessRate": 0.94
    }
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: none explicit — authenticated session only.

Invalidates classification cache entries

feniciaCategoryIdstring

Invalidates only the entries associated with this Fenicia category. If omitted, applies the `cleanup` criterion.

cleanupboolean

Runs a general cleanup of expired/stale entries.

{ "feniciaCategoryId": "cat-ropa-playeras", "cleanup": false }
200
{ "invalidatedCount": 12, "cleanedCount": 3 }

Required permission: none explicit — authenticated session only.

Category mappings by marketplace

A mapping relates a Fenicia category to its equivalent in a marketplace, with usage metrics (success rate) and an approval flow for automatically generated mappings.

Looks up the existing mapping between a Fenicia category and a marketplace

feniciaCategoryIdstringrequired

Fenicia category ID.

marketplacestringrequired

Target marketplace.

{ "feniciaCategoryId": "cat-ropa-playeras", "marketplace": "walmart" }
200
{
  "found": true,
  "mapping": {
    "feniciaCategoryId": "cat-ropa-playeras",
    "marketplace": "walmart",
    "marketplaceCategoryId": "5438",
    "marketplaceCategoryName": "Shirts",
    "confidence": 0.95
  }
}
200No existing mapping
{ "found": false }
400
{ "success": false, "error": "feniciaCategoryId and marketplace are required", "code": "MISSING_PARAMETER" }

Required permission: products:read

Creates or updates the mapping between a Fenicia category and a marketplace

feniciaCategoryIdstringrequired

Fenicia category ID.

feniciaCategoryPathstring

Readable path of the Fenicia category.

marketplacestringrequired

Target marketplace.

marketplaceCategoryIdstringrequired

Category ID in the marketplace.

marketplaceCategoryNamestring

Readable name of the category in the marketplace.

mappingTypestring

Mapping type (for example, manual vs. AI-generated).

confidencenumber

Mapping confidence, if it was automatically generated.

sourcestring

Origin of the mapping.

attributeMappingsobject

Associated attribute mapping.

{
  "feniciaCategoryId": "cat-ropa-playeras",
  "feniciaCategoryPath": "Ropa > Playeras",
  "marketplace": "walmart",
  "marketplaceCategoryId": "5438",
  "marketplaceCategoryName": "Shirts",
  "mappingType": "ai_inferred",
  "confidence": 0.95,
  "source": "ai",
  "attributeMappings": { "color": "COLOR_ATTR", "size": "SIZE_ATTR" }
}
400
{ "success": false, "error": "feniciaCategoryId, marketplace, and marketplaceCategoryId are required", "code": "MISSING_PARAMETER" }

Required permission: products:manage

Records the result of using a mapping (for example, after exporting a product with that category) and returns its updated metrics

feniciaCategoryIdstringrequired

Fenicia category ID.

marketplacestringrequired

Marketplace.

successboolean

Whether the mapping usage was successful.

errorCodestring

Error code, if `success` is `false`.

errorMessagestring

Error message.

{ "feniciaCategoryId": "cat-ropa-playeras", "marketplace": "walmart", "success": true }
200
{ "status": "active", "usageCount": 34, "successRate": 0.97 }
200No prior usage record
null

Required permission: products:read

Lists mappings pending approval

marketplacestring

Filters by marketplace.

limitnumber

Result limit. Default 50.

200
{
  "success": true,
  "data": {
    "total": 2,
    "mappings": [
      {
        "feniciaCategoryId": "cat-ropa-playeras",
        "marketplace": "walmart",
        "marketplaceCategoryId": "5438",
        "marketplaceCategoryPath": "Shirts",
        "mappingType": "ai_inferred",
        "confidence": 0.82,
        "source": "ai",
        "status": "pending",
        "stats": { "usageCount": 6, "successRate": 0.83 }
      }
    ]
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:read

Approves or rejects a pending mapping

feniciaCategoryIdstringrequired

Fenicia category ID of the mapping.

marketplacestringrequired

Marketplace of the mapping.

approvedbooleanrequired

`true` to approve, `false` to reject.

rejectionReasonstring

Reason for rejection, when `approved` is `false`.

{ "feniciaCategoryId": "cat-ropa-playeras", "marketplace": "walmart", "approved": true }
200
{
  "success": true,
  "data": {
    "feniciaCategoryId": "cat-ropa-playeras",
    "marketplace": "walmart",
    "marketplaceCategoryId": "5438",
    "marketplaceCategoryPath": "Shirts",
    "mappingType": "ai_inferred",
    "confidence": 0.82,
    "source": "ai",
    "status": "validated",
    "stats": { "usageCount": 6, "successRate": 0.83 },
    "validatedAt": "2026-07-21T18:40:00.000Z",
    "validatedBy": "admin"
  }
}
400
{ "success": false, "error": "feniciaCategoryId, marketplace, and approved are required", "code": "MISSING_PARAMETER" }

Required permission: settings:manage

Aggregated mapping statistics

marketplacestring

Restricts the statistics to a marketplace.

200
{
  "success": true,
  "data": {
    "service": {
      "version": "2.13.0",
      "description": "Bidirectional Fenicia ↔ Marketplace category mappings"
    },
    "stats": {
      "totalMappings": 634,
      "byStatus": { "pending": 40, "auto_approved": 210, "validated": 350, "flagged": 12, "rejected": 22 },
      "bySource": { "manual": 100, "ai": 480, "community": 0, "api": 40, "publication_feedback": 14 },
      "avgConfidence": 0.91,
      "avgSuccessRate": 0.96,
      "totalUsage": 5820
    }
  }
}
500
{ "success": false, "error": "Unknown error", "code": "INTERNAL_ERROR" }

Required permission: settings:read

AI attribute resolution (multi-marketplace)

In addition to POST /categories/walmart/resolve-attributes (documented above), there are two variants: a generic multi-marketplace one and a MercadoLibre-specific one.

Resolves, with AI, attributes required by a category from any supported marketplace, based on a list of requirements

requirementsarrayrequired

List of attribute requirements to resolve.

productobjectrequired

Product data; `product.title` is required.

channelTypestring

Channel/marketplace type, as additional context.

localestring

Language for the resolution.

{
  "requirements": [
    {
      "id": "MATERIAL_SUELA",
      "name": "Material de la suela",
      "type": "select",
      "required": true,
      "allowedValues": [{ "id": "GOMA", "name": "Goma" }, { "id": "CUERO", "name": "Cuero" }]
    }
  ],
  "product": {
    "title": "Tenis casuales para hombre",
    "brand": "Fenicia Basics",
    "attributes": [{ "name": "suela", "value": "Goma" }]
  },
  "channelType": "tiktok",
  "locale": "es"
}
200
{
  "success": true,
  "resolvedAttributes": [
    { "id": "MATERIAL_SUELA", "value": "Goma", "confidence": 0.98, "source": "exact_match" }
  ],
  "unresolvedAttributes": [],
  "processingTimeMs": 210
}
400
{ "code": "MISSING_PARAMETER", "message": "requirements array is required" }

Required permission: products:read

Resolves attributes required by a MercadoLibre category; variant attributes (size/color) are derived from the product's actual variants, not guessed with AI

requirementsarrayrequired

List of attribute requirements.

productobjectrequired

Product data; `product.title` is required.

categoryIdstringrequired

MercadoLibre category ID.

categoryNamestring

Category name.

hasVariantsboolean

Whether the product has variants.

variantAxesarray

Product's variant axes (for example, size, color).

{
  "product": {
    "title": "Tenis Nike Air Max",
    "brand": "Nike",
    "attributes": [{ "name": "material", "value": "Sintético" }]
  },
  "requirements": [
    { "id": "BRAND", "name": "Marca", "type": "text", "required": true, "sourceField": "brand" }
  ],
  "categoryId": "MLM1234",
  "categoryName": "Tenis",
  "hasVariants": true,
  "variantAxes": ["Talla", "Color"]
}
200
{
  "success": true,
  "resolvedAttributes": [
    { "attributeId": "BRAND", "value": "Nike", "valueType": "value_name", "confidence": 0.99, "source": "product_field" }
  ],
  "unresolvedAttributes": [],
  "variantAttributes": [
    {
      "attributeId": "TALLA",
      "name": "Talla",
      "reason": "allows_variations",
      "valueType": "value_id",
      "resolvedByVariant": [
        { "sku": "TENIS-001-28", "feniciaValue": "28", "mlValue": { "id": "28MX", "name": "28 MX" }, "confidence": 1, "matched": true }
      ]
    }
  ],
  "stats": {
    "totalAttributes": 2,
    "resolvedCount": 1,
    "variantCount": 1,
    "unresolvedCount": 0,
    "processingTimeMs": 380,
    "aiInferredCount": 0
  }
}
400
{ "code": "MISSING_PARAMETER", "message": "requirements array is required" }

Required permission: products:read

variantAttributes: derived from real data, not AI

Unlike the rest of the attribute resolution endpoints, this endpoint's response includes a variantAttributes field built from the product's actual options/variants (for example, SIZE/COLOR) — it isn't an AI inference, and it includes resolvedByVariant[] with the value already matched by SKU. The rest of the resolved attributes (resolvedAttributes[]) can indeed come from the AI engine (source: 'ai_inferred'), in addition to exact_match, alias_match, default, or product_field.

Example — suggest a product's SAT code

curl -X POST https://api.fenicia.io/categories/sat/suggest \
  -H "Authorization: Bearer fkapi_tu_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Camisa de algodón manga larga" }'

Errors

CodeStatusDescription
MISSING_PARAMETER400A required parameter is missing (q, title, etc.).
not-found404Unknown route. The response includes availableRoutes with the full list of routes supported by this lambda.
auth:invalid_token401The API key is invalid, has been revoked, or the tenant couldn't be resolved.
auth:permission_denied403The API key doesn't have the required permission.

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

CORS: no PUT/DELETE

This domain only allows GET, POST, and OPTIONS at the CORS level — there are no PUT/DELETE operations on /categories/* (consistent with the fact that all write routes in this domain are POST, never PUT/DELETE).

Next steps