Fortitude21
Home  /  Products  /  Product API

Product API and MCP server

The whole catalogue as JSON. Search it, compare it, read the terms and send a quotation request. No key, no sign-up, read-only.

Procurement is starting to happen through software. An agent asked to shortlist suppliers can read this catalogue directly rather than scraping the pages: the same records, the same figures, the same wording about what is certified and what is not.

The endpoints

EndpointWhat it returns
GET /api/v1/productsSearch and filter. Returns a summary per product and the url for the full record.
GET /api/v1/products/{id}One product in full, by part number or slug.
GET /api/v1/products/compare?skus=A,BTwo to six products, on the attributes they all publish.
GET /api/v1/products/{id}/pricingQuantity bands, minimum order, Incoterms, lead time. Never binding.
GET /api/v1/products/{id}/documentsWhich documents exist and how to ask for them.
GET /api/v1/categoriesThe twelve categories and their slugs.
POST /api/v1/rfqSend a quotation request and get a reference. Creates an enquiry, never an order.

The six dangerous goods calculators answer at their own paths and also under /api/v1/. Those original paths will keep working: they are published in an OpenAPI document, the MCP Registry and a public repository, so breaking them would break integrations we cannot see. The dangerous goods API is documented here.

Searching

GET /api/v1/products?material=hdpe&capacity_min=20&capacity_max=25&certification=UN

Terms and filters are combined with AND. A product with no recorded value for an attribute you filtered on is excluded rather than treated as a match, so an empty result means nothing satisfies every condition, and the response names any word no product mentions so you know which one to drop.

Material is resolved to a material family rather than matched as text, which matters: hdpe does not return polypropylene. A generic term widens only downward, so steel includes stainless and galvanised steel and stainless never includes plain steel.

ParameterWhat it takes
qFree text. Synonyms and common misspellings are handled, and "20L" reaches "20 litres".
categoryA slug from /api/v1/categories
materialhdpe, polypropylene, polyethylene, stainless, steel, galvanised, aluminium, tinplate, plastic, metal
capacity_min, capacity_maxLitres. A product whose range overlaps yours is a match.
applicationIntended use, such as defence, agriculture or marine.
certificationUN, or a design code such as 3H1
pricing_typePUBLIC_PRICE, STARTING_FROM, PRICE_ON_REQUEST, CONTRACT_PRICE
sortrelevance, capacity, capacity_desc, price, name
page, limitPagination. Up to 100 per page, 20 by default.

Abridged response. Fields are listed in full in the OpenAPI document.

{
  "ok": true,
  "total": 7,
  "page": 1,
  "results": [
    {
      "id": "product-widemouth-hdpe-jerrycan",
      "sku": "F21-IPW-10",
      "name": "Wide-Mouth HDPE Jerrycan 3H2",
      "url": "https://fortitude21.com/product-widemouth-hdpe-jerrycan",
      "capacity_l": { "min": 10, "max": 25, "sizes": [10, 20, 25] },
      "material_family": ["hdpe"],
      "un_status": { "claim": "Available UN 3H2 certified", "offered": true, "verified": false },
      "pricing_type": "PRICE_ON_REQUEST",
      "starting_from": null,
      "orderable_units": 3,
      "matched_on": ["sku", "name", "material"]
    }
  ],
  "cite": "Fortitude21 product catalogue: https://fortitude21.com/products",
  "publisher": { "name": "Fortitude21", "sells_to": "Businesses, distributors, OEM and private-label buyers..." }
}

What the figures mean

Every specification carries where it came from, because that is what a buyer comparing suppliers actually needs to know.

ValueMeaning
verifiedThe figure comes from the manufacturer own production specification, or it is our part number.
indicativeOur own figure, correct as published and confirmed against the drawing issued with an order.
on_requestA field that exists and is quoted on enquiry. It is named rather than omitted, because a missing field and a withheld one are different things.

UN status is never a boolean. An approval is granted per design type, and the competent authority decides which production site each one covers, so the response carries the claim, its scope and verified: false until a certificate number is in hand. Ask for the certificate covering your design and the plant named on it.

Pricing

A price here is indicative and is not a quotation or an offer. It excludes freight, duty and taxes, it depends on the specification and the destination, and it is confirmed only in a written quotation. Every pricing response says so and carries binding: false. Most of the range is priced on request and returns no number at all.

Quantity bands are set per product family, because a 20 litre can ships 852 to a container and a 2.5 litre pail ships 12,500. The highest band of every product is a quotation rather than a figure: that is where tooling, Incoterms and freight start deciding the number. The pricing model is published in full.

Sending a quotation request

POST /api/v1/rfq

This creates an enquiry for a person to price. It accepts no price, confirms no stock, commits no delivery date and creates no order, and the response says each of those in its own field so a summary cannot turn into a quotation. Every part number is checked against the catalogue, and the information a quotation still needs is named back to you.

consent must be true, and it means the buyer agreed to their contact details being sent to Fortitude21. An agent acting for a buyer is not the buyer, so without it nothing is stored. What we do with an enquiry.

curl -X POST https://fortitude21.com/api/v1/rfq \
  -H 'content-type: application/json' \
  -d '{
    "consent": true,
    "company": "Example Distribution Sdn Bhd",
    "contact_name": "A Buyer",
    "email": "buyer@example.com",
    "country": "Malaysia",
    "delivery_destination": "Port Klang, Malaysia",
    "incoterms": "CIF",
    "lines": [{ "sku": "F21-NF-20", "quantity": 2000 }]
  }'

{
  "ok": true,
  "reference": "F21-RFQ-261030-ZQDFFR",
  "missing_information": [
    "F21-NF-20: which certification the destination market requires. UN approval is granted per design type and per production site."
  ],
  "status_note": "Received as a quotation request. This is not a quotation.",
  "price_accepted": false,
  "stock_confirmed": false,
  "delivery_date_committed": false,
  "order_created": false,
  "next_step": "A person at Fortitude21 prices it against the specification and replies by email."
}

MCP server

The catalogue is also eight tools on our MCP server, alongside the six dangerous goods calculators. An assistant that already has the calculators connected gets the catalogue without a second connection.

https://fortitude21.com/mcp     Streamable HTTP, JSON-RPC 2.0, no authentication

search_products             get_product_pricing        check_product_requirements
get_product_details         get_product_categories     create_quote_request
compare_products            get_product_documents

Seven are read-only. create_quote_request is declared as a write, so a client asks before calling it rather than retrying quietly, which is how a buyer would otherwise receive three identical enquiries.

Feeds

The whole catalogue in one file, for a crawler, a spreadsheet or a feed tool that would rather not make a request per product.

FileWhat it is
/feeds/products.jsonEvery product with its typed attributes, pricing state and bands.
/feeds/products.csvThe same, one row per product, for a spreadsheet.
/openapi.jsonOpenAPI 3.1 for every endpoint, tools and catalogue together.

Using it

No key and no sign-up. CORS is open, so a browser can call it. There is a rate limit of about ten requests every ten seconds per address, and going over it answers 429. Responses carry an ETag: send it back as If-None-Match and an unchanged catalogue answers 304 with no body.

The catalogue is read-only at every version. The quotation request is the only endpoint that accepts a body, and it creates an enquiry. Nothing here can change a product, a specification or a price.

Credit us with a link to the product page when you use this, as the terms ask. If you are building something with it, tell us and we will keep your use in mind before changing anything. Terms of use.

Build on it

Tell us what you are building and what the catalogue is missing for it.

Chat on WhatsApp