# New York Cannabis Licenses - OCM Register & Equity (`j0401/ny-ocm-cannabis`) Actor

New York's OCM cannabis licence register (3,002 locations): licence type and status, entity and DBA, county and region, whether the business is actually operating, the authorised activities, and the equity category.

- **URL**: https://apify.com/j0401/ny-ocm-cannabis.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 new york ocm cannabis licence records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## New York Cannabis Licenses - OCM Register & Equity

New York's cannabis licence register, straight from the Office of Cannabis
Management via the State's open data portal. **3,002 licensed locations**
covering 2,265 licences (as of 2026-09-28) - with what each licence actually
authorises, and the social and economic equity category it qualifies under.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.** Pay only for the
records you actually receive - the whole register stays queryable, you are
never billed for the scan behind it.

### What you get

- **Which licence** - the licence number, the application number, the licence
  type (Retail Dispensary, Conditional Retail Dispensary, Microbusiness,
  Processor, Cultivator, Distributor, Registered Organization, ) and both the
  type code and the status code
- **Status** - the licence status, plus a **separate operational status** -
  a licence can be Active while the business is not yet operating
- **Who** - the licence holder's legal entity name, its trading name where it
  has one, the primary contact, and the business website
- **Where** - the county and the region (both well populated), plus the street
  address, city and ZIP where the licence publishes one
- **When** - issued, effective and expiration dates, and the date the store
  opened to the public for retail licences
- **What the licence authorises** - a set of per-activity flags: indoor,
  outdoor, mixed-light and combination cultivation; drying and curing; storage;
  packaging; waste rendering; extraction; blending; packaging and labelling;
  branding; retail sales with and without delivery; non-cannabis products; and
  drive-through retail
- **Equity category** - the OCM social and economic equity qualifying class:
  women-owned, minority-owned, service-disabled veteran-owned businesses and
  the other categories, on the 1,130 licences that carry one

### Modes

- **rows** (default) - licence locations matching your filters
- **aggregate** - counts by licence type, status, operational status, region,
  county or business purpose

### Filters

Licence number, licence type, licence status, operational status, region,
county, city, ZIP, entity name, DBA, business purpose, equity category, an
issue-date range, an expiration cutoff, and five activity filters
(indoor/outdoor cultivation, extraction, retail with delivery, drive-through).

### Example inputs

**Active retail dispensaries**

```json
{ "licenseType": "Retail Dispensary", "licenseStatus": "Active", "maxResults": 100 }
```

**Licences held in one county**

```json
{ "county": "Kings", "operationalStatus": "Active", "maxResults": 100 }
```

**Women-owned licences**

```json
{ "seeCategory": "Women-Owned", "maxResults": 100 }
```

**Who can actually cultivate indoors**

```json
{ "cultivationIndoor": "1", "licenseStatus": "Active" }
```

**Renewals coming up**

```json
{ "expiringBefore": "2026-12-31", "licenseStatus": "Active" }
```

**How the register splits by type**

```json
{ "mode": "aggregate", "groupBy": "licenseType" }
```

### Example output

**One licence location** - `licenseNumber=OCM-RETL-26-000511` (keys left empty
by the source are shown for completeness):

```json
{
 "platform": "ny-ocm-cannabis",
 "source": "ny-ocm-licenses",
 "mode": "rows",
 "recordType": "license-location",
 "groupKey": "",
 "groupCount": "",
 "groupBy": "",
 "licenseNumber": "OCM-RETL-26-000511",
 "licenseType": "Adult-Use Retail Dispensary License",
 "licenseTypeCode": "OCMRETL",
 "licenseStatus": "Active",
 "licenseStatusCode": "LICACT",
 "issuedDate": "2026-05-26",
 "effectiveDate": "2026-05-26",
 "expirationDate": "2028-05-26",
 "applicationNumber": "OCMRETL-2023-000952",
 "seeCategory": "",
 "entityName": "TRASH ISLAND BK INC.",
 "dba": "Hibernica Central Park",
 "locationId": "2397EF30-C94D-4982-B1FF-98DBBDFB559F",
 "addressLine1": "111 Central Park North",
 "addressLine2": "Store FRNT B",
 "city": "New York",
 "state": "NY",
 "zip": "10026",
 "county": "New York",
 "region": "Manhattan",
 "businessWebsite": "shophibernica.com/centralpark",
 "operationalStatus": "Active",
 "businessPurpose": "Adult-Use Retail Sales",
 "tierType": "",
 "processorType": "",
 "cultivationIndoor": "0",
 "cultivationOutdoor": "0",
 "cultivationMixedLight": "0",
 "cultivationCombination": "0",
 "cultivationDryingCuring": "0",
 "cultivationStorage": "0",
 "cultivationPackaging": "0",
 "cultivationWasteRendering": "0",
 "processingExtraction": "0",
 "processingBlending": "0",
 "processingPackagingLabeling": "0",
 "processingBranding": "0",
 "retailSalesWithDelivery": "0",
 "retailSalesNoDelivery": "1",
 "retailNonCannabisProducts": "0",
 "retailDriveThru": "0",
 "retailDateOpenedToPublic": "2026-06-26",
 "hoursOfOperation": "Sun: 10:00 AM - 09:00 PM; Mon: 10:00 AM - 09:00 PM; ",
 "primaryContactName": "JENNIFER HESTER",
 "sourceUpdatedAt": "2026-09-24"
}
```

**`mode=aggregate`, `groupBy=licenseType`** - one count row per type:

```
Adult-Use Retail Dispensary License               689
Adult-Use Microbusiness License                   483
Adult-Use Processor License                       458
Adult-Use Conditional Retail Dispensary License   457
Adult-Use Cultivator License                      383
Adult-Use Distributor License                     298
Adult-Use Processor Type Three-Branding           185
```

### Notes on the data, from the source

- 🔴 **A row is a licensed location, not a licence.** The 3,002 rows carry
  2,265 distinct licence numbers, because one licence can be held at several
  addresses (one microbusiness licence appears on 7 rows, each a distinct
  location). Count locations with a row count and licences with a distinct
  count on `licenseNumber` - this actor reports both rather than letting a row
  count pass as a licence count.
- 🔴 **361 rows have no licence number at all.** They are the not-yet-issued
  applications - 356 `licenseStatus='In-Process'` and 5 more
  `'PCA Under Review'` - so there is nothing to number. Nothing is invented for
  them: the field is returned empty, and a search by licence number simply
  excludes them, which is what asking by number means.
- 🔴 **The activity flags are stored as the text `'1'` and `'0'`, not as Y/N and
  not as booleans** - and blank is a third state. `cultivationIndoor` is `1` on
  352 rows, `0` on 2,434 and blank on 216. The actor returns them verbatim in
  that three-state form, and the filters take `1` or `0`, because collapsing
  `0` into blank would merge "not authorised" with "not recorded" - on those
  216 rows that is exactly the distinction that matters.
- 🔴 **The location block is withheld on most licences.** Street address, city
  and ZIP are populated on 1,358 of 3,002 rows (45%). The **county (90%) and
  region (88%)** are the populated geography and are what the geographic
  filters and the aggregate use. No part of this actor promises a street
  address.
- 🔴 **The region column mixes two vocabularies and one legacy spelling.** It
  holds the ten New York economic-development regions, the New York City
  boroughs (Brooklyn, Queens, Manhattan, Bronx, Richmond, plus a bare "NYC" on
  8 rows) - and it spells the capital region **both ways**, "Capital District"
  (281 rows) and "Capital Region" (3). The values are served exactly as the
  State publishes them and the region filter matches on a substring, so
  searching "Capital" finds both spellings. Which spelling is "correct" is not
  for this actor to decide.
- **`businessPurpose` and `seeCategory` are comma-joined multi-value fields.**
  A licence can read "Adult-Use Cultivation, Adult-Use Processing, Adult-Use
  Retail Sales" - so both are matched as substrings.
- **The status pair is not redundant.** Licence status and operational status
  differ: of the 2,478 Active licences, 1,950 are operating and 528 are
  not-yet-operational, and 272 licences have already passed their expiration
  date. Ask for `operationalStatus=Active` when you mean "open for business".
- **These fields exist only for the licence classes they apply to**: the tier
  type (28%), processor type (36%), DBA (26%), business website (26%) and hours
  of operation (25%). Blank is normal, not missing data.
- Invalid filter inputs (a `%` in a search, a ZIP with no digits, a flag that
  is not `1` or `0`, a malformed date, a key this actor does not implement) are
  rejected rather than passed to the source.

### Coverage and freshness

New York OCM's current licence register, all 3,002 rows, published by the
Office of Cannabis Management. The newest licence issue date at the time of
writing was 2026-09-24. Every record carries `sourceUpdatedAt`; the actor also
carries a count guard and a whole-corpus field-coverage guard, so a source that
collapses or changes shape fails loudly instead of returning an empty page as
success.

# Actor input Schema

## `mode` (type: `string`):

rows = records matching your filters (default). aggregate = one count row per group (see groupBy).

## `licenseNumber` (type: `string`):

Exact licence number, e.g. 'OCM-RETL-26-000530'. Blank = any. 12% of rows are in-process applications with no number yet.

## `licenseType` (type: `string`):

Substring, e.g. 'Retail Dispensary', 'Microbusiness', 'Processor', 'Cultivator', 'Distributor'. Blank = any.

## `licenseStatus` (type: `string`):

Exact status: 'Active' (2,478), 'In-Process' (356), 'Inactive' (84), 'Amendment Under Review' (78), 'PCA Under Review' (6). Blank = any.

## `operationalStatus` (type: `string`):

Exact operational status: 'Active' (1,950) or 'Non-Operational' (964). A licence can be Active while not yet operating. Blank = any.

## `region` (type: `string`):

Region substring, e.g. 'Mid-Hudson', 'Western NY', 'Long Island', 'Brooklyn'. The source mixes the ten economic regions with the NYC boroughs and spells 'Capital' two ways; a substring finds all of them. Blank = any.

## `county` (type: `string`):

County substring, e.g. 'Kings', 'Queens', 'Suffolk'. Blank = any.

## `city` (type: `string`):

City substring. Only 45% of licences publish a location. Blank = any.

## `zip` (type: `string`):

ZIP, matched as a prefix. Only 45% of licences publish a location. Blank = any.

## `entityName` (type: `string`):

Licence holder's legal entity name substring. Blank = any.

## `dba` (type: `string`):

Trading name substring. Populated on 26% of licences. Blank = any.

## `businessPurpose` (type: `string`):

Substring of the authorised purpose, e.g. 'Adult-Use Retail Sales', 'Adult-Use Cultivation', 'Medical Sales'. Blank = any.

## `seeCategory` (type: `string`):

Social and economic equity category substring, e.g. 'Women-Owned Business', 'Minority-Owned Business', 'Service-Disabled Veteran-Owned Business'. Populated on 1,130 licences. Blank = any.

## `issuedFrom` (type: `string`):

Earliest issue date (YYYY-MM-DD). Blank = any.

## `issuedTo` (type: `string`):

Latest issue date (YYYY-MM-DD), inclusive. Blank = any.

## `expiringBefore` (type: `string`):

Expiration cutoff, inclusive (YYYY-MM-DD) - pair with issuedFrom for a renewal window. Blank = any.

## `cultivationIndoor` (type: `string`):

Authorised for indoor cultivation. '1' = only those; '0' = only those without it recorded; blank = any.

## `cultivationOutdoor` (type: `string`):

Authorised for outdoor cultivation. Blank = any.

## `processingExtraction` (type: `string`):

Authorised for processing by extraction. Blank = any.

## `retailSalesWithDelivery` (type: `string`):

Authorised for retail sales with delivery. Blank = any.

## `retailDriveThru` (type: `string`):

Authorised for drive-through retail (88 licences). Blank = any.

## `maxResults` (type: `integer`):

Maximum records to return in rows mode (1-10000). Default 50.

## `groupBy` (type: `string`):

aggregate mode only: the dimension to count by.

## Actor input object example

```json
{
  "mode": "rows",
  "licenseNumber": "",
  "licenseType": "",
  "licenseStatus": "",
  "operationalStatus": "",
  "region": "",
  "county": "",
  "city": "",
  "zip": "",
  "entityName": "",
  "dba": "",
  "businessPurpose": "",
  "seeCategory": "",
  "issuedFrom": "",
  "issuedTo": "",
  "expiringBefore": "",
  "cultivationIndoor": "",
  "cultivationOutdoor": "",
  "processingExtraction": "",
  "retailSalesWithDelivery": "",
  "retailDriveThru": "",
  "maxResults": 50,
  "groupBy": "licenseType"
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

New York OCM cannabis licences - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/ny-ocm-cannabis").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/ny-ocm-cannabis").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call j0401/ny-ocm-cannabis --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/ny-ocm-cannabis"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VfLSYrPQMOcLzBeg4/builds/etiB7cSI2fZCYkNnf/openapi.json
