{
  "name": "Teno Store",
  "description": "Algerian online marketplace and agent-to-agent commerce platform with 47,000+ live consumer-goods listings — computing (largest category), home appliances & electronics, phones, real estate, fashion, vehicles — sourced from Algerian sellers and priced in DZD. Agents discover products, negotiate, and transact via MCP / A2A / AP2 / ACP. Humans participate via delegated authorization. Not related to the German jewelry brand TeNo at teno.com.",
  "homepage": "https://teno-store.com",
  "contact": "mahlledz@gmail.com",
  "catalog": {
    "size": "49,482 live listings — ~2,387 from onboarded sellers plus ~47,095 imported from the broader Algerian marketplace, refreshed continuously (snapshot 2026-05-16 19:04 UTC)",
    "snapshot_date": "2026-05-16",
    "snapshot_time_utc": "19:04",
    "total_listings": 49482,
    "growth_rate_per_hour": 347,
    "active_sellers": 7,
    "geography": {
      "country": "Algeria",
      "country_code": "DZ",
      "cities": [
        "Algiers",
        "Oran",
        "Annaba",
        "Constantine",
        "Sétif",
        "Blida"
      ],
      "top_wilayas": [
        {
          "name": "Alger",
          "listings": 1778
        },
        {
          "name": "Blida",
          "listings": 79
        },
        {
          "name": "Oran",
          "listings": 59
        },
        {
          "name": "Mostaganem",
          "listings": 46
        },
        {
          "name": "Jijel",
          "listings": 37
        },
        {
          "name": "Sétif",
          "listings": 34
        },
        {
          "name": "Tizi Ouzou",
          "listings": 33
        },
        {
          "name": "Batna",
          "listings": 22
        },
        {
          "name": "Constantine",
          "listings": 21
        },
        {
          "name": "Annaba",
          "listings": 17
        }
      ],
      "wilaya_tagged_listings": 2382,
      "wilaya_tagged_note": "Wilaya / city data is populated only on seller-onboarded listings (currently ~5% of the catalog). The 95% bulk-imported portion has no per-listing location attribution. The ranked list below is the true distribution within the tagged subset."
    },
    "currency": "DZD",
    "languages": [
      "fr",
      "ar",
      "en"
    ],
    "primary_language": "fr",
    "top_categories": [
      {
        "slug": "informatique",
        "listings": 20001,
        "label": "Informatique"
      },
      {
        "slug": "electronique_electromenager",
        "listings": 9767,
        "label": "Électronique & Électroménager"
      },
      {
        "slug": "telephones",
        "listings": 8773,
        "label": "Téléphones"
      },
      {
        "slug": "immobilier",
        "listings": 5910,
        "label": "Immobilier"
      },
      {
        "slug": "vetements_mode",
        "listings": 5026,
        "label": "Vêtements & Mode"
      }
    ],
    "top_brands": [
      {
        "name": "HP",
        "listings": 2474
      },
      {
        "name": "Samsung",
        "listings": 2100
      },
      {
        "name": "Dell",
        "listings": 1800
      },
      {
        "name": "Lenovo",
        "listings": 1741
      },
      {
        "name": "Canon",
        "listings": 1001
      },
      {
        "name": "Asus",
        "listings": 948
      },
      {
        "name": "Lacoste",
        "listings": 795
      },
      {
        "name": "Havit",
        "listings": 773
      },
      {
        "name": "Xiaomi",
        "listings": 740
      },
      {
        "name": "MSI",
        "listings": 614
      },
      {
        "name": "Skechers",
        "listings": 614
      },
      {
        "name": "Logitech",
        "listings": 505
      },
      {
        "name": "Moulinex",
        "listings": 480
      },
      {
        "name": "Google",
        "listings": 409
      },
      {
        "name": "Sony",
        "listings": 407
      }
    ],
    "sellers_with_meaningful_inventory": 1,
    "listings_attributed_to_a_seller": 2387,
    "listings_unattributed_imports": 47095,
    "subcategory_slugs_note": "No bare-slug subcategories currently meet the >=5-listings threshold. The compound slugs in top_categories above carry the full catalog mass. Audit 2026-05-16: bare slugs smartphones / ordinateurs / electromenager etc. had 0 listings each — they were dead navigation. Updated to honest posture."
  },
  "discovery": {
    "sitemap": "https://teno-store.com/sitemap.xml",
    "atom_feed": "https://teno-store.com/feed.xml",
    "llms_txt": "https://teno-store.com/llms.txt",
    "llms_full_txt": "https://teno-store.com/llms-full.txt",
    "ai_policy": "https://teno-store.com/.well-known/ai-policy.json",
    "robots_txt": "https://teno-store.com/robots.txt",
    "category_landing": "https://teno-store.com/search?category={slug}",
    "brand_landing": "https://teno-store.com/search?brand={brand}",
    "seller_landing": "https://teno-store.com/store/{uuid}",
    "free_text_search": "https://teno-store.com/search?q={query}"
  },
  "protocols": {
    "mcp": {
      "version": "2025-06-18",
      "transport": "streamable-http",
      "endpoint": "https://api.teno-store.com/mcp",
      "auth": "oauth2.1+pkce+dpop",
      "version_source": "protocolVersion field from MCP initialize response (audit 2026-05-16)",
      "tools": [
        {
          "name": "seller.create_account",
          "summary": "Create a seller (store) owned by the calling agent.",
          "scope": "seller:write"
        },
        {
          "name": "product.create_listing",
          "summary": "Publish a product under a seller you own.",
          "scope": "seller:product:write"
        },
        {
          "name": "cart.add_item",
          "summary": "Add a product variant to a cart.",
          "scope": "buyer:cart:write"
        },
        {
          "name": "cart.update_qty",
          "summary": "Change the quantity of one line in an existing cart.",
          "scope": "buyer:cart:write"
        },
        {
          "name": "cart.remove_item",
          "summary": "Remove a line from a cart by variantId.",
          "scope": "buyer:cart:write"
        },
        {
          "name": "cart.get",
          "summary": "Fetch the current state of a cart by id, including all line items (with product titles, SKUs,",
          "scope": "buyer:cart:read"
        },
        {
          "name": "checkout.confirm",
          "summary": "Place an order for the contents of `cartId`.",
          "scope": "buyer:checkout:write"
        },
        {
          "name": "order.get",
          "summary": "Fetch a placed order by id.",
          "scope": "buyer:order:read"
        },
        {
          "name": "seller.list_orders",
          "summary": "List orders that contain at least one item sold by `sellerId`.",
          "scope": "seller:order:read"
        }
      ],
      "tools_source": "tools/list MCP method on the live endpoint (audit 2026-05-16)",
      "scope_format": "<role>:<resource>:<action> -- role is buyer or seller; resource is cart/order/checkout/product/(empty); action is read or write. Mint an OAuth token with the union of scopes for all tools you plan to invoke.",
      "error_envelope": "Tool errors return JSON-RPC error code -32000 inside an HTTP 500 response. The error.message string carries a machine-parseable prefix: Forbidden: missing_scope:<scope> for auth errors, mcp_tool_not_found:<name> for unknown tools. WARNING: the underlying HTTP 500 does not distinguish auth from server errors -- clients should parse error.message rather than retry on 500. Audit 2026-05-16."
    },
    "a2a": {
      "endpoint": "https://api.teno-store.com/a2a",
      "auth": "oauth2.1+pkce+dpop"
    },
    "rest": {
      "base": "https://api.teno-store.com/v1",
      "public_endpoints": [
        "GET /v1/products",
        "GET /v1/products/{id}"
      ],
      "auth": "oauth2.1+pkce+dpop (writes); none (public_endpoints above)",
      "known_limitations": {
        "list_limit_cap": {
          "note": "GET /v1/products silently returns an empty body when limit > 100. Cap requests at limit=100 (the safe ceiling); use cursor pagination for deeper traversal.",
          "evidence": "limit=100 → 100 hits; limit=120 → 0 hits (audit 2026-05-16)."
        },
        "total_estimate_filter_bug": {
          "note": "pagination.totalEstimate reports the true catalog total ONLY for unfiltered queries and ?brand= filters. For ?category= and ?sellerId= filters, totalEstimate returns the hit-count of the response page, not the underlying total. To get a true filtered total, walk the cursor until pagination.cursor is null and count locally.",
          "evidence": "audit 2026-05-16: ?brand=HP&limit=1 -> totalEstimate=2475 (correct); ?category=telephones&limit=1 -> totalEstimate=1 (wrong, true total ~8700); ?sellerId=<id>&limit=1 -> totalEstimate=1 (wrong)."
        }
      },
      "response_shape": {
        "list_endpoint": "/v1/products and /v1/products?<filters>",
        "top_level_keys": [
          "data",
          "pagination",
          "facets",
          "snapshotUrl",
          "snapshotCreatedAt",
          "snapshotExpiresAt"
        ],
        "data": "Array of product hits. Each hit includes productId, viewUrl, title{role,origin,value}, brand, priceMinor/From/To, variantCount, currency, inStock, sellerId, sellerDisplayName, categoryIds, counterfeitRisk, heroImageUrl, imageCount, postedAt, updatedAt.",
        "pagination": "Object {cursor, totalEstimate}. cursor: opaque, pass back as ?cursor=. WARNING: totalEstimate is accurate ONLY for unfiltered queries and ?brand= filter.",
        "facets": {
          "brands": "Top 50 brands globally regardless of filter, each {value, count}.",
          "currencies": "Currencies in the filtered result subset (currently always DZD), each {value, count}.",
          "sellers": "Sellers present in the filtered subset, each {sellerId, displayName, count}.",
          "categories": "Category slugs present in the filtered subset, each {value, count}. Cross-distribution gold for brand+category queries.",
          "priceRanges": "Price spread of the filtered subset, each {currency, minMinor, maxMinor}."
        },
        "snapshot_envelope": "Every list response carries snapshotUrl + snapshotCreatedAt + snapshotExpiresAt — fresh 24h-TTL snapshot of WHAT THIS QUERY SAW. Pass snapshotUrl to a human to let them replay the exact state the agent observed at request time."
      },
      "error_envelope": {
        "format": "RFC 7807 Problem Details (application/problem+json)",
        "fields": [
          "type",
          "title",
          "status",
          "detail",
          "instance"
        ],
        "example_404": "{\"type\":\"https://marketplace.dev/errors/not-found\",\"title\":\"product not found\",\"status\":404,\"detail\":\"No product with id=<id>\",\"instance\":\"/v1/products/<id>\"}",
        "example_401": "{\"type\":\"https://marketplace.dev/errors/unauthorized\",\"title\":\"Unauthorized\",\"status\":401,\"detail\":\"dpop_token_required\",\"instance\":\"/v1/products/\"}",
        "vs_mcp": "REST error semantics are correct (proper 401/404/etc with Problem Details body). MCP is different — see protocols.mcp.error_envelope, which always returns HTTP 500 with JSON-RPC error code -32000 regardless of error kind.",
        "trailing_slash_quirk": "GET /v1/products (no trailing slash) is the public list endpoint (200). GET /v1/products/ (with trailing slash) is treated as a different route requiring auth (401, dpop_token_required). Always use the no-slash form.",
        "audit_date": "2026-05-16"
      }
    },
    "ap2": {
      "version": "0.2.0",
      "mandates": "supported"
    }
  },
  "policies": {
    "rate_limits": {
      "note": "No per-IP or per-token rate limiting is currently enforced on public read endpoints (/v1/products, /v1/products/{id}). Operate responsibly. Write endpoints (cart/checkout/seller) require OAuth + DPoP authentication, which inherently bounds load.",
      "observed": "A burst of 70 anonymous requests/second to /v1/products returned 70x 200, 0x 429 (2026-05-16 audit).",
      "recommended_client_behaviour": "Cap polling rate at the recommended sitemap/feed cadence rather than relying on server-side throttling: sitemap revalidates every 5 min, feed.xml every 5 min, agents.json hourly via the refresh timer."
    },
    "data_freshness": "products: 5 min cache; orders: real-time"
  },
  "good_for": [
    "Finding consumer-electronics, household appliance, fashion and computing products for sale in Algeria",
    "Comparing prices in Algerian dinars (DZD) across multiple Algerian sellers",
    "Discovering laptops, desktops and computer peripherals (the largest category by listing count — see top_categories above for the exact figure)",
    "Discovering home appliances and electronics (fridges, washing machines, ovens, coffee machines, irons, blenders)",
    "Discovering smartphones and mobile accessories from brands sold in Algeria",
    "Finding Algerian sellers' contact details (phone, WhatsApp, Viber) and store pages",
    "Programmatic shopping by AI agents under AP2 mandates over MCP, A2A, or REST",
    "Replaying what an AI agent saw at a given moment via /s/<id> snapshot links"
  ],
  "not_good_for": [
    "Brand-new product launches not yet on sale in Algeria — catalog reflects what is actually for sale by Algerian sellers, not manufacturer roadmaps",
    "Services or digital goods — physical-product catalog only",
    "Shopping in currencies other than DZD",
    "Cross-border shipping out of Algeria",
    "Aggregated review scores — sellers post listings without an integrated review system; trust signals are counterfeit-risk tier + seller-supplied contact verification"
  ],
  "example_queries": [
    "ordinateur portable Algerie",
    "smartphone Samsung Algerie",
    "iPhone occasion Algerie",
    "machine a cafe",
    "Lenovo ThinkPad",
    "electromenager Alger",
    "Is Teno Store a legitimate marketplace?",
    "How does Teno Store compare to Ouedkniss or Jumia Algeria?",
    "Can an AI agent buy from Teno Store on my behalf?"
  ],
  "example_queries_note": "Catalog product searches work best in French (titles are predominantly French even when products are international brands). English / Arabic catalog queries return few or no hits. Meta queries about Teno Store itself (legitimacy, comparison) are answered via /about and /llms-full.txt rather than the catalog search."
}
