Nabis APInabis.com ↗
Access Nabis cannabis wholesale data: CA and NY inventory, SKU lookups, retailers, orders, warehouses, and invoices via 9 structured endpoints.
What is the Nabis API?
The Nabis API exposes 9 endpoints covering the Nabis cannabis wholesale platform, including paginated inventory for California and New York, licensed retailer listings, wholesale orders, warehouse locations, and invoice records. The get_inventory_by_sku_ca endpoint returns product details by SKU code, while get_nabis_days_off exposes non-delivery dates that affect fulfillment scheduling — all scoped to licensed business accounts authenticated with a valid access token.
curl -X GET 'https://api.parse.bot/scraper/05fa71df-cbde-47ae-8e29-945e53b3144b/get_inventory_ca' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace nabis-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
Nabis Marketplace API Client
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, Dict, Any, List
class ParseClient:
"""Client for interacting with the Nabis Marketplace API through Parse."""
def __init__(self, api_key: Optional[str] = None):
"""
Initialize the Parse API client.
Args:
api_key: Parse API key. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "a82d4854-b40f-40a1-8073-71cb657b931e"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key required. Pass as argument or set PARSE_API_KEY env var.")
def _call(
self,
endpoint: str,
method: str = "POST",
**params
) -> Dict[str, Any]:
"""
Make a request to the Parse API.
Args:
endpoint: The endpoint name (e.g., 'get_inventory_ca')
method: HTTP method ('GET' or 'POST')
**params: Parameters to send with the request
Returns:
Response JSON as dictionary
Raises:
requests.RequestException: If the API call fails
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method == "GET":
response = requests.get(url, headers=headers, params=params)
elif method == "POST":
response = requests.post(url, headers=headers, json=params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def get_inventory_ca(
self,
access_token: str,
limit: int = 500,
page: int = 1
) -> Dict[str, Any]:
"""
Retrieve paginated list of cannabis inventory/products available in California.
Args:
access_token: Nabis x-nabis-access-token header value
limit: Max results per page (1-500, default 500)
page: Page number (default 1)
Returns:
Dictionary with 'items' and 'total' keys
"""
return self._call(
"get_inventory_ca",
method="GET",
access_token=access_token,
limit=limit,
page=page
)
def get_inventory_by_sku_ca(
self,
access_token: str,
sku_code: str
) -> Dict[str, Any]:
"""
Retrieve detailed inventory/product information for a specific SKU in California.
Args:
access_token: Nabis x-nabis-access-token header value
sku_code: SKU code of the product
Returns:
Dictionary with product details including skuCode and skuName
"""
return self._call(
"get_inventory_by_sku_ca",
method="GET",
access_token=access_token,
sku_code=sku_code
)
def get_inventory_ny(
self,
access_token: str,
limit: int = 500,
page: int = 1
) -> Dict[str, Any]:
"""
Retrieve paginated list of cannabis inventory/products available in New York.
Args:
access_token: Nabis x-nabis-access-token header value
limit: Max results per page (1-500, default 500)
page: Page number (default 1)
Returns:
Dictionary with 'items' and 'total' keys
"""
return self._call(
"get_inventory_ny",
method="GET",
access_token=access_token,
limit=limit,
page=page
)
def get_inventory_by_product_code_ny(
self,
access_token: str,
item_code: str
) -> Dict[str, Any]:
"""
Retrieve detailed inventory/product information for a specific product in New York.
Args:
access_token: Nabis x-nabis-access-token header value
item_code: Item code of the product in NY
Returns:
Dictionary with product details including itemCode and skuName
"""
return self._call(
"get_inventory_by_product_code_ny",
method="GET",
access_token=access_token,
item_code=item_code
)
def get_retailers(
self,
access_token: str,
limit: int = 500,
page: int = 1
) -> Dict[str, Any]:
"""
Retrieve list of licensed dispensary retailers on the Nabis platform.
Args:
access_token: Nabis x-nabis-access-token header value
limit: Max results per page (default 500)
page: Page number (default 1)
Returns:
Dictionary with 'items' array of retailers
"""
return self._call(
"get_retailers",
method="GET",
access_token=access_token,
limit=limit,
page=page
)
def get_orders(
self,
access_token: str,
limit: int = 500,
page: int = 1
) -> Dict[str, Any]:
"""
Retrieve paginated list of wholesale orders placed through the Nabis platform.
Args:
access_token: Nabis x-nabis-access-token header value
limit: Max results per page (default 500)
page: Page number (default 1)
Returns:
Dictionary with 'items' array of orders
"""
return self._call(
"get_orders",
method="GET",
access_token=access_token,
limit=limit,
page=page
)
def get_warehouses(
self,
access_token: str,
limit: int = 500,
page: int = 1
) -> Dict[str, Any]:
"""
Retrieve list of Nabis warehouse locations.
Args:
access_token: Nabis x-nabis-access-token header value
limit: Max results per page (default 500)
page: Page number (default 1)
Returns:
Dictionary with 'items' array of warehouses
"""
return self._call(
"get_warehouses",
method="GET",
access_token=access_token,
limit=limit,
page=page
)
def get_invoices(
self,
access_token: str,
limit: int = 500,
page: int = 1
) -> Dict[str, Any]:
"""
Retrieve paginated list of invoices/orders.
Args:
access_token: Nabis x-nabis-access-token header value
limit: Max results per page (default 500)
page: Page number (default 1)
Returns:
Dictionary with 'items' array of invoices
"""
return self._call(
"get_invoices",
method="GET",
access_token=access_token,
limit=limit,
page=page
)
def get_nabis_days_off(
self,
access_token: str
) -> Dict[str, Any]:
"""
Retrieve list of Nabis non-delivery/holiday dates.
Args:
access_token: Nabis x-nabis-access-token header value
Returns:
Dictionary with 'items' array of days off with date and description
"""
return self._call(
"get_nabis_days_off",
method="GET",
access_token=access_token
)
if __name__ == "__main__":
# Example usage: Realistic workflow for a cannabis distributor
# This demonstrates a practical use case: finding retailers, checking their orders,
# and looking up product details for items in those orders.
# Initialize client
client = ParseClient()
# Use a sample access token (replace with actual token)
access_token = "your_nabis_access_token_here"
print("=" * 60)
print("NABIS MARKETPLACE WORKFLOW EXAMPLE")
print("=" * 60)
# Step 1: Get all retailers on the platform
print("\n📍 Step 1: Fetching all retailers...")
retailers_response = client.get_retailers(access_token=access_token, limit=10)
retailers = retailers_response.get("items", [])
print(f"Found {len(retailers)} retailers")
if retailers:
for retailer in retailers[:3]: # Show first 3
retailer_id = retailer.get("id")
retailer_name = retailer.get("name", "Unknown")
print(f" • {retailer_name} (ID: {retailer_id})")
# Step 2: Get available inventory in California
print("\n📦 Step 2: Fetching California inventory...")
ca_inventory_response = client.get_inventory_ca(
access_token=access_token,
limit=5
)
ca_products = ca_inventory_response.get("items", [])
total_ca = ca_inventory_response.get("total", 0)
print(f"Total CA products available: {total_ca}")
# Step 3: Get detailed info for each product
if ca_products:
print("\n🔍 Step 3: Getting detailed product information...")
for product in ca_products:
sku_code = product.get("skuCode")
sku_name = product.get("skuName", "Unknown")
if sku_code:
try:
product_details = client.get_inventory_by_sku_ca(
access_token=access_token,
sku_code=sku_code
)
detailed_name = product_details.get("skuName", sku_name)
print(f" • {detailed_name} (SKU: {sku_code})")
except Exception as e:
print(f" • {sku_name} (SKU: {sku_code}) - Details unavailable")
# Step 4: Check recent orders
print("\n📋 Step 4: Fetching recent orders...")
orders_response = client.get_orders(access_token=access_token, limit=5)
orders = orders_response.get("items", [])
print(f"Retrieved {len(orders)} recent orders")
total_order_value = 0
for order in orders:
order_id = order.get("id")
total_price = order.get("totalPrice", 0)
total_order_value += total_price
print(f" • Order #{order_id}: ${total_price:,.2f}")
if orders:
print(f" 📊 Total order value: ${total_order_value:,.2f}")
# Step 5: Check warehouse locations
print("\n🏭 Step 5: Fetching warehouse locations...")
warehouses_response = client.get_warehouses(access_token=access_token)
warehouses = warehouses_response.get("items", [])
print(f"Nabis warehouses:")
for warehouse in warehouses:
warehouse_name = warehouse.get("name", "Unknown")
warehouse_id = warehouse.get("id")
print(f" • {warehouse_name} (ID: {warehouse_id})")
# Step 6: Check days off (holidays when orders can't be placed)
print("\n🗓️ Step 6: Checking Nabis days off...")
days_off_response = client.get_nabis_days_off(access_token=access_token)
days_off = days_off_response.get("items", [])
if days_off:
print("Nabis non-delivery dates:")
for day_off in days_off[:5]: # Show first 5
date = day_off.get("date", "Unknown")
description = day_off.get("description", "Holiday")
print(f" • {date}: {description}")
# Step 7: Get invoices (billing records)
print("\n💳 Step 7: Fetching recent invoices...")
invoices_response = client.get_invoices(access_token=access_token, limit=5)
invoices = invoices_response.get("items", [])
print(f"Retrieved {len(invoices)} recent invoices")
for invoice in invoices:
invoice_id = invoice.get("id")
invoice_number = invoice.get("invoiceNumber")
print(f" • Invoice #{invoice_number} (ID: {invoice_id})")
print("\n" + "=" * 60)
print("✅ Workflow complete!")
print("=" * 60)Retrieve paginated list of cannabis inventory/products available in California.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number |
| limit | integer | Max results per page (1-500) |
| access_tokenrequired | string | Nabis x-nabis-access-token header value |
{
"type": "object",
"fields": {
"items": "array",
"total": "integer"
},
"sample": {
"items": [
{
"skuCode": "SKU12345",
"skuName": "Blue Dream 3.5g"
}
],
"total": 100
}
}About the Nabis API
Inventory and Product Lookup
Two state-specific inventory endpoints — get_inventory_ca and get_inventory_ny — return paginated arrays of available cannabis products, each accepting page and limit parameters (up to 500 results per page) alongside a required access_token. For granular product data in California, get_inventory_by_sku_ca accepts a sku_code and returns fields including skuCode and skuName. The New York equivalent, get_inventory_by_product_code_ny, uses an item_code parameter and returns skuName and itemCode.
Orders, Invoices, and Retailers
get_orders returns a paginated list of wholesale orders placed through the platform, and get_invoices returns the corresponding invoice records — both accept page and limit for pagination. get_retailers exposes licensed dispensary retailers on the Nabis network, also paginated. These three endpoints together cover the core transactional data a brand or distributor needs to reconcile fulfillment and billing.
Warehouses and Operational Dates
get_warehouses returns Nabis warehouse location records, useful for understanding distribution coverage. get_nabis_days_off requires only an access_token and returns an array of dates when Nabis does not make deliveries — holidays and other non-operational days. This is particularly relevant when building order scheduling or lead-time calculation logic that needs to account for actual delivery availability.
The Nabis API is a managed, monitored endpoint for nabis.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when nabis.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official nabis.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Sync California and New York cannabis product catalogs into an internal inventory management system using
get_inventory_caandget_inventory_ny - Look up product details by SKU for CA order confirmation flows using
get_inventory_by_sku_ca - Reconcile wholesale invoices against placed orders by cross-referencing
get_invoicesandget_ordersrecords - Build a retailer directory or coverage map from licensed dispensary data returned by
get_retailers - Exclude Nabis non-delivery dates from automated order scheduling using
get_nabis_days_off - Map fulfillment routes or distribution zones using warehouse locations from
get_warehouses - Monitor order history for a licensed brand account by polling
get_orderswith pagination
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Nabis have an official developer API?+
What does `get_inventory_ca` actually return, and how is pagination controlled?+
get_inventory_ca returns an items array of product records and a total integer indicating the full result count. You control pagination with page (page number) and limit (results per page, max 500). The same pagination parameters apply to get_inventory_ny, get_retailers, get_orders, get_warehouses, and get_invoices.Is product data available for states other than California and New York?+
get_inventory_ca and get_inventory_by_sku_ca, and New York via get_inventory_ny and get_inventory_by_product_code_ny. You can fork this API on Parse and revise it to add inventory endpoints for additional states if Nabis expands coverage.Does the API expose product pricing or stock quantity fields?+
skuCode, skuName, and itemCode, along with the broader items array. Detailed sub-fields such as unit pricing or on-hand quantity are nested inside items but not individually enumerated in the endpoint spec. You can fork the API on Parse and revise response mapping if you need those fields surfaced explicitly.Can I filter orders or invoices by date range or status?+
get_orders and get_invoices endpoints accept only page and limit for pagination — date range or status filtering is not exposed. You can fork this API on Parse and revise the endpoint to add filtering parameters if those inputs are available upstream.