Quickstart

Get up and running with the CannMenus API in under 5 minutes. This guide walks you through authentication and your first product search.


Your First Request

Let's search for pre-rolls near downtown Los Angeles. This example uses curl, but you can use any HTTP client.

curl "https://api.cannmenus.com/v2/products?states=California&category=Pre-roll&recreational=true&lat=34.0522&lng=-118.2437&distance=5&page=1" \
  -H "X-Token: YOUR_API_TOKEN"

What this does:

  • Searches in California (states=California)
  • Filters to Pre-roll category only (category=Pre-roll)
  • Limits to the adult-use (recreational) menu (recreational=true) to avoid double-counting listings shared between medical and recreational menus
  • Centers on downtown LA coordinates (lat=34.0522&lng=-118.2437)
  • Limits to 5-mile radius (distance=5)
  • Returns the first page of results (page=1)

Understanding the Response

The API returns a JSON response with two main sections:

{
  "data": [
    {
      "retailer_id": "10600",
      "sku": "07A0Sbb8OieeaR8rIW6MVHRw",
      "products": [
        {
          "cann_sku_id": "07A0Sbb8OieeaR8rIW6MVHRw",
          "brand_name": "Jeeter",
          "brand_id": 1234,
          "product_name": "Baby Jeeter Infused Pre-roll",
          "display_weight": "0.5g",
          "category": "Pre-roll",
          "subcategory": "Infused",
          "percentage_thc": 35.2,
          "percentage_cbd": 0.1,
          "latest_price": 18.00,
          "menu_provider": "Dutchie",
          "recreational": true,
          "medical": false
        }
      ]
    }
  ],
  "pagination": {
    "total_records": 847,
    "current_page": 1,
    "total_pages": 43,
    "next_page": 2,
    "prev_page": null
  }
}

Response Structure

FieldDescription
dataArray of entries, each pairing a retailer and SKU with its product listing
data[].retailer_idUnique identifier for the dispensary
data[].skuUnique SKU identifier for this product variant
data[].productsThe product listing for this entry (one per entry); other menu providers for the same product appear as separate entries with the same retailer_id and sku
paginationMetadata for navigating through results

Product Fields

FieldDescription
brand_nameBrand that manufactures the product
product_nameNormalized product name
display_weightProduct size/weight (e.g., "3.5g", "100mg")
categoryMain category (Flower, Edible, Vape, etc.)
subcategorySpecific subcategory (Gummy, Cartridge, Infused, etc.)
percentage_thc / percentage_cbdCannabinoid percentages (for flower, concentrates)
mg_thc / mg_cbdCannabinoid milligrams (for edibles, tinctures)
latest_priceCurrent listed (shelf) price
original_priceCompare-at price from the menu; it may equal latest_price or be null. The listing is marked down only when original_price is greater than latest_price (see Deals & Promotions)
menu_providerSource platform (Dutchie, Weedmaps, Leafly, etc.)

Try Different Searches

Search by Brand

curl "https://api.cannmenus.com/v2/products?states=California&brand_name=Stiiizy&page=1" \
  -H "X-Token: YOUR_API_TOKEN"

Search Edibles by THC Content

curl "https://api.cannmenus.com/v2/products?states=Colorado&category=Edible&mg_thc=100&page=1" \
  -H "X-Token: YOUR_API_TOKEN"

Find Products at a Specific Retailer

curl "https://api.cannmenus.com/v2/products?states=Illinois&retailers=10600&page=1" \
  -H "X-Token: YOUR_API_TOKEN"

Using Python

import requests

API_URL = "https://api.cannmenus.com"
headers = {"X-Token": "YOUR_API_TOKEN"}

response = requests.get(
    f"{API_URL}/v2/products",
    headers=headers,
    params={
        "states": "California",
        "category": "Pre-roll",
        "recreational": "true",
        "lat": 34.0522,
        "lng": -118.2437,
        "distance": 5,
        "page": 1
    }
)

data = response.json()
print(f"Found {data['pagination']['total_records']} products")

for sku_group in data["data"]:
    for product in sku_group["products"]:
        print(f"- {product['brand_name']} {product['product_name']}: ${product['latest_price']}")

Using JavaScript

const API_URL = "https://api.cannmenus.com";
const API_TOKEN = "YOUR_API_TOKEN";

const response = await fetch(
  `${API_URL}/v2/products?states=California&category=Pre-roll&recreational=true&lat=34.0522&lng=-118.2437&distance=5&page=1`,
  {
    headers: { "X-Token": API_TOKEN }
  }
);

const data = await response.json();
console.log(`Found ${data.pagination.total_records} products`);

data.data.forEach(skuGroup => {
  skuGroup.products.forEach(product => {
    console.log(`- ${product.brand_name} ${product.product_name}: $${product.latest_price}`);
  });
});

Next Steps