{"openapi":"3.1.0","info":{"title":"Classify7 API","version":"2026.08.1","description":"Determine whether a product is a dangerous good and return its UN number, proper shipping name, hazard class and division, packing group, labels, and per-carrier eligibility for UPS, FedEx, USPS and Amazon FBA — including the lithium battery packing instructions PI965 to PI970.\n\nThree outcomes, and only three: `classified` when an entry matched and every datum needed to pin down the packing group was present; `not_regulated` when the material was positively identified as outside the regulations, with the reason; `needs_review` when nothing matched, a required datum is missing, or two entries are too close to separate. There is no fourth outcome where a plausible-looking guess is returned — a wrong UN number on a shipping paper is worse than no UN number.\n\nRuleset scope: A curated subset of the 49 CFR 172.101 Hazardous Materials Table covering the substances and articles that appear in commercial parcel, e-commerce and FBA shipping, reconciled against the IATA DGR and the IMDG Code. Anything the table does not cover returns needs_review with the reason stated — it is never resolved to a plausible-looking guess.\n\nPOST /api/classify is open and unauthenticated on the free tier, one classification per rolling day per IP. Batch classification, signed certificates and continuous re-classification require an API key on a paid plan.","contact":{"name":"Classify7","url":"https://classify7.com","email":"classify7@relay.openhelm.ai"},"license":{"name":"Proprietary","url":"https://classify7.com/terms"}},"servers":[{"url":"https://classify7.com"}],"security":[{},{"apiKey":[]}],"tags":[{"name":"Classification","description":"Determine what a product is for transport."},{"name":"Certificates","description":"Signed audit artefacts pinned to a ruleset hash."},{"name":"Monitoring","description":"Re-classification when a regulatory edition changes."},{"name":"Reference","description":"The ruleset itself, machine-readable."}],"paths":{"/api/classify":{"post":{"tags":["Classification"],"operationId":"classifyProduct","summary":"Classify one product for dangerous goods transport","description":"Accepts a free-text description, a composition list with CAS numbers, SDS text, or a UN number to verify. Returns the determination with the evidence that produced it, the reasoning in order, the citations, and the ruleset version hash it was made under.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassifyRequest"},"examples":{"solventFromCas":{"summary":"Isopropyl alcohol cleaner, identified by CAS number","value":{"sku":"CLN-IPA-500","description":"70% isopropyl alcohol screen cleaner, 500 ml spray bottle","composition":[{"name":"Isopropyl alcohol","cas":"67-63-0","percent":70}],"modes":["ground","air"]}},"lithiumPowerBank":{"summary":"Standalone lithium ion power bank — resolves to PI965","value":{"sku":"PB-20K","description":"20,000 mAh USB-C power bank","lithium":{"chemistry":"ion","packing":"alone","unit":"battery","wattHours":74,"stateOfChargePercent":28,"netWeightKgPerPackage":0.4}}},"householdBleach":{"summary":"Household bleach — concentration decides the packing group","value":{"sku":"HH-BLEACH-2L","description":"Household thin bleach, 2 L bottle","composition":[{"name":"Sodium hypochlorite","cas":"7681-52-9","percent":5}],"concentrationPercent":5}},"needsFlashPoint":{"summary":"Nail polish with no flash point — returns needs_review, not a guess","value":{"sku":"NP-15","description":"Nail polish, 15 ml glass bottle"}}}}}},"responses":{"200":{"description":"A determination, or an honest refusal to make one","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationResult"}}}},"400":{"description":"Body was not valid JSON"},"401":{"description":"An API key was presented but did not verify"},"402":{"description":"Quota exhausted on the free tier for a signed-in caller"},"422":{"description":"Body failed schema validation"},"429":{"description":"Rate limited, or the free daily allowance is used up"}}}},"/api/classify/batch":{"post":{"tags":["Classification"],"operationId":"classifyBatch","summary":"Classify up to 500 SKUs in one call","description":"Pro feature. Each item is classified independently, so one malformed row reports its own error in place rather than failing the batch. Returns a summary by determination and by hazard class alongside the full results.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"},"examples":{"catalogueOnboarding":{"summary":"Three SKUs from a catalogue onboarding","value":{"batchRef":"catalogue-import-2026-08","items":[{"sku":"CLN-IPA-500","description":"70% isopropyl alcohol screen cleaner, 500 ml spray bottle","composition":[{"name":"Isopropyl alcohol","cas":"67-63-0","percent":70}],"modes":["ground","air"]},{"sku":"PB-20K","description":"20,000 mAh USB-C power bank","lithium":{"chemistry":"ion","packing":"alone","unit":"battery","wattHours":74,"stateOfChargePercent":28,"netWeightKgPerPackage":0.4}},{"sku":"HH-BLEACH-2L","description":"Household thin bleach, 2 L bottle","composition":[{"name":"Sodium hypochlorite","cas":"7681-52-9","percent":5}],"concentrationPercent":5}]}}}}}},"responses":{"200":{"description":"One result per item, with a batch summary"},"401":{"description":"No API key"},"402":{"description":"Free plan — batch is a paid endpoint"},"422":{"description":"Body failed schema validation"},"429":{"description":"Rate limited"}}}},"/api/classify/{id}/certificate":{"get":{"tags":["Certificates"],"operationId":"getClassificationCertificate","summary":"Signed classification certificate for a stored determination","description":"Issued against the stored determination, not against a fresh classification, so it records what was actually returned at the time and under which ruleset hash. Signed with Ed25519; verify against the JWK published at /api/certificate-key.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The classificationId returned by /api/classify."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["pdf","json"]},"description":"Defaults to pdf. Use json for the signed payload and compact JWS."}],"responses":{"200":{"description":"The certificate","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"$ref":"#/components/schemas/SignedCertificate"}}}},"401":{"description":"No API key"},"402":{"description":"Free plan — certificates are a paid artefact"},"403":{"description":"That classification belongs to another account"},"404":{"description":"No stored classification with that id"},"503":{"description":"No database, or no signing key configured"}}}},"/api/certificate-key":{"get":{"tags":["Certificates"],"operationId":"getCertificatePublicKey","summary":"Public key certificates are signed with","description":"Published so a recipient can verify a certificate offline. A verification path that runs through the issuer is not really verification.","responses":{"200":{"description":"A JWK set with one Ed25519 public key"},"503":{"description":"No signing key configured on this deployment"}}}},"/api/monitored-skus":{"get":{"tags":["Monitoring"],"operationId":"listMonitoredSkus","summary":"SKUs under continuous re-classification","security":[{"apiKey":[]}],"responses":{"200":{"description":"Monitored SKUs with their last verdict and staleness"}}},"post":{"tags":["Monitoring"],"operationId":"monitorSku","summary":"Put a SKU under continuous re-classification","description":"The SKU is re-run whenever the ruleset hash changes — a DGR edition turnover, a 49 CFR amendment, or a carrier overlay correction. Supply a webhookUrl to be told when a determination moves.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorRequest"},"examples":{"monitorPowerBank":{"value":{"sku":"PB-20K","input":{"sku":"PB-20K","description":"20,000 mAh USB-C power bank","lithium":{"chemistry":"ion","packing":"alone","unit":"battery","wattHours":74,"stateOfChargePercent":28,"netWeightKgPerPackage":0.4}},"webhookUrl":"https://example.com/hooks/classify7"}}}}}},"responses":{"201":{"description":"Monitoring started"},"402":{"description":"Free plan — monitoring is a paid feature"}}},"delete":{"tags":["Monitoring"],"operationId":"unmonitorSku","summary":"Stop monitoring a SKU","security":[{"apiKey":[]}],"parameters":[{"name":"sku","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Monitoring stopped"},"404":{"description":"Not monitored"}}}},"/api/monitored-skus/recheck":{"post":{"tags":["Monitoring"],"operationId":"recheckMonitoredSkus","summary":"Re-run every stale monitored SKU and report what moved","security":[{"apiKey":[]}],"responses":{"200":{"description":"The changes, field by field, per SKU"}}}},"/api/reference":{"get":{"tags":["Reference"],"operationId":"getRuleset","summary":"The machine-readable ruleset","description":"The entry table, hazard classes, packing group rules, lithium thresholds, carrier overlays and the ruleset hash. Diff it between versions to see exactly what moved.","responses":{"200":{"description":"The ruleset"}}}},"/api/keys":{"get":{"tags":["Reference"],"operationId":"listApiKeys","summary":"List API keys on the signed-in account","responses":{"200":{"description":"Key prefixes; the secret is never retrievable"}}},"post":{"tags":["Reference"],"operationId":"createApiKey","summary":"Issue an API key — the plaintext is returned exactly once","responses":{"201":{"description":"The new key"}}},"delete":{"tags":["Reference"],"operationId":"revokeApiKey","summary":"Revoke an API key","description":"Revocation is immediate and permanent — a revoked key authenticates nothing from the next request onward. This is the response to a leaked key, so it is documented here rather than left to the dashboard alone.","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"The key id from listApiKeys. Not the key itself, which is never stored."}],"responses":{"200":{"description":"Revoked"},"401":{"description":"Not signed in"},"404":{"description":"No active key with that id on this account"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from the dashboard, sent as `Authorization: Bearer classify7_live_…`. The `X-API-Key` header is accepted as an alternative."}},"schemas":{"ClassifyRequest":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"description":{"description":"Free-text product description, e.g. \"70% isopropyl alcohol screen cleaner, 500 ml spray bottle\". The usual starting point.","type":"string","maxLength":2000},"composition":{"description":"Ingredient or composition rows. A CAS number here usually settles the match outright.","maxItems":100,"type":"array","items":{"type":"object","properties":{"name":{"description":"Ingredient or constituent name.","type":"string","maxLength":300},"cas":{"description":"CAS registry number. The single strongest identifier the matcher accepts.","type":"string","maxLength":20},"percent":{"description":"Percentage of the formulation. Major constituents carry more matching weight.","type":"number","minimum":0,"maximum":100}},"additionalProperties":false}},"sdsText":{"description":"Text extracted from a safety data sheet. Section 14 (transport information) is the most useful part to paste.","type":"string","maxLength":200000},"unNumber":{"description":"A UN number you already believe applies, e.g. \"UN1993\". It is verified against the table, not taken on trust.","type":"string","maxLength":20},"sku":{"description":"Your own identifier. Echoed back on the result and printed on any certificate.","type":"string","maxLength":200},"modes":{"description":"Transport modes to report carrier eligibility for. Defaults to all three.","maxItems":3,"type":"array","items":{"type":"string","enum":["ground","air","ocean"]}},"flashPointC":{"description":"Closed-cup flash point in °C. Decides the Class 3 packing group under 49 CFR 173.121.","type":"number","minimum":-200,"maximum":1000},"initialBoilingPointC":{"description":"Initial boiling point in °C. Separates packing group I from packing group II.","type":"number","minimum":-200,"maximum":2000},"concentrationPercent":{"description":"Concentration of the hazardous constituent. Decides the Class 8 packing group and, for several entries, whether the solution is regulated at all.","type":"number","minimum":0,"maximum":100},"alcoholByVolumePercent":{"description":"Alcohol by volume for a beverage. At or below 24% the beverage is not regulated.","type":"number","minimum":0,"maximum":100},"lithium":{"description":"Battery details, when the item is or contains a cell.","type":"object","properties":{"chemistry":{"description":"\"ion\" for rechargeable lithium ion or polymer cells, \"metal\" for non-rechargeable primary lithium cells. Lithium metal is sized by lithium content in grams, not watt-hours, which is the most common classification error in this area.","type":"string","enum":["ion","metal"]},"packing":{"description":"\"alone\" for a standalone battery (PI965 / PI968), \"with-equipment\" for a battery packed alongside the device (PI966 / PI969), \"in-equipment\" for a battery installed in the device (PI967 / PI970).","type":"string","enum":["alone","with-equipment","in-equipment"]},"unit":{"description":"Whether the figures describe a single \"cell\" or an assembled \"battery\". The thresholds differ: 20 Wh per cell against 100 Wh per battery.","type":"string","enum":["cell","battery"]},"wattHours":{"description":"Watt-hour rating. Required for lithium ion.","type":"number","exclusiveMinimum":0,"maximum":100000},"lithiumContentGrams":{"description":"Lithium content in grams. Required for lithium metal.","type":"number","exclusiveMinimum":0,"maximum":10000},"netWeightKgPerPackage":{"description":"Net weight of cells and batteries in one package. Decides the 5 kg Section II limit.","type":"number","exclusiveMinimum":0,"maximum":10000},"stateOfChargePercent":{"description":"State of charge as a percentage of rated capacity. Standalone lithium ion must not exceed 30% for air transport.","type":"number","minimum":0,"maximum":100},"cellsPerPackage":{"type":"integer","minimum":0,"maximum":100000},"batteriesPerPackage":{"type":"integer","minimum":0,"maximum":100000}},"additionalProperties":false}},"additionalProperties":false},"BatchRequest":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"batchRef":{"description":"Your reference for this batch.","type":"string","maxLength":200},"items":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"object","properties":{"description":{"description":"Free-text product description, e.g. \"70% isopropyl alcohol screen cleaner, 500 ml spray bottle\". The usual starting point.","type":"string","maxLength":2000},"composition":{"description":"Ingredient or composition rows. A CAS number here usually settles the match outright.","maxItems":100,"type":"array","items":{"type":"object","properties":{"name":{"description":"Ingredient or constituent name.","type":"string","maxLength":300},"cas":{"description":"CAS registry number. The single strongest identifier the matcher accepts.","type":"string","maxLength":20},"percent":{"description":"Percentage of the formulation. Major constituents carry more matching weight.","type":"number","minimum":0,"maximum":100}},"additionalProperties":false}},"sdsText":{"description":"Text extracted from a safety data sheet. Section 14 (transport information) is the most useful part to paste.","type":"string","maxLength":200000},"unNumber":{"description":"A UN number you already believe applies, e.g. \"UN1993\". It is verified against the table, not taken on trust.","type":"string","maxLength":20},"sku":{"description":"Your own identifier. Echoed back on the result and printed on any certificate.","type":"string","maxLength":200},"modes":{"description":"Transport modes to report carrier eligibility for. Defaults to all three.","maxItems":3,"type":"array","items":{"type":"string","enum":["ground","air","ocean"]}},"flashPointC":{"description":"Closed-cup flash point in °C. Decides the Class 3 packing group under 49 CFR 173.121.","type":"number","minimum":-200,"maximum":1000},"initialBoilingPointC":{"description":"Initial boiling point in °C. Separates packing group I from packing group II.","type":"number","minimum":-200,"maximum":2000},"concentrationPercent":{"description":"Concentration of the hazardous constituent. Decides the Class 8 packing group and, for several entries, whether the solution is regulated at all.","type":"number","minimum":0,"maximum":100},"alcoholByVolumePercent":{"description":"Alcohol by volume for a beverage. At or below 24% the beverage is not regulated.","type":"number","minimum":0,"maximum":100},"lithium":{"description":"Battery details, when the item is or contains a cell.","type":"object","properties":{"chemistry":{"description":"\"ion\" for rechargeable lithium ion or polymer cells, \"metal\" for non-rechargeable primary lithium cells. Lithium metal is sized by lithium content in grams, not watt-hours, which is the most common classification error in this area.","type":"string","enum":["ion","metal"]},"packing":{"description":"\"alone\" for a standalone battery (PI965 / PI968), \"with-equipment\" for a battery packed alongside the device (PI966 / PI969), \"in-equipment\" for a battery installed in the device (PI967 / PI970).","type":"string","enum":["alone","with-equipment","in-equipment"]},"unit":{"description":"Whether the figures describe a single \"cell\" or an assembled \"battery\". The thresholds differ: 20 Wh per cell against 100 Wh per battery.","type":"string","enum":["cell","battery"]},"wattHours":{"description":"Watt-hour rating. Required for lithium ion.","type":"number","exclusiveMinimum":0,"maximum":100000},"lithiumContentGrams":{"description":"Lithium content in grams. Required for lithium metal.","type":"number","exclusiveMinimum":0,"maximum":10000},"netWeightKgPerPackage":{"description":"Net weight of cells and batteries in one package. Decides the 5 kg Section II limit.","type":"number","exclusiveMinimum":0,"maximum":10000},"stateOfChargePercent":{"description":"State of charge as a percentage of rated capacity. Standalone lithium ion must not exceed 30% for air transport.","type":"number","minimum":0,"maximum":100},"cellsPerPackage":{"type":"integer","minimum":0,"maximum":100000},"batteriesPerPackage":{"type":"integer","minimum":0,"maximum":100000}},"additionalProperties":false}},"additionalProperties":false},"description":"One entry per SKU. Up to 500 per call; each is classified independently."}},"required":["items"],"additionalProperties":false},"MonitorRequest":{"type":"object","required":["sku","input"],"properties":{"sku":{"type":"string","maxLength":200},"input":{"$ref":"#/components/schemas/ClassifyRequest"},"webhookUrl":{"type":"string","format":"uri"}}},"Citation":{"type":"object","properties":{"edition":{"type":"string","enum":["49cfr","iata-dgr","imdg"]},"provision":{"type":"string"},"establishes":{"type":"string"}}},"CarrierEligibility":{"type":"object","properties":{"carrier":{"type":"string","enum":["ups","fedex","usps","amazon-fba"]},"carrierName":{"type":"string"},"ground":{"$ref":"#/components/schemas/Eligibility"},"air":{"$ref":"#/components/schemas/Eligibility"},"note":{"type":"string"},"authority":{"type":"string"},"authorityUrl":{"type":"string"}}},"Eligibility":{"type":"string","enum":["accepted","contract-required","restricted","prohibited","review-required"],"description":"accepted: ordinary terms. contract-required: needs an approved hazmat agreement. restricted: some services or below stated limits only. prohibited: not accepted. review-required: the carrier decides on documentation the API cannot see."},"LithiumDetermination":{"type":"object","properties":{"unNumber":{"type":"string","enum":["UN3480","UN3481","UN3090","UN3091"]},"packingInstruction":{"type":"string","enum":["PI965","PI966","PI967","PI968","PI969","PI970"]},"section":{"type":"string","enum":["IA","IB","I","II"]},"sizeBand":{"type":"string"},"lithiumBatteryMarkRequired":{"type":"boolean"},"classNineLabelRequired":{"type":"boolean"},"dangerousGoodsDeclarationRequired":{"type":"boolean"},"stateOfChargeCapPercent":{"type":["number","null"]},"passengerAircraft":{"type":"string","enum":["forbidden","permitted"]},"cargoAircraft":{"type":"string","enum":["forbidden","permitted"]},"requirements":{"type":"array","items":{"type":"string"}},"blockers":{"type":"array","items":{"type":"string"},"description":"Reasons this consignment cannot go as described."},"missing":{"type":"array","items":{"type":"object"}}}},"ClassificationResult":{"type":"object","properties":{"classificationId":{"type":["string","null"],"description":"Pass to the certificate endpoint."},"determination":{"type":"string","enum":["classified","not_regulated","needs_review"]},"isHazmat":{"type":["boolean","null"],"description":"null on needs_review — unknown is not the same as false."},"unNumber":{"type":["string","null"]},"properShippingName":{"type":["string","null"]},"hazardClass":{"type":["string","null"],"enum":["1","2.1","2.2","2.3","3","4.1","4.2","4.3","5.1","5.2","6.1","6.2","7","8","9",null]},"hazardDivision":{"type":["string","null"]},"subsidiaryRisks":{"type":"array","items":{"type":"string"}},"packingGroup":{"type":["string","null"],"enum":["I","II","III",null]},"labels":{"type":"array","items":{"type":"string"}},"specialProvisions":{"type":"array","items":{"type":"string"}},"ergGuide":{"type":["string","null"]},"limitedQuantityEligible":{"type":["boolean","null"]},"marinePollutant":{"type":["boolean","null"]},"lithium":{"oneOf":[{"$ref":"#/components/schemas/LithiumDetermination"},{"type":"null"}]},"carrierEligibility":{"type":"array","items":{"$ref":"#/components/schemas/CarrierEligibility"}},"confidence":{"type":["string","null"],"enum":["high","medium","low",null]},"matchScore":{"type":["number","null"]},"evidence":{"type":"array","items":{"type":"object"},"description":"Exactly what matched, where, and what it contributed to the score."},"alternatives":{"type":"array","items":{"type":"object"},"description":"Other entries that scored, shown rather than silently discarded."},"missingData":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"decides":{"type":"string"}}},"description":"What to supply next, and precisely what it would decide."},"reasoning":{"type":"array","items":{"type":"string"},"description":"Every step the engine took, in order, so the answer can be audited."},"citations":{"type":"array","items":{"$ref":"#/components/schemas/Citation"}},"ruleset":{"type":"object"}}},"SignedCertificate":{"type":"object","properties":{"payload":{"type":"object"},"signature":{"type":"string","description":"Compact JWS over the canonical payload JSON."},"algorithm":{"type":"string","enum":["EdDSA"]},"verifyWith":{"type":"string"}}}}},"x-ruleset":{"version":"2026.08.1","hash":"f31c40d32828554081ce3e567617cd8c","currency":{"49cfr":"49 CFR as revised through the 1 October 2025 annual revision","iata-dgr":"IATA DGR 67th edition (effective 1 January 2026)","imdg":"IMDG Code Amendment 42-24 (mandatory from 1 January 2026)"},"scope":"A curated subset of the 49 CFR 172.101 Hazardous Materials Table covering the substances and articles that appear in commercial parcel, e-commerce and FBA shipping, reconciled against the IATA DGR and the IMDG Code. Anything the table does not cover returns needs_review with the reason stated — it is never resolved to a plausible-looking guess."}}