Skip to main content

Limits & Policy

Each provider has prescribing limits and eligibility rules that apply when you submit a consultation. Some are enforced by the API today; others are policy to agree with Cannaflow and are planned for enforcement. Confirm your policy before going live. Provider users can change the minimum patient age, medication item cap, and monthly quantity cap together in Provider settings > Prescribing limits.

Checklist to agree with Cannaflow​

Walk through this list with your Cannaflow contact and record the agreed value for each. The Default column is the value a new provider starts with.

PolicyDefaultEnforced today?How it's checked
Minimum patient age21✅ YesRejects a submission whose patient is younger than this on the submission date.
Max medication items per consultation3✅ YesRejects a single submission carrying more than this many medication items.
Max cannabis quantity per patient per month100✅ YesRejects a submission that would push the patient's running monthly total past this cap.
Cooldown between consultationsto be defined⏳ PlannedNot yet enforced — a minimum wait between a patient's consultations. Agree the value now.

Read this carefully. ✅ rows are enforced by the API right now — a violating request is rejected with the error shown below. ⏳ rows are not enforced yet: the API will currently accept a consultation that breaks them. Until enforcement ships, treat them as your responsibility to apply before submitting. The defaults are starting points for the conversation, not legal advice — you are responsible for compliance with applicable regulations.

Enforced limits​

Minimum patient age — default 21​

The patient's birthDate (sent on every consultation) must put them at or above the provider's minimum age on the Europe/Berlin calendar date of submission. The check is inclusive: when the minimum is 18, someone turning 18 today passes from 00:00 in Berlin, even if it is still the previous date in UTC. One instant before their birthday, they are still 17 and are rejected. The default is 21; provider settings accept whole years of 18 or higher.

For example, a patient born on 2008-07-15 reaches 18 at 2026-07-14T22:00:00Z (midnight in Berlin during summer time). In winter, Berlin midnight is 23:00 UTC on the previous day. This age rule is separate from the UTC calendar month used for medication quantity accounting.

Failing it returns PatientUnderMinimumAge (HTTP 422):

{
"id": "PatientUnderMinimumAge",
"message": "Patient is below the provider minimum age",
"payload": { "patientAge": 20, "minimumAge": 21 }
}

payload reports the patient's computed age and the provider's minimum. There is no remediation for a given patient — do not submit until they meet the minimum.

Max medication items per consultation — default 3​

A single consultation may carry at most this many entries in requestedMedications. The limit is inclusive: a consultation with exactly 3 items passes; a 4th is rejected.

Exceeding it returns PrescriptionItemLimitExceeded (HTTP 422):

{
"id": "PrescriptionItemLimitExceeded",
"message": "Prescription exceeds the maximum medication items per consultation",
"payload": { "limit": 3, "requested": 4 }
}

React by reducing the number of items to payload.limit or fewer.

Max cannabis quantity per patient per month — default 100​

Across all of a patient's consultations in the current calendar month (UTC), the total requested (or, once a doctor has prescribed, the prescribed) quantity may not exceed this cap. The check is inclusive and projected: it sums what the patient already has this month plus the new request, and rejects the request before anything is saved if the total would cross the cap. Cancelled and rejected consultations do not count toward the total.

Unit of measure. Quantities are summed as plain units — one gram, one milliliter, and one piece each count as 1. So a cap of 100 means 100 mixed units per month, not 100 grams. Keep this in mind when you set and reason about the value with Cannaflow. (This is a deliberate current simplification and may be refined later.)

Exceeding it returns MonthlyPrescribedQuantityLimitExceeded (HTTP 422):

{
"id": "MonthlyPrescribedQuantityLimitExceeded",
"message": "Prescription exceeds the patient's monthly prescribed quantity",
"payload": { "limit": 100, "alreadyPrescribed": 95, "requested": 10 }
}

payload tells you the cap, how much is already counted this month, and what you requested. React by lowering the quantity to fit limit - alreadyPrescribed, or wait for the next calendar month.

Planned policy (not yet enforced)​

These are agreed with Cannaflow but not enforced by the API yet. Design your integration to apply them now; the API will begin rejecting violations once enforcement ships, so building to them early avoids a behavior change later.

Cooldown between consultations​

A minimum wait between a single patient's consultations. There is no default yet and it is not enforced — agree a value (e.g. a number of days) with Cannaflow, and apply it on your side for now.

Reading limits and allowance​

Read current organization policy with GET /telehealth/limits, including before a patient has been created:

curl 'https://doctors.cannaflow.de/api/v1/telehealth/limits' \
-H "x-api-key: $CANNAFLOW_API_KEY"

HTTP 200 (example configured policy, not necessarily your organization's values):

{
"minimumAge": 18,
"monthlyQuantity": { "limit": 100 },
"itemsPerConsultation": { "limit": 3 }
}

For an existing patient, GET /telehealth/patients/{patientReferenceId}/allowance also returns quantity usage, remaining quantity, and contributing consultations. Unknown patients return 404; use the organization limits endpoint for first-time patients. These reads are advisory and do not reserve quantity.

curl 'https://doctors.cannaflow.de/api/v1/telehealth/patients/patient-123/allowance' \
-H "x-api-key: $CANNAFLOW_API_KEY"

HTTP 200:

{
"patientReferenceId": "patient-123",
"minimumAge": 21,
"period": {
"from": "2026-09-01T00:00:00.000Z",
"to": "2026-10-01T00:00:00.000Z"
},
"monthlyQuantity": { "limit": 100, "used": 35, "remaining": 65 },
"itemsPerConsultation": { "limit": 3 },
"consultations": [
{
"id": "consultation-pending",
"status": "pending",
"createdAt": "2026-09-09T10:00:00.000Z",
"countedQuantity": 15,
"quantitySource": "requested"
},
{
"id": "consultation-completed",
"status": "completed",
"createdAt": "2026-09-02T10:00:00.000Z",
"countedQuantity": 20,
"quantitySource": "prescribed"
}
]
}
  • period.from is inclusive and period.to exclusive. The consultation's creation time, not prescription issuance or signing time, determines its month.
  • quantitySource: "requested" reserves the original request until a prescription exists. "prescribed" replaces that reservation with prescription-item quantities, including before signing. The two sources are never added for the same consultation.
  • consultations includes only positive contributions, newest first, with ID descending breaking creation-time ties. Cancelled and rejected consultations are omitted. countedQuantity values sum to monthlyQuantity.used.
  • An existing patient with no counted usage receives consultations: [], used: 0, and remaining equal to limit. This is different from an unknown patient (404).
  • remaining is max(0, limit - used). If the cap is lowered to 30 after the example's usage of 35, the result is { "limit": 30, "used": 35, "remaining": 0 }, not an error. Reaching the cap also returns 200 with zero remaining.
  • itemsPerConsultation.limit is a per-request entry cap, not a monthly remaining item count. minimumAge is organization policy, not a patient eligibility verdict. Reads do not check the patient's age, questionnaire, or identity. Consultation creation rechecks its own gates and can still fail after a successful allowance read.

Read errors​

All errors use { "message": "...", "id": "..." }, with payload only where the error defines one. Branch on id, not the message.

  • 401 Unauthorized: the API key is missing or unknown. Supply a valid x-api-key.
  • 403 TelemedicineProviderNotActive: the key resolves to an inactive provider. Contact Cannaflow to activate the provider.
  • 400 InvalidArguments (allowance): the request fails input validation. patientReferenceId must be a nonempty string path segment; URL-encode it. Schema validation details are in payload.issues.
  • 404 NotFound (allowance): the patient does not exist in the calling organization, including a reference that exists only in another organization. Use /telehealth/limits before the first consultation creates the patient.
  • 500 InternalError: an unexpected server, database, or response-validation failure. Internal details are masked; retain the response for support.

For example, an unknown patient returns HTTP 404:

{
"message": "Patient not found",
"id": "NotFound",
"payload": { "kind": "patient", "entities": ["patient-123"] }
}

The limits endpoint has no patient lookup and does not return a patient 404. Neither read throws PatientUnderMinimumAge, PrescriptionItemLimitExceeded, or MonthlyPrescribedQuantityLimitExceeded; those are submission errors described above.

Cancelling a consultation​

Use POST /telehealth/consultations/{id}/cancel to release a supported consultation's counted allowance without deleting its clinical history or identity. No request body is required:

curl -X POST \
'https://doctors.cannaflow.de/api/v1/telehealth/consultations/consultation-pending/cancel' \
-H "x-api-key: $CANNAFLOW_API_KEY"

HTTP 200:

{
"id": "consultation-pending",
"status": "cancelled",
"cancelledAt": "2026-09-09T11:00:00.000Z"
}

The consultation must be a partner-origin questionnaire consultation linked to a provider patient, in pending or in_review, with no prescription. Repeating a supported cancellation returns 200 with the original timestamp. A supported historical cancellation without a stored timestamp returns cancelledAt: null. Re-read allowance after cancelling; in the example above, cancelling the pending 15-unit reservation leaves used: 20 and remaining: 80 under the 100-unit cap.

This endpoint does not issue refunds, revoke prescriptions, send cancellation webhooks, or change the prescription signing lifecycle.

Cancellation errors​

  • 400 InvalidArguments: malformed request input (for example, an invalid JSON body if one is sent). Use the consultation ID from create/list and omit the body.
  • 401 Unauthorized and 403 TelemedicineProviderNotActive: the same authentication failures as the reads above.
  • 404 NotFound: the consultation does not exist or belongs to another provider. Its payload is { "kind": "consultation", "entities": ["consultation-pending"] }.
  • 403 OperationNotPermitted: the consultation is rejected, awaiting_signature, or completed; has any prescription; lacks a linked provider patient; is not a questionnaire consultation; or belongs to an unsupported shop, patient-request, doctor-directed, pharmacy, cart, appointment, appointment-hold, or video-meeting flow. It also applies if the guarded update can no longer transition an eligible consultation. Already-cancelled consultations must still meet the supported-flow and no-prescription conditions to be retried successfully.
  • 500 InternalError: an unexpected server or database failure; internal details are masked. A retry is safe for a supported cancellation.

An ineligible cancellation returns HTTP 403, not 409, without a payload:

{
"message": "Consultation cannot be cancelled",
"id": "OperationNotPermitted"
}

Changing a value​

Signed-in provider users can change all three values for their own organization in Provider settings > Prescribing limits, with a single Save action. Minimum age must be a whole number at least 18; the item and monthly quantity caps must be positive whole numbers. The defaults remain 21, 3, and 100. Invalid input rejects the entire save. Changes are saved together and audited.

Saved values apply to subsequent eligibility checks, not retroactively to completed consultations. Lowering the monthly cap below existing usage does not erase that usage or cancel consultations: the allowance reports zero remaining, and further positive medication requests are rejected until they fit the cap.

The public API key provides read access only. There is no public write endpoint for these settings; the portal uses its session-authenticated settings API. For an agreed cooldown policy, contact Cannaflow support with your provider name and the change you need.

See also​