These are the official docs for the v0 API. Version 0 is currently under active development and is not yet considered stable — as such, there may be breaking changes introduced without incrementing the version number.
API Endpoints
All endpoints use the standard HTTP verbs to describe their behavior (GET, POST, PUT, DELETE) and use status codes to categorize their responses (200, 301/302, 400, 401, 404, 405, 500). In general, a correctly signed and formatted request will return with status code 200.
When sending data, use a correctly escaped querystring for GET endpoints or a standard form upload (application/x-www-form-urlencoded) for POST/PUT/DELETE. If you are using a request library, this is likely handled for you automatically.
Request bodies are form-encoded, not JSONThe API does not accept
application/jsonrequest bodies. Endpoints that take complex objects (like creating an order) accept a JSON-encoded string as a single form field — each endpoint's reference documents this.
Every endpoint returns a JSON formatted response. After receiving a 200, you should always check the success field to see if your request completed as expected.
GET requests generally always succeed, but any POST/PUT/DELETE request can fail because of pre-requisites or invalid state (like a name conflict or requiring something to exist), which will set the success flag to false. When success is false, there will be an error_code field (and potentially error_message and error_details) to help you identify and react to whatever caused the problem.
Response Envelope
Every response body has roughly the same pieces:
success— true/false flag that is always presenterror_code— a string code if an error occurred (always present when
successis false)error_message— a human readable error messageerror_details— per-field validation errors whenerror_codeis
invalid_request, keyed by field name
Common error codes returned by every endpoint:
| Code | Status | Meaning |
|---|---|---|
missing_api_key | 401 | Missing X-ConfidentCannabis-APIKey header |
invalid_api_key | 401 | API key is not valid (deleted, not found, etc.) |
api_access_denied | 401 | Account does not have access to the API |
missing_signature | 401 | Missing X-ConfidentCannabis-Signature header |
missing_timestamp | 401 | Missing X-ConfidentCannabis-Timestamp header |
invalid_timestamp | 401 | Timestamp header is not a valid epoch timestamp |
request_too_old | 400 | Signed request timestamp is too old — includes current_server_time in the response for calibration |
invalid_signature | 401 | Request is not correctly signed |
permission_denied | 403 | Account does not have permission for this action |
invalid_request | 400 | Generic problem with the request (usually validation) |
Authentication and Signing
All endpoints (even GETs) require an API key header (X-ConfidentCannabis-APIKey). By default, requests must also be signed with a signature generated using the matching API secret — incorrectly signed requests are rejected with a 401 response. Signing can be disabled per credential from the organization settings page to speed up development.
The signature is the hex-encoded SHA256-HMAC of the API key, the data fields (sorted alphabetically, ascending), and the API secret. Never send your API secret in a request — it should only be used for generating signatures.
Read the full, step-by-step signing instructions on the Request Signing page and see example code that correctly signs requests at github.com/ConfidentCannabis/public-api-tools.
Summary of steps to generate a signature:
- Create the base string by combining method and route — e.g.
GET/v0/test - Create an ascii-sorted (ascending), lowercased list of (key, value) pairs from the headers dictionary (must include
X-ConfidentCannabis-Timestampbut notX-ConfidentCannabis-APIKeyorX-ConfidentCannabis-Signature) - Create a url-encoded string
key=value&...for the ascii-ordered header fields, lowercased - Create a semicolon-separated list of lowercase header keys — e.g.
x-confidentcannabis-timestamp;host - Create an ascii-sorted list of (key, value) pairs from the form data
- Add
('api_key', <your api key>)to the END of the list - Create a url-encoded param string
key=value&...for the ordered data fields - Percent-encode the base string from step 1
- Combine the percent-encoded base string, url-encoded header string, and url-encoded parameter string with
&between them - Create the SHA256 HMAC signature of that string using your API secret
- Prefix with the signing algorithm and header list string:
CC0-HMAC-SHA256:host;x-confidentcannabis-timestamp:<signature>
Additional Notes
Updates
All updates and notifications regarding the API are sent via an email list. Please email [email protected] to automatically subscribe. This includes notifications of upcoming features, breaking changes, and version upgrades.
Signing
Getting signing right is the hardest (but most important) part of interacting with the API — the POST /v0/signingtest endpoint exists explicitly for testing your signing code during development.
Paging
Many endpoints that return dynamic lists (e.g. clients, orders, and samples — but not test types, sample categories, etc.) are limited to 100 results and include a more_results boolean field. If more_results is true, additional results exist, which can be queried by passing a number for start (default 0)
and optionally limit (default 100), allowing you to iterate through pages until more_results is false.
Timestamps
Timestamps are always returned in isoformat — for example:
2016-10-04T13:20:42.395276.
Dates with times should always be sent in UTC time in the format
YYYY-MM-DD HH:MM:SS — for example: 2016-10-04 13:20:42.
Dates should always be sent as YYYY-MM-DD — for example: 2016-10-04.
Currency and Pricing
All currency and pricing numbers are always represented as integer cents (instead of floating point dollars). Currency and pricing fields are generally named to reflect this.
File Uploads
Several endpoints support uploading files (images, PDFs, etc.). These file fields are not included when generating signatures, so be sure to exclude them during the signing process. Send files as standard multipart/form-data uploads.
Additional Help
If you need any help or just have questions, comments, or complaints, please reach out at [email protected]. We want to make sure you have the best experience possible, so definitely let us know what you think or if you get stuck!