Skip to content

Supercollections


T3 API Supercollections

With Metrc data, users frequently encounter these sorts of problems:

  • "I want to load my packages, but also need test results for each"
  • "I want to load my transfers, but also want all the packages"
  • "I want to load my items, but I also want all the images and ingredients"

Enter supercollections

What is a Supercollection?

The best way to understand supercollections is to compare them to T3 collections:

  • T3 collection endpoints are designed to send exactly one request to Metrc per request to T3.
  • Examples: Active Packages, Incoming Transfers, Active Items.
  • This ensures the endpoints are fast, have generous rate limits, and are flexible to use.
  • If you want to load metadata for a collection, you need to explicitly request it per row.
  • T3 supercollection endpoints are designed to eagerly load all metadata for each collection object.
  • Examples: Active Superpackages, Incoming Supertransfers, Superitems.
  • They extend existing collection endpoint behavior.
  • This allows the endpoint to efficiently load, organize, and analyze the metadata for you.
  • Endpoints have lower rate limits, and are slower to use.
  • Metadata is loaded declaratively. For example, you'd specify you want lab results and history for an active superpackages request.

Available Supercollection Endpoints

Supercollection Path include options
Superitems /v2/items/super notes, history, ingredients, images
Active Superpackages /v2/packages/active/super labResults, labResultBatches, sourceHarvests, history
Inactive Superpackages /v2/packages/inactive/super labResults, labResultBatches, sourceHarvests, history
In Transit Superpackages /v2/packages/intransit/super labResults, labResultBatches, sourceHarvests, history
On Hold Superpackages /v2/packages/onhold/super labResults, labResultBatches, sourceHarvests, history
Incoming Active Supertransfers /v2/transfers/incoming/active/super packages, transporters
Incoming Inactive Supertransfers /v2/transfers/incoming/inactive/super packages, transporters
Outgoing Active Supertransfers /v2/transfers/outgoing/active/super packages, transporters
Outgoing Inactive Supertransfers /v2/transfers/outgoing/inactive/super packages, transporters
Rejected Supertransfers /v2/transfers/rejected/super packages, transporters
Hub Supertransfers /v2/transfers/hub/super packages, history
Active Superharvests /v2/harvests/active/super history, plants, packages
Inactive Superharvests /v2/harvests/inactive/super history, plants, packages
On Hold Superharvests /v2/harvests/onhold/super history, plants, packages
Vegetative Superplants /v2/plants/vegetative/super history
Flowering Superplants /v2/plants/flowering/super history
Inactive Superplants /v2/plants/inactive/super history
On Hold Superplants /v2/plants/onhold/super history
Active Mother Superplants /v2/plants/mother/active/super history
Inactive Mother Superplants /v2/plants/mother/inactive/super history
On Hold Mother Superplants /v2/plants/mother/onhold/super history
Active Superplantbatches /v2/plantbatches/active/super history
Inactive Superplantbatches /v2/plantbatches/inactive/super history
On Hold Superplantbatches /v2/plantbatches/onhold/super history
Active Supersales /v2/sales/active/super transactions
Inactive Supersales /v2/sales/inactive/super transactions
Available Supertags /v2/tags/available/super (none)
Used Supertags /v2/tags/used/super (none)
Voided Supertags /v2/tags/voided/super (none)
Active Superlocations /v2/locations/active/super (none)
Superstrains /v2/strains/super (none)

The last five have no include options: there is no related Metrc data to attach to a tag, location or strain. They exist as /super paths so that a caller building URLs by pattern does not have to special-case them, and they return the same records their plain collection counterparts do.

The include Parameter

The include parameter controls which additional data is fetched and attached to each object in the response. Without it, a supercollection request behaves like a regular collection request.

Each include value does two things:

  1. Attaches raw Metrc data as a new array on each object (e.g. labResults, sourceHarvests).
  2. Populates fields on the metadata object with extracted, cleaned-up values derived from that raw data.

You can combine multiple include values by repeating the parameter: include=labResults&include=sourceHarvests.

A comma-joined list is not supported — include=labResults,sourceHarvests is one value, not two.

An include value the endpoint does not accept returns 400 Invalid Include, and the response lists the values it does accept:

GET /v2/packages/active/super?licenseNumber=EX-00001&include=labresults

400 Invalid Include
Unrecognized include `labresults`. This endpoint accepts: history, sourceHarvests,
labResultBatches, labResults.

Include values are case-sensitive, so labresults above is rejected while labResults is accepted. The valid values for each endpoint are also published as an enum in the OpenAPI spec, so an API client can read them programmatically rather than copying them from this page.

The same include values work on super reports, which return the whole enriched dataset in one request instead of paging through it — useful for spreadsheet exports. See Super Reports.

A few metadata fields are populated unconditionally (no include required), when the underlying data is available:

  • Superpackages: netWeightOrVolume, netWeightOrVolumeUnitOfMeasure
  • Superitems: approvalNumber, itemImages

Superpackage includes

include Raw data attached metadata fields populated
labResults labResults[] extractedLabResults, testSamplePackageLabels, labResultPdfs, indexedLabResults
labResultBatches labResultBatches[] extractedLabResults, testSamplePackageLabels, labResultPdfs, indexedLabResults
sourceHarvests sourceHarvests[] harvestDates
history history[] initialQuantity, initialQuantityUnitOfMeasure, manifestNumber², destinationFacilityLicenseNumber², destinationFacilityName², transferType²

² Only present for in-transit packages.

indexedLabResults is a simplified dictionary intended for templating (e.g. on a label). Example access:

{{ package.metadata.indexedLabResults.totalThc.name }}    → "Total THC"
{{ package.metadata.indexedLabResults.totalThc.value }}   → 12.5
{{ package.metadata.indexedLabResults.totalThc.unit }}    → "%"
{{ package.metadata.indexedLabResults.totalThc.full }}    → "Total THC: 12.5 %"

Also indexed: totalCbd, topTerpene1, topTerpene2, etc.

Superitem includes

include Raw data attached metadata fields populated
notes notes[] (none)
history history[] (none)
ingredients ingredients[] (none)
images images[] itemImages

approvalNumber and itemImages are populated on every superitem when the data is available — you don't need include=images to get image metadata, only the raw base64/image records themselves.

Supertransfer includes

include Raw data attached metadata fields populated
packages packages[] (none)
transporters transporters[] (none)

Hub supertransfer includes

Hub transfers — the ones your license transports — take a different include set:

include Raw data attached metadata fields populated
packages packages[] (none)
history history[] (none)

There is deliberately no transporterDetails include. Metrc embeds the driver legs directly in the hub response as shipmentTransporterDetails, so they are present on every record without spending a request:

import requests

response = requests.get(
    "https://api.trackandtrace.tools/v2/transfers/hub/super",
    headers={"Authorization": f"Bearer {access_token}"},
    params={
        "licenseNumber": "DIS000038",
        "pageSize": 20,
        "include": ["packages", "history"],
    },
)

for transfer in response.json()["data"]:
    # Already present -- no include was needed for this
    for leg in transfer["shipmentTransporterDetails"]:
        print(transfer["manifestNumber"], leg["lineNumber"], leg["driverName"])

    # These two required the includes above
    print(f"  {len(transfer['packages'])} packages, {len(transfer['history'])} history entries")

Note that transporterFacilityName, driverName, vehicleMake and friends are also flattened onto the transfer itself. When multiVehicle or isLayover is true those top-level fields describe only the first leg — read shipmentTransporterDetails for the rest.

Superharvest includes

include Raw data attached metadata fields populated
history history[] (none)
plants plants[] (none)
packages packages[] (none)

Superplant includes

include Raw data attached metadata fields populated
history history[] (none)

Supersales includes

include Raw data attached metadata fields populated
transactions transactions[] (none)

Superpackages Example

This is the most commonly used supercollection. Below is an example that loads all active superpackages with lab results for packages in the "Buds" product category:

#!/usr/bin/env python3
# /// script
# requires-python = ">=3.8"
# dependencies = [
#     "t3api-utils",
# ]
# ///


from t3api_utils.api.parallel import load_all_data_sync
from t3api_utils.main.utils import (get_authenticated_client_or_error,
                                    interactive_collection_handler,
                                    pick_license)


def main():
    api_client = get_authenticated_client_or_error()

    license_number = pick_license(api_client=api_client)

    all_packages = load_all_data_sync(
        client=api_client,
        path="/v2/packages/active/super",
        license_number=license_number["licenseNumber"],
        page_size=50,
        include="labResults",
        filter="item.productCategoryName__eq:Buds"
    )

    interactive_collection_handler(data=all_packages)

if __name__ == "__main__":
    main()

Each object in the response will contain:

  • All the standard package fields (label, item, quantity, etc.).
  • A labResults array with the raw Metrc lab result data.
  • A metadata object with extractedLabResults, testSamplePackageLabels, labResultPdfs, indexedLabResults, plus the unconditional netWeightOrVolume / netWeightOrVolumeUnitOfMeasure.

You can find more supercollection examples in the T3 API examples repository.


Next Steps

  • If you haven't yet, set up Python and write your first API script.
  • Compare against Reports, which return a whole dataset in one call. A plain report doesn't attach related objects; a super report does, using the same include values documented above.
  • Browse the OpenAPI spec — each supercollection's include options are documented there.
  • Refer to the T3 API documentation to explore all the available endpoints.
  • Most API endpoints require a T3+ subscription. If you don't have a T3+ subscription, you can sign up here.