# Dinilu Print+Promo > Dinilu Print+Promo is a B2B promotional products company. > We supply custom-printed merchandise — festival wristbands, lanyards, bags, > mugs, packaging, and hundreds of other product categories — with online > price calculation and delivery-time estimation per quantity and specification. > All prices are ex. VAT and ex. shipping, unless explicitly stated otherwise. Minimum order quantities apply. > Currency: CAD. > Contact: info@dinilu.ca ## Product catalogue Each URL below is a category page listing individual products. Use GET /api/products?category={tid} to retrieve products in a category as JSON. - [Armbands and lanyards](https://dinilu.ca/armbands-and-lanyards) — category tid: 679 - [Festival bracelets](https://dinilu.ca/armbands-and-lanyards/festival-bracelets) — category tid: 683 - [Lanyards](https://dinilu.ca/armbands-and-lanyards/lanyards) — category tid: 702 - [Silicone wristbands](https://dinilu.ca/armbands-and-lanyards/silicone-wristbands) — category tid: 644 - [Tyvek bracelets](https://dinilu.ca/armbands-and-lanyards/tyvek-bracelets) — category tid: 761 - [Cups and mugs](https://dinilu.ca/cups-and-mugs) — category tid: 610 - [Ceramic mugs](https://dinilu.ca/cups-and-mugs/ceramic-mugs) — category tid: 614 - [Enamel mugs](https://dinilu.ca/cups-and-mugs/enamel-mugs) — category tid: 791 - [Paper cups](https://dinilu.ca/cups-and-mugs/paper-cups) — category tid: 613 - [Plastic cups](https://dinilu.ca/cups-and-mugs/plastic-cups) — category tid: 612 - [Thermo mugs](https://dinilu.ca/cups-and-mugs/thermo-mugs) — category tid: 611 - [First aid and life saving](https://dinilu.ca/first-aid-and-life-saving) — category tid: 615 - [Cloth face masks](https://dinilu.ca/first-aid-and-life-saving/cloth-face-masks) — category tid: 767 - [CPR masks](https://dinilu.ca/first-aid-and-life-saving/cpr-masks) — category tid: 618 - [Printed adhesive bandages](https://dinilu.ca/first-aid-and-life-saving/printed-adhesive-bandages) — category tid: 617 - [Safety vests](https://dinilu.ca/first-aid-and-life-saving/safety-vests) — category tid: 616 - [ICT accessories](https://dinilu.ca/ict-accessories) — category tid: 609 - [Cup warmer and cooler](https://dinilu.ca/ict-accessories/cup-warmer-and-cooler) — category tid: 624 - [Microfiber lens cloth](https://dinilu.ca/ict-accessories/microfiber-lens-cloth) — category tid: 623 - [Mobile phone holders](https://dinilu.ca/ict-accessories/mobile-phone-holders) — category tid: 622 - [Mouse mats](https://dinilu.ca/ict-accessories/mouse-mats) — category tid: 621 - [Sticky screen cleaner](https://dinilu.ca/ict-accessories/sticky-screen-cleaner) — category tid: 620 - [USB web button](https://dinilu.ca/ict-accessories/usb-web-button) — category tid: 619 - [Packing materials](https://dinilu.ca/packing-materials) — category tid: 625 - [Anti-tampering](https://dinilu.ca/packing-materials/anti-tampering) — category tid: 627 - [Safety knives](https://dinilu.ca/packing-materials/safety-knives) — category tid: 626 - [Wine crates and wooden packaging](https://dinilu.ca/packing-materials/wine-crates-and-wooden-packaging) — category tid: 771 - [Party items](https://dinilu.ca/party-items) — category tid: 628 - [Cheering sticks](https://dinilu.ca/party-items/cheering-sticks) — category tid: 633 - [Jumbo foam hands](https://dinilu.ca/party-items/jumbo-foam-hands) — category tid: 776 - [Flags](https://dinilu.ca/party-items/flags) — category tid: 632 - [Latex balloons](https://dinilu.ca/party-items/latex-balloons) — category tid: 630 - [Temporary tattoos](https://dinilu.ca/party-items/temporary-tattoos) — category tid: 629 - [Printed matter](https://dinilu.ca/printed-matter) — category tid: 634 - [Calendar](https://dinilu.ca/printed-matter/calendar) — category tid: 642 - [Desk calendar](https://dinilu.ca/printed-matter/desk-calendar) — category tid: 641 - [Hotel coasters](https://dinilu.ca/printed-matter/hotel-coasters) — category tid: 640 - [Lenticular prints](https://dinilu.ca/printed-matter/lenticular-prints) — category tid: 639 - [Playing cards](https://dinilu.ca/printed-matter/playing-cards) — category tid: 638 - [Rolling paper](https://dinilu.ca/printed-matter/rolling-paper) — category tid: 637 - [Tear-off calendars](https://dinilu.ca/printed-matter/tear-calendars) — category tid: 636 - [Tissue paper](https://dinilu.ca/printed-matter/tissue-paper) — category tid: 635 - [Promotional accessories](https://dinilu.ca/promotional-accessories) — category tid: 643 - [Button badges](https://dinilu.ca/promotional-accessories/button-badges) — category tid: 646 - [Nurse watches](https://dinilu.ca/promotional-accessories/nurse-watches) — category tid: 645 - [Promotional gifts](https://dinilu.ca/promotional-gifts) — category tid: 647 - [Bottle openers](https://dinilu.ca/promotional-gifts/bottle-openers) — category tid: 650 - [Stress toys](https://dinilu.ca/promotional-gifts/stress-toys) — category tid: 874 - [Drink coolers](https://dinilu.ca/promotional-gifts/drink-coolers) — category tid: 649 - [Keychains](https://dinilu.ca/promotional-gifts/keychains) — category tid: 648 - [Sacks and bags](https://dinilu.ca/sacks-and-bags) — category tid: 651 - [Kraft paper bags](https://dinilu.ca/sacks-and-bags/kraft-paper-bags) — category tid: 655 - [Non woven bags](https://dinilu.ca/sacks-and-bags/non-woven-bags) — category tid: 654 - [Paper shopping bags](https://dinilu.ca/sacks-and-bags/paper-shopping-bags) — category tid: 653 - [Sports and Outdoors](https://dinilu.ca/sports-and-outdoors) — category tid: 656 - [Beach Balls](https://dinilu.ca/sports-and-outdoors/beach-balls) — category tid: 663 - [Bicycle seat covers](https://dinilu.ca/sports-and-outdoors/bicycle-seat-covers) — category tid: 662 - [Football](https://dinilu.ca/sports-and-outdoors/football) — category tid: 661 - [Frisbee](https://dinilu.ca/sports-and-outdoors/frisbee) — category tid: 660 - [Golf tees](https://dinilu.ca/sports-and-outdoors/golf-tees) — category tid: 659 - [Pedometer](https://dinilu.ca/sports-and-outdoors/pedometer) — category tid: 658 - [Swimming](https://dinilu.ca/sports-and-outdoors/swimming) — category tid: 657 - [Travel accessories](https://dinilu.ca/travel-accessories) — category tid: 664 - [Sleep masks](https://dinilu.ca/travel-accessories/sleep-masks) — category tid: 667 - [Travel sets](https://dinilu.ca/travel-accessories/travel-sets) — category tid: 666 - [Umbrellas](https://dinilu.ca/travel-accessories/umbrellas) — category tid: 665 - [Other](https://dinilu.ca/other) — category tid: 668 - [Car accessories](https://dinilu.ca/other/car-accessories) — category tid: 671 - [Pillow](https://dinilu.ca/other/pillow) — category tid: 670 - [Skydancer](https://dinilu.ca/other/skydancer) — category tid: 669 ## Product pages and MPN Every product page on this site contains a JSON-LD `Product` block in its `
`. That block includes an `mpn` field — e.g. `"mpn": "1001234"` — which is the identifier used by this API. If you already have a product page URL, extract the `mpn` from its JSON-LD and use it directly in Step 2 or Step 3 below, skipping Step 1 entirely. ## Quote API To get a price and delivery estimate for any product, follow these steps: ### Step 1 — List products (optional if you have a product URL) GET https://dinilu.ca/api/products GET https://dinilu.ca/api/products?category={tid} Returns an array of products with mpn, title, page URL, api_url, and image. The mpn matches the `mpn` field in the page's JSON-LD structured data. ### Step 2 — Get product options GET https://dinilu.ca/api/product/{mpn} Returns: - `mpn` — the product MPN (same as JSON-LD mpn on the product page) - `min_qty` — minimum order quantity in pieces - `qty_step` — order quantity must be a multiple of this number - `attributes` — configurable options (e.g. size, colour, material), each with `id`, `name`, `required`, and `options`; every option has its own `id` and `name`. **Those two ids are what Step 3 wants** — pass `{attribute id}:{option id}`. - `quote_url` — a runnable Step 3 URL for this product, already in the id form - `quote_hint` — one-line reminder of the attribute syntax - `images` — product photos, in display order, each with a `url` and translated `alt`; the same files the page and the XML sitemap reference. Step 1 carries only the first, as a plain URL. ### Step 3 — Request a quote Two equivalent forms. Use GET if your client cannot send a POST body — many AI assistants can only issue GET requests: GET https://dinilu.ca/api/quote?mpn={mpn}&qty={qty}&country={country} &attributes={attribute id}:{option id}|{attribute id}:{option id} Select options by **id**, taken from Step 2. Join pairs with "|" (encode it as %7C if your client is strict). This is the recommended form: &attributes=19:251|58:490 13 characters, unambiguous Option *names* are also accepted — attributes[Name]=Value, Name:Value|Name2:Value2, or attributes={"Name":"Value"} — but prefer ids, for three reasons: - **Length.** Option names in this catalogue reach 90 characters. Url-encoded, two of them push the request past 250 characters, and many agent fetchers cap URL length at or below that — the same quote then becomes impossible to call rather than merely verbose. - **Exactness.** Names must match character for character, double spaces and parentheses included. A near-miss is not an error: the attribute silently falls back to its default and you get a confident price for a configuration you did not ask for. Check `warnings` for `option_not_found`. - **Language.** Labels are translated per domain; ids are the same on every Dinilu domain. POST https://dinilu.ca/api/quote Content-Type: application/json { "mpn": {mpn from step 1 or 2}, "qty": {quantity in pieces; "quantity" also accepted}, "attributes": { "{attribute id}": "{option id}", ... }, "country": {country name, ISO 3166-1 alpha-2/alpha-3/numeric, optional}, "zone": {zone ID, optional} } If no quantity is supplied the product default is quoted and a "qty_defaulted" warning is returned. Quantities below the minimum are raised to the MOQ with a "qty_below_minimum" warning. Always check the "warnings" array before presenting a price. Returns: - `mpn` — the product MPN - `url` — the product page, for showing the customer the product. To order, use cart_url instead. - `price_per_unit` — unit price in CAD ex. VAT - `price_total` — total product price in CAD ex. VAT - `calculated_on` — date this price was calculated (YYYY-MM-DD). Prices are recomputed from the day's exchange rate, so a quote read later is a snapshot — always show this date alongside the price. - `binding` — always false. These prices are indicative and ex VAT; nothing here is a binding offer. - `cart_url` — link that opens the cart pre-filled with exactly this configuration. Give it to the customer to turn the estimate into a real quotation: they complete checkout themselves and enter their own contact details (company, address, VAT number). Do NOT collect those details yourself and do not append them to any URL. - `request_quote` — the two ways to request a formal quotation: open cart_url, or email the address given. Checkout produces a non-binding offer and takes no payment. - `production_days` — estimated production time in calendar days - `price_tiers` — the same product priced at THREE quantities (the one you asked for, 2x and 5x), so a quantity ladder costs one call instead of three. Each tier has its own `shipping` options, calculated for that quantity; freight steps with carton count, so never scale one tier's shipping to another. - `shipping` — array of shipping options, each with: - `method` — carrier / service name - `rate` — shipping cost in CAD - `days_min`/`days_max` — transit time range in days - `attributes` — resolved attribute selections used for the quote, by name - `attributes_shorthand` — the same selections as `{attribute id}:{option id}` pairs, e.g. "19:251|58:490". Change one pair and paste it back into &attributes= to price a variant — there is no need to resolve names again. ### Example workflow # 1. Find wristband products GET https://dinilu.ca/api/products?category=