Skip to main content

cannabis-label-new-york (v1)

The JobSchema for New York patient-specific dispensing labels — the label a registered organization's dispensing site affixes to each sealed medical-cannabis package it dispenses to a certified patient or designated caregiver. One job represents one dispensing transaction; the printer emits one label per unit of each line item (see Multiple line items).

It is intended for a label-capable printer loaded with die-cut adhesive label stock, not a receipt printer.

Scope

This page describes what the schema accepts and what the label prints. It is not legal advice — the registered organization remains responsible for compliance, including confirming that the data it sends is accurate and complete.

Working in more than one state? See cannabis-label-florida (v1) and cannabis-label-maryland (v1). The three labels carry deliberately different content and their payloads are not interchangeable — the differences are noted below.

Metadata​

FieldValue
namecannabis-label-new-york-v1
verticalcannabis
version1
sourceapiV20

What this prints​

Each job is a single dispensing transaction. Every printed label is self-contained: it repeats the shared transaction data (patient, caregiver, practitioner, dispensing site, date) and carries the details of exactly one product.

The label is text only. Unlike the Florida and Maryland labels it carries no fixed text of any kind — every row comes from the orderData you send. There is nothing the template supplies on its own, no warning paragraph, and no symbol or reserved corner. Two consequences worth planning for:

  • Everything on the label is your data. A row is blank because you sent it blank; a row is missing because the field was optional and you omitted it.
  • Plain stock. This label needs no pre-printed artwork, unlike cannabis-label-florida (v1), whose stock must carry the universal symbol.

Multiple line items​

As in the other two states, this does not print one combined ticket — it prints one label per product package.

  • Each entry in line_items[] is one product.
  • An entry's quantity is the number of units of that product, and one label prints per unit. quantity: 2 produces two identical labels for that product.
  • The total number of labels printed is the sum of quantity across all line items.
  • Labels print in line_items order; within a line item, its N identical labels print consecutively.
  • The shared identity block (patient, caregiver, practitioner, dispensing site, date) is identical on every label; only the product block changes between products.

A single combined label covering several packages is never produced — each sealed package receives its own complete label.

quantity and quantity_dispensed are different things

quantity is how many labels — the number of units of that product. quantity_dispensed is what prints in the QTY: row — the amount and unit of product in each package, e.g. 30 ml.

A line item with quantity: 2 and quantity_dispensed: { "amount": 0.5, "unit": "g" } prints two labels, each reading QTY: 0.5 g. It does not print one label reading 1 g.

How many labels print​

A job with two line items:

Line itemproduct_namequantityLabels printed
1Hudson Valley Balance Tincture 30mL11
2Catskill Live Resin Concentrate 0.5g22
Total3

Three labels come off the printer: one tincture label, then two identical concentrate labels. All three carry the same patient / caregiver / practitioner / dispensing-site / date block. This is the example payload below.

What the label carries​

The rows below are what prints, in the order they appear on the label. Captions are printed in bold as shown.

RowCaptionFieldNotes
1PATIENT: … ID:patient.name, patient.registry_idBoth always print — see Registry identification numbers
2CAREGIVER: … ID:caregiver.name, caregiver.registry_idOnly row that can be absent — see The caregiver block
3PRACTITIONER:practitioner.nameName only; nothing else about the practitioner prints
4DISPENSED BY:dispensing_site.name
5—dispensing_site.addressPrinted on its own row, no caption
6—dispensing_site.phoneSent as +18455550142, printed as (845) 555-0142 — see Phone numbers
7PRODUCT:line_items[].product_nameOptional — omit it and no row prints
8QTY: … DATE:line_items[].quantity_dispensed, dispensed_date{amount} {unit}; date prints MM/DD/YYYY
9DOSING:line_items[].dosing_instructionsWraps rather than truncating
10USE BY (OPENED):line_items[].expiration_once_openedPrints MM/DD/YYYY
11PRACTITIONER NOTES:line_items[].practitioner_recommendationsAlways prints — send "None" when there is nothing to state

Rows 1–6 are the shared identity block and are the same on every label of the job. Rows 7–11 come from the individual line item.

Registry identification numbers​

This label prints a government identifier, and neither sibling label does. patient.registry_id — and caregiver.registry_id when a caregiver is present — appear on the printed label next to the corresponding name.

Two things follow from that:

  • A name never prints without its number. name and registry_id are both required on the patient block, and both required on the caregiver block when you send one. A partial block is rejected when the job is created — the request fails with a 400 and nothing prints, rather than printing a label carrying a name with no number.
  • Registry numbers are not sent to your webhook. See orderData is not sent to your webhook below — this is the field that makes that behaviour worth checking.

The number is printed verbatim, exactly as you send it. No format is imposed and none is validated.

The caregiver block​

caregiver is the only optional block in the schema. Everything else at the root is required.

  • Omit it and the label prints no caregiver row and no blank line — the rows below it move up. The label is shorter, not gappy.
  • Send it and both the name and the registry identification number print.
  • Sending a caregiver with only one of name / registry_id is a 400.

Formatting the data you send​

The template prints the data you send largely verbatim. The rules worth knowing when populating orderData:

  • Nothing is added to what you send. The label carries no fixed wording, so any wording restriction that applies to a product name applies to the string you send — the name is printed as given and is not screened for you.
  • product_name is optional, and it is the only optional field on a line item. It exists so staff can tell which label belongs to which package when a transaction has several items. Omit it and no row prints.
  • practitioner_recommendations is required and always prints. When there is no recommendation to state, send the literal string "None". It prints verbatim, as an affirmative declaration on the label. That distinction matters: "None" states that there is nothing to add, whereas an absent field is a data gap — and omitting the field is a 400, not a shorter label.
  • dispensing_site.address is a single line of text. Newlines are rejected — send "210 Main Street, Suite 4B, Poughkeepsie, NY 12601", not an address broken across lines. The label wraps it to the printed width for you.
  • dispensing_site.phone is sent in E.164 and printed in local form. See Phone numbers below — this is the one field where what you send is not what prints.
  • Units print verbatim, with no conversion. quantity_dispensed.unit is your string: g, ml, capsules, units.
  • Amounts below 1 print with a leading zero — 0.5 g, never .5 g. Send the numeric value.
  • Dates. dispensed_date and expiration_once_opened are ISO 8601 dates (YYYY-MM-DD) and print as MM/DD/YYYY.
  • English. Captions are in English. Product data you send is printed as supplied.

Phone numbers​

dispensing_site.phone is the only field where what you send is not what prints.

Send it in E.164: a +1 country code followed by ten digits, e.g. "+18455550142". The label prints the local form — (845) 555-0142 — which is what a patient reads off the paper to dial.

You send+18455550142
The label prints(845) 555-0142
  • North American numbers only. The value must match +1 followed by an area code starting 2–9 and nine further digits. Anything else — a bare (845) 555-0142, a number with spaces or dashes, a non-North-American number — is rejected with a 400 and nothing prints.
  • No extensions. E.164 has no extension concept, so a dispensary publishing a main line plus an extension should send the direct-dial number instead.
  • The limit of 12 characters is exactly the length of a conforming number; it is not a field you can shorten or pad.

What this label does not include​

New York splits the labelling a sealed medical-cannabis package must carry across three artefacts. This dispensing label is one of them, and printing another's content here would consume the space the seven required elements need. Do not send it:

ArtefactCarriesWho applies it
The product label (Part 128, delegated by 113.12(k)(1))Potency, lot, unopened expiration date, storage conditions, processor identityThe manufacturer, before the package reaches the dispensary
The package safety insert (113.13(l)(12))The medicinal-use / pregnancy / driving warning block, and the original-container statementThe dispensing site, inside the package
This dispensing label (113.13(k))The patient-specific remainder — the seven elements on this pageThe dispensing site, on the package

So this label carries no warning block, no potency or lot number, no unopened expiration date and no symbol. Their absence is deliberate and is not an omission to correct by adding them to orderData — the schema rejects unknown properties, so a payload carrying them fails.

This also means printing a compliant label does not complete your packaging obligations. The insert and the product label are separate artefacts this print job does not produce.

Two statutory elements are on no artefact at all

Cannabis Law § 34(13) lists six elements a sealed package must carry. Two of them are allocated to no artefact by any current version of Part 113 or Part 128:

  • the packaging date, and
  • the dose count for inhalable products.

Neither is a dispensing-label element, so nothing on this label changes and there is nothing to send. This is a gap in the regulation, not in this schema — but it sits with the registered organization's packaging, so it is worth confirming how your own packaging addresses it. Verified against primary sources on 2026-08-12; see Sources.

Shape​

orderData: object
├── id: string # required — dispensing-transaction identifier (minLength 1)
├── dispensed_date: string (date) # required — ISO 8601 date, e.g. "2026-08-03"
├── dispensing_site: { # required
│ name, # required — maxLength 60
│ address, # required — single line, maxLength 120
│ phone # required — E.164 "+1XXXXXXXXXX", maxLength 12
│ }
├── patient: { # required
│ name, # required — maxLength 48
│ registry_id # required — printed; maxLength 16
│ }
├── caregiver?: { # optional — the only optional block
│ name, # required when caregiver is sent — maxLength 48
│ registry_id # required when caregiver is sent — maxLength 16
│ }
├── practitioner: { name } # required — name maxLength 48
└── line_items: [NewYorkLabelItem, ...] # required — minItems 1

NewYorkLabelItem​

{
quantity: integer (≥ 1), # required — one label prints per unit
product_name?: string, # optional — maxLength 80
dosing_instructions: string, # required — maxLength 160
quantity_dispensed: { # required
amount: number (> 0), # required
unit: string # required — e.g. "g", "ml", "capsules"
}, # unit maxLength 16
practitioner_recommendations: # required — send "None" if there are none
string, # maxLength 160
expiration_once_opened: # required — ISO 8601 date
string (date)
}

orderData is validated strictly — unknown/extra properties are rejected. Note that the root object uses dispensing_site and practitioner, where Florida uses mmtc / physician and Maryland uses dispensary / certifying_provider. A payload shaped for either of those states will not validate here.

Required fields​

ScopeRequired fields
orderData (root)id, dispensed_date, dispensing_site, patient, practitioner, line_items
dispensing_sitename, address, phone
patientname, registry_id
caregiver (when sent)name, registry_id
practitionername
each line_items[] entryquantity, dosing_instructions, quantity_dispensed, practitioner_recommendations, expiration_once_opened
quantity_dispensedamount, unit

caregiver is the only optional block, and product_name is the only optional field on a line item.

dispensed_date and expiration_once_opened must be ISO 8601 dates (YYYY-MM-DD). line_items must carry at least one entry.

webhook_url and webhook_method are also required on every job creation, but live at the root of the POST body (alongside printerId), not inside orderData. See the Create job page.

orderData is not sent to your webhook​

The callback sent to webhook_url carries only a state update — the Job id, the state change, your externalId, and timestamps. No orderData is transmitted to your webhook URL.

On this schema that is worth stating plainly: the patient and caregiver blocks — including both registry_id values — are never sent to that endpoint. Retrieve them, if you need them, with an authenticated request to GET /v20/jobs/{jobId}.

Field length limits​

Every string that prints on the label carries a length limit. A payload that exceeds one is rejected when the job is created — the request fails with a 400 and nothing prints. The response names the field that was too long.

The limits are set as a set, not field by field: they are chosen so that a label built from a payload respecting all of them fits the stock, with the longest permitted identity block and the longest permitted product text together.

Payload pathLimit
dispensing_site.name60 characters
dispensing_site.address120 characters
dispensing_site.phone12 characters — E.164, see Phone numbers
patient.name48 characters
patient.registry_id16 characters
caregiver.name48 characters
caregiver.registry_id16 characters
practitioner.name48 characters
line_items[].product_name80 characters
line_items[].dosing_instructions160 characters
line_items[].practitioner_recommendations160 characters
line_items[].quantity_dispensed.unit16 characters

Every one of these also has a minimum of 1 character — a limit never made a field optional. caregiver stays the only optional block and product_name the only optional field on a line item.

id is not length-limited; it is not printed on the label. dispensed_date and expiration_once_opened are constrained by date format rather than length. line_items must carry at least one entry and has no upper bound.

Content is never shortened to fit. Long text wraps, and a payload within every limit above prints complete. Nothing is truncated, and no label prints with a required row cut short — the length check happens at submission, before anything is sent to a printer.

Printed output​

The default template produces a landscape label on 76.2 × 50.8 mm (3″ × 2″) die-cut stock — the same stock as cannabis-label-florida (v1), and not the square Maryland stock.

The preview below is one label — the tincture line item from the example, with a caregiver present. The same job also prints two identical concentrate labels (quantity: 2), for three labels total.

New York patient-specific dispensing label, the tincture line item, shown on its 76.2 x 50.8 mm die-cut stock

The thin outline marks the edge of the label stock. It is not printed. Content shorter than the label leaves the rest of the stock blank, as here.

Example​

Two line items — quantities 1 and 2 — producing three labels. A caregiver is present, so every label carries the caregiver row. The second line item has no practitioner recommendation and sends the "None" sentinel.

{
"id": "NY-DISP-51284",
"dispensed_date": "2026-08-03",
"dispensing_site": {
"name": "Hudson Valley Dispensary",
"address": "210 Main Street, Suite 4B, Poughkeepsie, NY 12601",
"phone": "+18455550142"
},
"patient": {
"name": "Maria Delgado",
"registry_id": "P-1234567"
},
"caregiver": {
"name": "Luis Delgado",
"registry_id": "C-7654321"
},
"practitioner": {
"name": "Dr. Anne Chu, M.D."
},
"line_items": [
{
"quantity": 1,
"product_name": "Hudson Valley Balance Tincture 30mL",
"dosing_instructions": "Place 0.5 ml under the tongue twice daily; wait 2 hours before re-dosing.",
"quantity_dispensed": { "amount": 30, "unit": "ml" },
"practitioner_recommendations": "Do not exceed 2 doses in 24 hours.",
"expiration_once_opened": "2026-11-03"
},
{
"quantity": 2,
"product_name": "Catskill Live Resin Concentrate 0.5g",
"dosing_instructions": "Vaporize one 0.05 g dose; wait 15 minutes before repeating.",
"quantity_dispensed": { "amount": 0.5, "unit": "g" },
"practitioner_recommendations": "None",
"expiration_once_opened": "2026-10-15"
}
]
}

This orderData is the body of a POST /v20/jobs request (alongside printerId, webhook_url, and webhook_method). See Create job.

Sources​

Citations on this page were re-verified against these primary sources on 2026-08-13. Earlier drafts of New York material cited the pre-2024 lettering (113.13(i)); that numbering is superseded.