borkoldocs

Catalog

Redirects and sitemap

Resolve renamed product and category paths to their new address, and list every live catalog path for a sitemap.

View as Markdown

These two endpoints help a storefront keep its search ranking when the merchant renames things. Borkol speaks in storefront paths of a fixed shape: a product lives at /products/{slug} and a category at /categories/{slug}. If your storefront uses different URLs, map these paths onto your own routes.

When the merchant changes a product or category slug, Borkol records a permanent redirect from the old path to the new one. Chains collapse: renaming a to b and then b to c leaves both /products/a and /products/b pointing straight at /products/c. A path that becomes live again (a new product takes the old slug) stops redirecting.

Both endpoints use the catalog authentication: a tenant API key carrying either the catalog:read or the commerce:read scope, sent as Authorization: Bearer {api_key}, and the catalog module enabled for the store. The shared tenant rate limit of 120 requests per minute applies.

GET /v1/api/redirects

Looks up the redirect for one storefront path. Call it when a product or category request on your storefront would otherwise answer 404, and send the visitor on with the returned status code.

The lookup strips one trailing slash (/products/old-chair/ matches /products/old-chair; the root path / is left alone) and is case-sensitive. Only exact paths match: query strings are not part of the path.

Query parameters

NameTypeRequiredDescription
pathstringYesThe storefront path to look up, for example /products/old-chair. At most 512 characters.
Request
curl "https://api.borkol.com/v1/api/redirects?path=%2Fproducts%2Fold-chair" \
  -H "Authorization: Bearer {api_key}" \
  -H "Accept: application/json"
Request (JS)
const res = await fetch(
  "https://api.borkol.com/v1/api/redirects?" +
    new URLSearchParams({ path: "/products/old-chair" }),
  {
    headers: {
      Authorization: `Bearer ${apiKey}`,
      Accept: "application/json",
    },
  }
);
if (res.status === 404) {
  // No redirect: render your own not-found page.
} else {
  const { data } = await res.json();
  // Redirect the visitor to data.to_path with data.status.
}
Response
{
  "data": {
    "from_path": "/products/old-chair",
    "to_path": "/products/oak-dining-chair",
    "status": 301
  }
}

Response fields

NameTypeRequiredDescription
from_pathstringalwaysThe stored old path (without a trailing slash).
to_pathstringalwaysThe path to send the visitor to. Redirects are recorded whatever the product's or category's status, and archiving does not remove one, so to_path itself may be unavailable; check it before redirecting.
statusintegeralwaysHTTP status to redirect with. Currently always 301 (permanent).

Errors

StatusBodyCause
401{"message":"Unauthenticated."}Missing or invalid API key.
403{"message":"Invalid ability provided."}Key carries neither the catalog:read nor the commerce:read scope.
403{"error":"Module not enabled: catalog"}Tenant does not have the catalog module enabled.
403{"message":"Tenant suspended.","code":"tenant_suspended"}Tenant account is suspended.
404{"message":"..."}No redirect exists for this path.
422{"message":"...","errors":{"path":["..."]}}path is missing, not a string, or longer than 512 characters.
429{"message":"Too Many Attempts."}Rate limit of 120 requests per minute exceeded.

GET /v1/api/sitemap

Lists every live catalog path, ready to render as a sitemap.xml: all products with status active and all categories that are active. Products come first, then categories, each group ordered by slug. The response is not paginated.

Parameters

None.

Request
curl "https://api.borkol.com/v1/api/sitemap" \
  -H "Authorization: Bearer {api_key}" \
  -H "Accept: application/json"
Response
{
  "data": [
    {
      "type": "product",
      "path": "/products/oak-dining-chair",
      "lastmod": "2026-10-11T09:14:33+00:00"
    },
    {
      "type": "category",
      "path": "/categories/chairs",
      "lastmod": "2026-10-02T15:20:11+00:00"
    }
  ]
}

Response fields

Each entry in data:

NameTypeRequiredDescription
typestringalwaysproduct or category.
pathstringalwaysStorefront path: /products/{slug} or /categories/{slug}.
lastmodstring (ISO 8601) or nullalwaysWhen the product or category was last updated.

Errors

StatusBodyCause
401{"message":"Unauthenticated."}Missing or invalid API key.
403{"message":"Invalid ability provided."}Key carries neither the catalog:read nor the commerce:read scope.
403{"error":"Module not enabled: catalog"}Tenant does not have the catalog module enabled.
403{"message":"Tenant suspended.","code":"tenant_suspended"}Tenant account is suspended.
429{"message":"Too Many Attempts."}Rate limit of 120 requests per minute exceeded.