{"openapi":"3.1.0","info":{"title":"FormNord 3D printing","version":"1.1.0","description":"Instant prices and ordering for 3D printing an STL or 3MF file in PETG or ABS, printed in Norway and shipped with Posten. Delivery to Norway only. Flow: 1) get the file to us (file_url, file_base64, stl_text, or an upload link the user opens), 2) POST /api/print/tilbud for a price, 3) POST /api/print/bestill with the user's details and explicit consent to get payment_url, which the user opens to pay with Vipps or card. Never ask for card details. The same tools are available over MCP at https://formnord.no/mcp.","contact":{"email":"kundeservice@formnord.no","url":"https://formnord.no/print/ai"},"termsOfService":"https://formnord.no/print/vilkar"},"servers":[{"url":"https://formnord.no"}],"paths":{"/api/print/info":{"get":{"operationId":"getPrintServiceInfo","summary":"Materials, colours, infill options, size limits, pricing model and delivery time","responses":{"200":{"description":"Service information"}}}},"/api/print/opplasting":{"post":{"operationId":"createUploadLink","summary":"Create a one-time upload page for the user's model file","description":"Use when the user has the file but you cannot send its contents. Give the user upload_url; after they upload, call getPrintQuote with upload_id. Valid 24 hours.","responses":{"200":{"description":"Upload link","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"upload_id":{"type":"string"},"upload_url":{"type":"string"},"expires_at":{"type":"string"}}}}}},"429":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}}}}},"/api/print/fil":{"post":{"operationId":"uploadModelFile","summary":"Upload a model file directly (multipart) and get fil_id","description":"For clients that can send HTTP. Returns fil_id and a printability check; use fil_id in getPrintQuote.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"fil":{"type":"string","format":"binary","description":".stl or .3mf, max 30 MB"}},"required":["fil"]}}}},"responses":{"200":{"description":"Uploaded; fil_id and model check"},"422":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"429":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}}}}},"/api/print/tilbud":{"post":{"operationId":"getPrintQuote","summary":"Get a price for a 3D model","description":"Provide exactly one of file_url, file_base64, stl_text, upload_id or file_id. If prisgrunnlag is \"estimat\" and slicing_status is \"pagar\", the exact price is ready within minutes at GET /api/print/tilbud/{tilbud_id}.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file_url":{"type":"string","description":"Direct https link to an .stl, .3mf or .zip file (max 500 MB; files over 30 MB are simplified automatically for pricing)."},"file_base64":{"type":"string","description":"The file as base64, for files up to 30 MB. Use createUploadLink for larger files."},"stl_text":{"type":"string","description":"ASCII STL content, for small generated models."},"upload_id":{"type":"string","description":"From createUploadLink, after the user has uploaded the file."},"file_id":{"type":"string","description":"fil_id from uploadModelFile."},"filename":{"type":"string"},"material":{"type":"string","enum":["PETG","ABS"],"default":"PETG"},"color":{"type":"string","description":"PETG: Svart, Hvit, Grå, Blå, Grønn, Rød. ABS: Svart, Hvit","default":"Svart"},"quantity":{"type":"integer","minimum":1,"maximum":500,"default":1},"colors":{"type":"array","items":{"type":"string"},"description":"Multicolour 3MF only: one colour name per slot, in slot order."},"infill":{"type":"integer","enum":[15,20,40,100],"default":20,"description":"15 light (lightning, 3 walls), 20 standard, 40 strong, 100 solid."},"zip_entry":{"type":"string","description":"For a zip with several models: which one to quote."}}}}}},"responses":{"200":{"description":"Quote: tilbud_id, pris.totalt (NOK incl. shipping) with breakdown, estimate, bestill_url."},"409":{"description":"upload_pending: the user has not uploaded the file yet.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"410":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"422":{"description":"The model cannot be printed as requested; see kode and grunn.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"429":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}}}}},"/api/print/tilbud/{tilbud_id}":{"get":{"operationId":"getQuoteStatus","summary":"Quote status: current price (updated after slicing), expiry, whether ordered, order status","parameters":[{"name":"tilbud_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Quote status"},"404":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}}}}},"/api/print/bestill":{"post":{"operationId":"createOrder","summary":"Order a quote on the user's behalf and get a payment link","description":"Only call after the user has given their details and explicitly confirmed that they accept the terms (https://formnord.no/print/vilkar) and have the right to use the model. Returns payment_url; the user pays there with Vipps or card. Calling again for the same quote returns the same order.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["quote_id","customer","accepted_terms","confirmed_rights"],"properties":{"quote_id":{"type":"string","description":"tilbud_id from getPrintQuote."},"customer":{"type":"object","required":["first_name","last_name","email","phone","address","postcode","city"],"properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string","description":"Norwegian mobile number."},"address":{"type":"string"},"postcode":{"type":"string","description":"4 digits; Norway only."},"city":{"type":"string"},"note":{"type":"string"}}},"accepted_terms":{"type":"boolean"},"confirmed_rights":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Order created (unpaid until the user pays)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"ordre_id":{"type":"integer"},"payment_url":{"type":"string"},"totalt_kr":{"type":"number"},"allerede_bestilt":{"type":"boolean"}}}}}},"404":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"409":{"description":"price_pending: slicing is still confirming the price; retry in a minute.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"410":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"422":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"429":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"502":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}},"503":{"description":"Error. kode is machine-readable, grunn is a Norwegian explanation for the user.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"kode":{"type":"string","enum":["rate_limited","invalid_request","invalid_input","not_printable","zip_entry_required","upload_pending","upload_link_expired","quote_not_found","quote_expired","consent_required","invalid_customer","price_pending","ordering_closed","order_failed"]},"grunn":{"type":"string"}}}}}}}}}}}