Drive an estimate from your own system, for example a web shop:
- Create the estimate with the customer's graphic, the materials they may choose and a designer link.
- Send your customer to the designer link, where they draw the parts on their graphic.
- Poll until they click Finish.
- Pull everything they drew, with the quote, nests and cut-file links.
All calls are team-scoped under /a/<team_slug>/estimating/api/v1/ and need an API key (see
the API overview). The examples use this shell setup:
export HOST=https://app.example.com
export AUTH="Authorization: Api-Key $API_KEY"
Create an estimate in one call#
/a/{team_slug}/estimating/api/v1/estimates/
Create an estimate in one call: fields, optional graphic (`file`), designer materials (`material_ids`, `default_material`) and a designer link (`designer_link`: true or options).
estimating_estimates_create ·
View in API reference
Send multipart/form-data (needed to include a file) or JSON. You need either name or file; everything else is
optional.
curl -sS -X POST "$HOST/a/acme/estimating/api/v1/estimates/" -H "$AUTH" \
-F "file=@postcard-a.pdf;type=application/pdf" \
-F "external_id=order-1001" \
-F "customer_name=C-102" \
-F "reference=PO-5555" \
-F "material_ids=7" -F "material_ids=8" \
-F "default_material=7" \
-F 'metadata={"order_id": 1001, "source": "webshop"}' \
-F 'designer_link={"role": "customer", "label": "Proof for C-102", "return_url": "https://example.com/orders/1001/done", "expires_in_days": 14}'
| Field | Notes |
|---|---|
name |
Up to 200 characters. Defaults to the file name, without its extension, when you send a file. |
customer_name, reference, notes |
Free text (customer up to 200, reference up to 100 characters). |
status |
draft (default), sent, won or lost. |
unit_system |
imperial (default) or metric: how the app shows lengths and areas. |
external_id |
Your own id, up to 100 characters, unique in the team. A duplicate gets 409 with existing_id. |
metadata |
Any JSON object up to 16 KB, returned as sent. In multipart, send it as a JSON string. |
file |
The graphic: PDF, PNG, JPG or WebP, up to 50 MB (images up to about 89 megapixels). It is also saved in Files, in the estimate's folder under Estimates. |
material_ids |
The materials offered in the designer, up to 500. Repeat the field in multipart, or send a JSON array. Empty or left out: every active material of the team. |
default_material |
The material the designer starts with. It must be in material_ids when that list isn't empty. |
designer_link |
true for a link with default options, or an object of link options. Leave it out for no link. |
parts |
Up to 500 parts sized by hand or priced by hand, for a quote without artwork. In multipart, send a JSON array string. |
price |
With parts: true prices every group before answering (within 10 seconds). |
The create is all or nothing: if any field or part fails, nothing is stored. When your team's storage is full the
graphic is refused with 507 and the code quota_exceeded (see Storage), and no estimate is
kept. Part errors come back by position:
{"parts": {"1": {"size": ["..."]}}}. The response (201) is the estimate. Besides
the fields above it has id, revision, totals (part_count, total_area_sq_in, total_cost, total_price),
documents (with their download URLs and page sizes), designer_links, designer_url (the newest active link, or null),
designer_submitted_at and data_url. With parts it also has parts (as the parts endpoints return
them) and quote.
A quote without artwork, in one call:
curl -sS -X POST "$HOST/a/acme/estimating/api/v1/estimates/" -H "$AUTH" -H "Content-Type: application/json" -d '{
"name": "Spring promo", "customer_name": "Larkfold Studio", "price": true,
"parts": [
{"name": "Postcard A", "size": "4x6", "quantity": 5000, "alt_quantities": [10000], "material": 41,
"route": "offset", "inks": "4/4", "external_id": "L-1"},
{"name": "Event poster", "width": 24, "height": 36, "unit": "in", "quantity": 10, "material": 7},
{"name": "Design fee", "route": "custom", "price_each": "75.00"}
]}'
The same in separate calls. Create with JSON, then add the file, set the materials and create a link:
/a/{team_slug}/estimating/api/v1/estimates/{id}/documents/
Add a PDF or image to the estimate (same validation as the upload page).
estimating_estimates_add_document ·
View in API reference
From Files. To add a file your team already has in Files, send its version's id (version_id, from
the Files API) instead of uploading it again. The document shows that version: its bytes aren't
copied, and a newer version of the file doesn't change the estimate. The same type and size rules apply (400 on
version_id); a version that isn't in your team's library, or whose file is in the trash, gets 404. Designer links
can't add files this way.
/a/{team_slug}/estimating/api/v1/estimates/{id}/documents/from-files/
Add a version from the team's Files library to the estimate: a PDF, PNG, JPG or WebP up to 50 MB.
estimating_estimates_add_document_from_files ·
View in API reference
Document downloads. A document's url and preview_url point at this API, never at file storage: fetch them
with the same Authorization header (or a signed-in session). The bytes come back as uploaded, under the original
file name; the preview is the first page as an image. Designer link pages get the same files through the link.
/a/{team_slug}/estimating/api/v1/documents/{id}/file/
The document's bytes (the PDF or image as uploaded), inline under its original file name.
estimating_documents_file ·
View in API reference
/a/{team_slug}/estimating/api/v1/documents/{id}/preview/
The document's first-page preview image (404 when it has none).
estimating_documents_preview ·
View in API reference
/a/{team_slug}/estimating/api/v1/estimates/{id}/materials/
Replace the designer's material allowlist ([] = all active materials) and default material.
estimating_estimates_set_materials ·
View in API reference
/a/{team_slug}/estimating/api/v1/estimates/{id}/
Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export.
estimating_estimates_partial_update ·
View in API reference
PATCH changes the header fields, external_id, metadata, material_ids and default_material. It refuses
file and designer_link, which only work on create. PUT on an estimate answers 405.
Designer links#
Designer links for customers and staff explains links from the app's side. A designer link is an unguessable URL (https://app.example.com/estimating/d/<token>/) that opens this one
estimate in the Takeoff designer, with no sign-in. The token in the URL is the credential: treat the link like a
password and revoke it when you're done.
/a/{team_slug}/estimating/api/v1/estimates/{id}/designer-links/
Create a designer link: an unguessable URL that opens this estimate's designer without login.
estimating_estimates_designer_links_create ·
View in API reference
| Option | Default | Meaning |
|---|---|---|
label |
empty | Your note, up to 120 characters. |
role |
customer |
Customer or Staff, see below. |
show_prices |
true |
Customer links: show sell prices. Off: measurements only. |
allow_uploads |
true |
Customer links: let them add more files. |
allow_parts |
false |
Customer links: let them add parts by size (see below). |
return_url |
empty | Where Finish sends the browser. http or https only. |
expires_in_days or expires_at |
never | 1 to 365 days from now, or a future date and time. Send one, not both. |
What each role can do. The server enforces this, not only the page.
| Customer | Staff | |
|---|---|---|
| Draw, measure, set scales | yes | yes |
| Pick materials | from material_ids |
from material_ids, and create new ones |
| Sell prices | when show_prices is on |
yes |
| Costs, margins, machine rates | never (removed from every response) | yes |
| Production settings, cut files, optimising a nest | no (403) |
yes |
| Edit the header (name, customer, status…) | no (403) |
yes |
| Add files | when allow_uploads is on |
yes |
| Add parts by size | when allow_parts is on: name, shape, size, quantity, material and inks only |
yes |
| Add boxes, booklets or labels | no (400) |
yes |
| Change a part your team set up | its quantity only (403 for anything else) |
yes |
| A box's plan, machines, steps and notices; the cost of dies and plates | never | yes |
A customer can edit and delete the parts they added. Their saves never remove a part your team added by size or a
price-only line, and never change its costs, hand prices, finishing or quantities to quote. Price-only lines can't be
added from a customer link (400). A customer sees a box line read-only, with its dies and plates as one-off rows
priced when show_prices is on; its production group (part-<uuid>) answers 404 on a customer link.
Manage links later with these:
/a/{team_slug}/estimating/api/v1/estimates/{id}/designer-links/
The estimate's designer links, newest first (revoked and expired ones included).
estimating_estimates_designer_links_list ·
View in API reference
/a/{team_slug}/estimating/api/v1/designer-links/{token}/
estimating_designer_links_retrieve ·
View in API reference
/a/{team_slug}/estimating/api/v1/designer-links/{token}/
estimating_designer_links_partial_update ·
View in API reference
/a/{team_slug}/estimating/api/v1/designer-links/{token}/
Revoke the link (sets revoked_at); its URL then answers 410 Gone.
estimating_designer_links_revoke ·
View in API reference
A revoked or expired link answers 410 Gone, and its page tells the visitor the link is no longer available.
Whatever they saved is kept.
Estimate lines#
An estimate's parts are its lines. A part is drawn on a page of the graphic, sized by hand (no graphic
needed), a box sized by its dieline, or a price-only item (a design fee, outsourced work). Every part has a
quantity, up to 3 other quantities to quote, a material, a route (roll for wide format, sheet for digital sheets,
offset, blank for made-to-size board, or custom for a price you type), inks and finishing.
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/
Add one sized part or price-only item, at the end of the list.
estimating_estimates_parts_create ·
View in API reference
| Field | Notes |
|---|---|
name, notes |
Free text. |
size |
The size as you would type it: 4x6, 24 x 36 in, 8 1/2 x 11, A4, 3 oval, 3.5x2 r0.125. Or send width and height with unit (in, mm, cm, ft or m; the estimate's own unit when left out), or width_in and height_in. |
shape |
rect, rounded (with corner_radius), oval, custom (with points: 3 to 500 [x, y] points in inches), or dieline for a box (see Boxes). |
dieline |
Boxes only: the definition (style, L, W, D, unit, basis, grain, params). |
die_design |
Boxes only, instead of dieline: the id of a single-up dieline of your tool library (a CAD dieline box); null turns it back into a box drawn from a dieline. |
quantity, alt_quantities |
1 to 1,000,000. Up to 3 other quantities, each different: quoted separately, never counted in the total. |
material or material_sku |
A material id, or the exact SKU of an active material. |
route |
roll, sheet, offset, blank or custom. Left out: the material's (a roll material runs on roll, a sheet stock on sheet, or offset when it runs on offset only; a box on a made-to-size grade runs on blank). |
inks |
4/0, 4/4, 4/1, 1/0, 4+PMS 185 C/1 or none. On sheet and offset an empty value becomes 4/0. |
finishing |
[{"id": 5, "count": null}]: operations from the finishing library. count is per piece for operations priced each; folding operations take a style (half, letter, z, gate, double_parallel, roll, accordion_4). An archived or unknown operation is left off, with a warnings entry. |
bleed |
In unit; left out: the group's. |
cost_each, price_each |
Decimal strings. On custom the price each is required to price the line. On any other route price_each overrides the computed price, and also prices a line that can't be computed yet. |
product, external_id |
The product the part came from; your own line id (up to 100 characters). |
family |
The part's product family: carton or corrugated on boxes, set by the server from the dieline style (a value you send on a box is ignored). Booklets and labels come in a later release; until then a family on any other part is 400. |
spec |
The family's options (see Boxes). Left out: kept; null: reset. An unknown or refused option comes back as {"spec": {"convert": ["..."]}}; options on a part with no family are 400. |
A custom part sent without a size is a price-only item ("kind": "item" says the same). Parts come back with
id, source (drawn, manual or item), description, the size in the estimate's unit and in inches, area,
perimeter, sides, family, spec, plan (a family part priced on its own: ups, press sheet, machines; null
otherwise), tooling (its one-off dies and plates: key, label, total_cost, total_price, billing, tool)
and price (total, each, tooling, pending, blocked; tooling is the one-off tooling billed on its own row,
not in total). Sizes of drawn parts come from the drawing:
changing one gets 400 (sending a part's own values back, as GET gave them, is fine).
Boxes#
A box is a part with "shape": "dieline" and a dieline: its outline, size, area and perimeter come from the
dieline, so size and points are refused on it (400), and so are width and height (or width_in,
height_in) unless they equal the box's blank: a box's own part, as GET gave it, can be sent back. The board
follows the part's material: the server stores the material's catalogue board, caliper and allowances in the dieline,
and keeps them until you update the box. A caliper_mm you send in the dieline is the box's own caliper: it wins over
the material's, also when the material changes, until you update the box. A box without all three sizes is saved and
waits for them, like a part with no size.
{"name": "Shipping box", "shape": "dieline", "material_sku": "C32-MTS", "route": "blank", "quantity": 1000,
"dieline": {"style": "fefco_0201", "L": 12, "W": 10, "D": 8, "unit": "in"}}
- Routes:
sheet(printed on sheets, cut on the cutting table, ganged with the flat parts on the same stock),offset(die-cut cartons, each priced on its own: press, die-cutter, folder-gluer and a die from your rate card; and litho-laminated corrugated: a corrugated grade onoffsetis laminated to an offset-printed sheet, withspec.litho_materialthe sheet stock andspec.litho_inksits inks, and needs a laminator),blank(board made to size: converted on a flexo folder-gluer or die-cut, or priced per blank by its rectangle: ft², m² or 1,000 ft²) andcustom. A box onrollgets400. A flat part onblankgets400. familyiscartonorcorrugated, from the style.specholds the costing options:convert(how the box is made:diefor die-cut and folder-gluer,tablefor the cutting table,ffgfor a flexo folder-gluer,nonefor board only,litho_lamfor litho-laminated; the route's default when left out),versions(artworks sharing one die, 1 to 50),tooling_billing(separate, the default: dies and plates on their own one-off row;included: in the line's price) and, on corrugated,print_panels(1, 2 or 4) andjoint(glued). A carton onoffsetor withconvert: die, and corrugated converted onblank, is priced on its own in production grouppart-<uuid>.- The die (die-cut and litho-laminated boxes, see Die on hand or a new die):
die_policyisprefer_on_hand(a die on hand that fits, else a new die; the team's default when left out),compare(the least all-in),standing(the die intool, else the cheapest one on hand) ornew;toolis the id of a die of your library to use (on hand; withdie_policy: standingalso one at the die maker or in repair);die_rush(true/false) adds the rate card's rush percentage to a new die;tool_accepted_near({"tool", "kind", "dist_mm", "geometry_hash"},nullclears it) makes a near match count for this box whilegeometry_hashis the part'sdieline_info.hash(it lapses when the box changes). An unknown policy, a die of another team or an archived one gets400on that key. A customer designer link'sspechas none oftool,die_policy,die_rushandtool_accepted_near; its save keeps the stored ones, and one sent gets403. - A size or option out of range comes back as
{"dieline": {"L": ["..."]}}. - Parts come back with
dieline,dieline_info(the blank's size and area, MSF per 1,000, outline, grain and line lengths, in inches) anddownloads(one URL per file format). - Update. A box keeps the geometry it was quoted with. To redraw it with the current box generator and its
material's current caliper and allowances, send its
dielinewithoutcaliper_mmandallowances.
A box from a CAD dieline#
Send die_design (the id of a folding carton or corrugated single-up dieline in Tools & dies, active and your team's)
instead of a dieline. The box takes its blank, rule lengths and family from it and never redraws it; its board
still follows the material. dieline comes back null, dieline_info.style.id is imported, and the part adds
die_design and die_design_summary (id, name, family, format, facts, file_version).
{"name": "Tuck box", "shape": "dieline", "die_design": 12, "material_sku": "SBS-18-2840", "route": "offset",
"quantity": 10000}
- Another team's, an archived or an unknown dieline, or one whose family is not folding carton or corrugated, gets
400{"die_design": ["..."]}; a stock of the other family gets400onmaterial. A dieline archived after the part took it stays on the part. - The single-up's
factsgive what the file can't:gluer(none,straight_line,crash_lock,four_corner,six_corner),glue_points,grain_axis. On a way of making that folds and glues (convertdie,ffgorlitho_lam) a box with no gluer class is blocked withimported_facts_missing; on the others it prices with the noticeimported_gluer_unknown. The part's blank is rebuilt from the single-up's current facts the next time the part is saved. downloadshaspdf,dxf,cf2(drawn from the stored single-up; no template, no fold check) andoriginal(a redirect to the die file it was read from, when there is one).- Designer links never get
die_designordie_design_summary, and customers can't pick one.
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/dieline/
Download a box part's dieline
estimating_estimates_parts_dieline ·
View in API reference
format is pdf (the dieline for the die maker or cutting table), template (for your designer), dxf, cf2 or
svg; pdf when left out. A CAD dieline box takes pdf, dxf, cf2 or original (302 to the
original file). It answers like the dieline export: the die files wait for the fold check
(409 foldcheck_failed, 503 while it runs), the template and the SVG never do. A flat part, a box with no size
yet, or a box that can't be drawn (its stock has no caliper, or its blank is too large; its downloads is null)
gets 404.
curl -sS -H "$AUTH" -OJ "$HOST/a/acme/estimating/api/v1/estimates/42/parts/$PART/dieline/?format=cf2"
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/
Parts of an estimate: drawn, sized and price-only items.
estimating_estimates_parts_list ·
View in API reference
Filter with source, route or external_id.
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/
Parts of an estimate: drawn, sized and price-only items.
estimating_estimates_parts_retrieve ·
View in API reference
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/
Change any field; fields left out keep their value.
estimating_estimates_parts_partial_update ·
View in API reference
PATCH changes only the fields you send.
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/
Parts of an estimate: drawn, sized and price-only items.
estimating_estimates_parts_destroy ·
View in API reference
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/bulk/
Create, update and delete parts in one all-or-nothing call (at most 500 operations).
estimating_estimates_parts_bulk ·
View in API reference
One call creates, updates and deletes up to 500 parts, all or nothing:
{"create": [...], "update": [{"id": "...", "quantity": 250}], "delete": ["..."]}. Errors come back by
section, even for one operation: {"create": {"0": {...}}, "update": {"<id>": {...}}, "delete": {"<id>": [...]}}.
Concurrency. Every write bumps the estimate's revision and answers with ETag: "<revision>". Send
If-Match: "<revision>" (or base_revision in the body) to get 409 with the current revision when someone
changed the estimate since you read it.
The quote#
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/quote/
The estimate's quote: lines, groups and totals, plus valid_until and currency.
estimating_estimates_quote ·
View in API reference
The quote has lines (one per part), groups (the parts sharing a route and a material) and the totals: price,
cost, margin, rounding, minimum, pieces and pending_groups, plus valid_until and currency. On a line,
total_price and total_cost are the all-in figures (material, printing, cutting, press, finishing and hand
prices); cost and price keep their earlier meaning, the material alone. Groups priced on sheets or offset are
worked out on the server: by default this call prices the ones without a fresh price first, within budget seconds
(10, at most 20); any left have pending: true and no price yet. refresh=0 answers at once.
Products and finishing#
Products are saved parts with defaults (size, quantity, route, stock, inks and finishing), picked when adding a line.
A starter set (postcard, flyer, business card, posters, banner, sticker, rigid sign, custom item, design fee) is
created the first time the team's products are read; it carries no prices. DELETE archives a product.
/a/{team_slug}/estimating/api/v1/products/
Product templates: saved parts with defaults.
estimating_products_create ·
View in API reference
Send defaults with any of the part fields above in inches (width_in, height_in, corner_radius_in, bleed_in)
plus size_presets, or part (a part id) to save a part's current fields. A material or finishing operation that
isn't in the library is left off with a warnings entry.
/a/{team_slug}/estimating/api/v1/products/{id}/used/
Record that the product was picked (it sorts first in the picker).
estimating_products_used ·
View in API reference
Finishing operations are priced per piece, per 1,000, per sheet, per ft² or m², per linear ft or m of perimeter, each
(grommets every so many inches) or per job, with a setup and a minimum. routes limits them to some routes (empty:
every route); per-sheet pricing needs sheet or offset. DELETE archives an operation.
/a/{team_slug}/estimating/api/v1/finishing/
Finishing operations: priced per piece, per 1,000, per sheet, by area, by perimeter, each or per job.
estimating_finishing_create ·
View in API reference
Stocks are materials: materials/ also takes runs_on (any, digital, offset), weight_label, weight_gsm,
caliper_in, finish, grain, paper_key (the same paper in other sheet sizes), preset_key and board_id (a
board of the shared board catalogue, for folding carton and corrugated board). The pricing units follow the
material: per sheet and per 1,000 sheets need a sheet size, per 1,000 ft² is for corrugated board and per 1,000 in²
for label stock; anything else is 400 on pricing_unit.
Set up a product family#
A team with no presses, machines or rate cards can quote a box at once with a hand price; to price it, one call creates what the family prices with. Nothing is ever created with prices you didn't send.
/a/{team_slug}/estimating/api/v1/family-setup/{family}/
Set up quoting for a product family: press, machines by role, the stock, tool rate cards and finishing by preset key, each with any of its fields.
estimating_family_setup ·
View in API reference
family is carton (the Tuck box: offset press, die-cutter, folder-gluer, board, die rate card, coating) or
corrugated (the Shipping box: flexo folder-gluer, corrugated grade, plate rate card, bundling). Every section is
optional and takes any field of its row:
| Section | Row |
|---|---|
press |
The team's default offset press, or a new one (preset_key: start from an offset press preset). |
machines |
By role: die_cutter, folder_gluer, window_patcher, laminator (carton); ffg, die_cutter, folder_gluer, laminator (corrugated). The team's default machine of that kind, or a new one (preset_key: a finishing machine preset of that kind). |
stock |
The stock of the family's product (18pt SBS 28 × 40 in, or C flute 32 ECT kraft made to size), or preset_key: another board preset of the same kind. |
tool_rates |
By tool type: steel_rule_die, foil_block, emboss_die (carton); flexo_plate, rotary_die, steel_rule_die (corrugated). |
finishing |
By finishing preset key, such as finish.aqueous_coating or finish.bundle_strap. |
{"estimate": 42,
"press": {"hourly_rate": "250", "plate_cost": "18", "speed_sph": 10000, "makeready_min_per_pass": 15},
"machines": {"die_cutter": {"hourly_rate": "160", "speed": 5000, "setup_min": 45},
"folder_gluer": {"hourly_rate": "120", "speed": 150, "speed_unit": "m_per_min", "setup_min": 30}},
"stock": {"price_per_unit": "0.60"},
"tool_rates": {"steel_rule_die": {"base_cost": "250", "cut_cost_per_in": "0.35", "crease_cost_per_in": "0.30"}},
"finishing": {"finish.aqueous_coating": {"price_per_unit": "0.02"}}}
A row that exists is only filled where it is empty (no value, 0, or a missing key of its settings), so the call can
be repeated and never overwrites a rate you set. The answer lists the ids of the rows it made (created), the fields
it filled (filled) and every row it touched (rows), and with estimate that estimate's
readiness list after the set-up. A refused value is 400 with the errors by section
({"machines": {"die_cutter": {"speed": ["..."]}}}) and nothing is written. Set the new stock on your lines with the
parts API. Booklets and labels come in a later release (404 until then).
Poll for the result#
When your customer clicks Finish in the designer, their work is saved, the link's submitted_at and the
estimate's designer_submitted_at are set, and the browser goes to return_url (or shows a thank-you message). They
can keep editing afterwards; a second Finish updates the times.
/a/{team_slug}/estimating/api/v1/estimates/
Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export.
estimating_estimates_list ·
View in API reference
# By your own id
curl -sS -G "$HOST/a/acme/estimating/api/v1/estimates/" -H "$AUTH" --data-urlencode "external_id=order-1001"
# Everything changed since your last poll
curl -sS -G "$HOST/a/acme/estimating/api/v1/estimates/" -H "$AUTH" --data-urlencode "updated_since=2026-09-25T00:00:00Z"
| Filter | Matches |
|---|---|
external_id |
Exactly. |
status |
draft, sent, won or lost (anything else is 400). |
q |
Text in the name, customer or reference. |
updated_since |
Estimates updated at or after an ISO 8601 date and time (400 if unreadable). URL-encode the + of a time-zone offset. |
The list is paged. Poll every 30 to 60 seconds; updated_at also changes on every save while
someone is drawing, so wait for designer_submitted_at.
/a/{team_slug}/estimating/api/v1/estimates/{id}/
Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export.
estimating_estimates_retrieve ·
View in API reference
The data export#
/a/{team_slug}/estimating/api/v1/estimates/{id}/data/
Everything generated for the estimate (schema_version 1): documents, scales, parts with outlines in inches, dimension lines, materials, the quote, production nests with cut-file URLs and designer links.
estimating_estimates_data ·
View in API reference
One JSON document with everything generated for the estimate. schema_version is 1: fields may be added, and a
rename or removal would bump the version. URLs are absolute. Lengths are in inches and areas in square inches; page
coordinates are PDF points (or pixels for images) from the top-left corner; money is in US dollars.
| Key | Contents |
|---|---|
estimate |
The estimate, as in the other calls. |
units |
The unit conventions above. |
documents[] |
Each file with its pages and their sizes. |
scales[] |
Each scale: the line drawn or the ratio, and inches per unit. |
parts[] |
Each part: name, material, quantity, the points as drawn, outline_in, width, height, area and perimeter, and its source, route, inks, sides, finishing, other quantities, description, hand prices and price. Boxes add dieline and dieline_info (null on other parts); every part has family (blank on flat work), spec and plan (null unless the part is priced on its own). |
dimension_lines[] |
Measurement lines and their lengths. |
materials[] |
Every material that is used, offered or the default. |
quote |
Price, cost and margin, per material group (with the nested roll length and cut time) and per part. |
production[] |
Per material group: machine, settings, the nest, cut time, placed pieces and cut_files links. |
designer_links[] |
Every link of the estimate. |
Warning: Not for customers as is
The export includes your costs and margins. Don't forward it to customers unchanged.
Changes. Parts sized by hand and price-only items have no graphic: their document, page and points_page
are null, a sized part's outline_in is its outline in inches and an item's is null, and kind can be item.
If your code reads parts[].document without checking for null, handle it or pass ?sources=drawn (a comma
list of drawn, manual, item). The quote always covers every part, so filtered parts may not add up to its
total. Quote lines gained the all-in total_price and total_cost; their cost and price are still the material
alone.
Nests and cut files#
Groups are named by route and material: roll-7, sheet-34, offset-34. A bare material id (7) still means its
roll group. Each roll group of an estimate is nested on its roll, and the quote uses the nested length. Nests run
automatically while someone draws. When a group's fresh is false, run one yourself:
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/nest/
Nest the group now with the Turbo solver (blocks for the time budget) and return the summary with pieces.
estimating_production_nest ·
View in API reference
With {"optimize": true} it searches for 10 seconds and keeps the current nest unless it finds a shorter one;
improved says which. Send revision to get 409 when the drawing changed since you read it.
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/cutfile/
Cut file of the current (fresh) nest.
estimating_production_cutfile ·
View in API reference
format is pdf, dxf or cff2; without it you get the cutting machine's own format. pages=beds gives one PDF
page per cutter bed. A group whose nest is missing or out of date, or whose material isn't cut, gets 400. Layouts
longer than 200 inches carry an X-Cut-File-Warning header.
A planned part (a carton on offset or die-cut, a corrugated box converted on blank, a litho-laminated box) is
priced alone in group part-<uuid>. Its summary has key, route, family, material, fresh, status,
blocked, notices, needs_rates, plan (ups, sheets, MSF …; for a die-cut box also the die, below), sheet
(the cost sheet: material, machine steps, finishing, tooling and outside lines with their cost and price),
alternates, compare (the other way of making it, filled by extras/) and equipment. nest/ plans it ({"force": true} plans again); GET quote/ plans the ones
without a fresh plan within its budget. PATCH takes equipment ({role: machine id}, null for the kind's
default), press, the sheet size, spoilage_pct, makeready_sheets, setup_sheets and plan_overrides (ups;
null clears a value). A blocked summary has fix_url, the page where it is fixed. cutfile/ answers 400: a box's
die line is its dieline download. save-tool/ adds the die the box's plan prices to the tool library as
ordered, with the stations of the plan's nest when its ups come from the nest (see below). Sheet, offset and
roll summaries carry finishing_timed ({part id: [{id, machine, units_in, time_s, cost, price, needs_rates}]}) for
finishing timed on a machine.
curl -sS -H "$AUTH" -OJ "$HOST/a/acme/estimating/api/v1/estimates/42/production/roll-7/cutfile/?format=dxf"
A die-cut or litho-laminated box's plan names its die: die_type (the dies matched: rotary_die on a rotary
die-cutter, else steel_rule_die), die_policy (the one in effect), die_options and die_vs. Each of
die_options has key (tool:<id> or new:<ups>), kind (standing or new), tool,
tool_number, ups, sheet_in, tier (exact, near or structural; empty for a new die), dist_mm,
reasons (why a die isn't used by itself: sheet_differs, not_mountable, not_on_hand, customer_die …),
usable, late, ready_on (a new die ordered today, from the rate card's lead time; a die at the die maker, its
expected date), customer_owned, and the money at the part's quantity: die_cost / die_price (a die on hand: 0
plus its missing companions, re-rule and wear), line_cost / line_price (everything but the die row),
total_cost / total_price (all-in); money is null on a die made for another sheet size when the board doesn't
come in that size or the press or die-cutter can't take it, and on a die of more than one up on a made-to-size board
(listed, never used). Exactly one option has chosen: true unless the box is blocked (die_sheet_stock: the picked
die's sheet size isn't a size of the board, or the press or die-cutter can't take it). die_vs is the cheapest
other option that could be used, as key, kind, ups, tool_number and delta_cost / delta_price (its all-in
minus the chosen one's), or null. On a die on hand the plan's ups_basis is tool and notices has
tool_reused, with die_cheaper_at when a new die would be cheaper all-in at the quantity or an alternate and
die_life_exceeded when the quantity or an alternate passes the die's life. A die on hand whose extras need a rate
card the team doesn't have (a missing companion, a re-rule) adds tool_rate to needs_rates. Each of alternates
includes the die's extras at its own quantity (a re-rule or wear the main quantity doesn't need). Designer links
never get plan.
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/save-tool/
estimating_production_save_tool ·
View in API reference
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/
Production summaries for every material group with scaled parts (rows created on demand).
estimating_production_list ·
View in API reference
/a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/
Change a group's settings.
estimating_production_partial_update ·
View in API reference
Box dielines#
The box and carton generator has its own endpoints under /a/<team_slug>/dielines/api/v1/. Every call that makes a
dieline takes a definition: the style, the three sizes and, optionally, the board and the style's options.
{"definition": {"style": "rte", "L": 2.5, "W": 1.5, "D": 6, "unit": "in", "basis": "inside",
"board_id": "board.sbs_c1s_18pt", "params": {"tuck_len": 15}}}
GET styles/ lists the styles with their options, ranges and defaults, and GET boards/ lists the boards with your
team's board materials (a board material with no catalogue board has board_id null). Option lengths are always
millimetres, whatever unit says. A definition may carry allowances: carton_k (0.5 to 2) for carton boards;
a_l_mm, a_w_mm and a_d_mm (all three, 0 to 50) and joint_mode for corrugated. Keys left out are the board's.
/a/{team_slug}/dielines/api/v1/preview/
Preview a dieline
dielines_preview ·
View in API reference
A definition with errors gets 400 with {"issues": [...]}: each issue has a code, a severity, the field it is
about (L, board_id, params.tuck_len, allowances.carton_k…) and a readable message (every code is listed
under Size and option messages). Warnings and notes come back with a successful
preview and never block it.
/a/{team_slug}/dielines/api/v1/check/
Run the fold check
dielines_check ·
View in API reference
The fold check folds the box in 3D and looks for clashes. Most sizes answer at once; a slow one answers 202 with
{"status": "running", "hash"}, and you poll check/<hash>/ until the report arrives. Results are kept per size, so
the same definition is checked once.
/a/{team_slug}/dielines/api/v1/export/
Download a dieline file
dielines_export ·
View in API reference
format is pdf (the dieline for the die maker or cutting table), template (the same lines plus bleed, glue areas
and labels, for your designer), dxf, cf2 or svg. The PDF, DXF and CF2 wait for the fold check: a size that
fails it gets 409 with {"code": "foldcheck_failed", "report"}, and 503 means the check is still running. The
template and the SVG are always available. The same definition always gives the same bytes.
curl -sS -H "$AUTH" -H "Content-Type: application/json" -OJ \
-d '{"definition": {"style": "fefco_0201", "L": 12, "W": 10, "D": 8, "unit": "in"}, "format": "cf2"}' \
"$HOST/a/acme/dielines/api/v1/export/"
/a/{team_slug}/dielines/api/v1/save/
Save the dieline PDF to Files (an imported single-up: its fold)
dielines_save ·
View in API reference
Saving stores the dieline PDF in Files with its style, size, board and generator. Send target_file to save a new
version of a file you saved before.
/a/{team_slug}/dielines/api/v1/open/
Open a dieline saved in Files, or an imported single-up
dielines_open ·
View in API reference
A single-up from Tools & dies#
An imported single-up dieline (a shape from a die file you imported into
Tools & dies) opens in the Box designer read-only. Send {"design": <id>} in
place of a definition:
open/returns the read-only payload: the design, its drawing, the export formats and a link to the original file.structure/folds it in 3D with its saved fold.export/takes{"design": <id>, "format": "pdf" | "dxf" | "cf2" | "svg"}and returns the stored geometry as it was imported: nothing is regenerated, and there is no artwork template.save/takes{"design": <id>, "fold": {"angles": {"<crease id>": 90}, "root_panel": "<panel id>"}}and returns{structure, scene}."fold": nullgoes back to the default fold.
A fold that names creases the dieline doesn't have gets 400 with {"code": "invalid_fold"}, and a single-up with
no panels to fold gets 409 with {"code": "no_structure"}.
Previews allow 600 requests a minute per user; checks, structures, downloads and saves 60.
| Method | Path | What it does |
|---|---|---|
| GET | /a/{team_slug}/dielines/api/v1/boards/ | List the boards |
| POST | /a/{team_slug}/dielines/api/v1/check/ | Run the fold check |
| GET | /a/{team_slug}/dielines/api/v1/check/{digest}/ | Poll a running fold check |
| POST | /a/{team_slug}/dielines/api/v1/export/ | Download a dieline file |
| POST | /a/{team_slug}/dielines/api/v1/open/ | Open a dieline saved in Files, or an imported single-up |
| POST | /a/{team_slug}/dielines/api/v1/preview/ | Preview a dieline |
| POST | /a/{team_slug}/dielines/api/v1/save/ | Save the dieline PDF to Files (an imported single-up: its fold) |
| POST | /a/{team_slug}/dielines/api/v1/structure/ | The 3D structure and scene |
| GET | /a/{team_slug}/dielines/api/v1/styles/ | List the box styles |
| GET | /a/{team_slug}/dielines/api/v1/styles/{style_id}/thumbnail.svg | A style's thumbnail (SVG) |
Errors and limits#
| Status | When |
|---|---|
400 |
Invalid fields, such as metadata that isn't an object or is over 16 KB; a material of another team or archived; a bad file; file or designer_link on PATCH; an unknown status filter. |
403 |
No valid key, not a member of the team, or a designer link doing something its role can't. |
404 |
The estimate, material, link or Files version isn't in this team. |
409 |
external_id already used ({"external_id": [...], "existing_id": 41}), a stale revision, or {"busy": true} while another request is pricing the same group (try again shortly). |
429 |
Too many pricing requests: nest and extras allow 60 a minute per user or designer link. |
410 |
The designer link was revoked or has expired. |
413 |
A JSON body over 5 MB. |
507 |
Your team's Files storage is full: a graphic or document upload is refused (quota_exceeded). |
| Limit | Value |
|---|---|
| Graphic | PDF, PNG, JPG or WebP, up to 50 MB; images up to about 89 megapixels |
metadata |
A JSON object up to 16 KB |
external_id |
100 characters, unique in the team |
material_ids |
500 ids |
| One estimate | 2,000 parts, 200 scales, 500 points per polygon, 50,000 drawn or custom outline points in total |
| A part | quantity 1 to 1,000,000; up to 3 other quantities; sizes 0.01 to 2,400 in; up to 12 finishing operations |
| Parts per call | 500 (one-call create, bulk) |
| Designer link expiry | 1 to 365 days, or never |
| List page | 100 estimates |
Every estimating endpoint#
Materials (the price list the designer offers) are managed with the materials/ endpoints; deleting one archives
it. The takeoff, snap-point and thumbnail endpoints serve the Takeoff workspace itself.
The takeoff sync. PUT takeoff/ replaces the whole drawing: {base_revision, scales, shapes, parts_scope}. With
"parts_scope": "all" any part missing from shapes is deleted. Without it, as older integrations call it, only
missing drawn parts and dimension lines are deleted: parts sized by hand and price-only items are kept. On a part
that already exists, a quoting field you leave out (route, inks, finishing, other quantities, bleed, product, hand
prices, shape and size) keeps its value, and null resets it.
| Method | Path | What it does |
|---|---|---|
| GET | /a/{team_slug}/estimating/api/v1/designer-links/{token}/ | estimating_designer_links_retrieve |
| PATCH | /a/{team_slug}/estimating/api/v1/designer-links/{token}/ | estimating_designer_links_partial_update |
| DELETE | /a/{team_slug}/estimating/api/v1/designer-links/{token}/ | Revoke the link (sets revoked_at); its URL then answers 410 Gone. |
| GET | /a/{team_slug}/estimating/api/v1/documents/{id}/file/ | The document's bytes (the PDF or image as uploaded), inline under its original file name. |
| GET | /a/{team_slug}/estimating/api/v1/documents/{id}/preview/ | The document's first-page preview image (404 when it has none). |
| GET | /a/{team_slug}/estimating/api/v1/documents/{id}/snap-points/ | Vector vertices of the artwork (page units) for snapping. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/ | Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export. |
| POST | /a/{team_slug}/estimating/api/v1/estimates/ | Create an estimate in one call: fields, optional graphic (`file`), designer materials (`material_ids`, `default_material`) and a designer link (`designer_link`: true or options). |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/ | Parts of an estimate: drawn, sized and price-only items. |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/ | Add one sized part or price-only item, at the end of the list. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/ | Parts of an estimate: drawn, sized and price-only items. |
| PATCH | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/ | Change any field; fields left out keep their value. |
| DELETE | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/ | Parts of an estimate: drawn, sized and price-only items. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/{part_id}/dieline/ | Download a box part's dieline |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/parts/bulk/ | Create, update and delete parts in one all-or-nothing call (at most 500 operations). |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/ | Production summaries for every material group with scaled parts (rows created on demand). |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/ | estimating_production_retrieve |
| PATCH | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/ | Change a group's settings. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/cutfile/ | Cut file of the current (fresh) nest. |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/extras/ | Alternate quantities and route compares of a sheet or offset group (staff): at most 24 re-prices and 8 s per call, `focus` (a part id) first; `pending: true` means call again for the rest. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/layout/ | estimating_production_layout |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/nest/ | Nest the group now with the Turbo solver (blocks for the time budget) and return the summary with pieces. |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/production/{key}/save-tool/ | estimating_production_save_tool |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{estimate_pk}/quote/ | The estimate's quote: lines, groups and totals, plus valid_until and currency. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{id}/ | Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export. |
| PATCH | /a/{team_slug}/estimating/api/v1/estimates/{id}/ | Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export. |
| DELETE | /a/{team_slug}/estimating/api/v1/estimates/{id}/ | Estimates of the team: header fields, integration data (external_id, metadata), the designer's material allowlist, designer links and the full data export. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{id}/data/ | Everything generated for the estimate (schema_version 1): documents, scales, parts with outlines in inches, dimension lines, materials, the quote, production nests with cut-file URLs and designer links. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{id}/designer-links/ | The estimate's designer links, newest first (revoked and expired ones included). |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{id}/designer-links/ | Create a designer link: an unguessable URL that opens this estimate's designer without login. |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{id}/documents/ | Add a PDF or image to the estimate (same validation as the upload page). |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{id}/documents/from-files/ | Add a version from the team's Files library to the estimate: a PDF, PNG, JPG or WebP up to 50 MB. |
| PUT | /a/{team_slug}/estimating/api/v1/estimates/{id}/materials/ | Replace the designer's material allowlist ([] = all active materials) and default material. |
| GET | /a/{team_slug}/estimating/api/v1/estimates/{id}/takeoff/ | Everything the takeoff workspace needs: documents, scales, shapes, materials and the quote. |
| PUT | /a/{team_slug}/estimating/api/v1/estimates/{id}/takeoff/ | Full-state sync: {base_revision, scales, shapes, parts_scope}. |
| POST | /a/{team_slug}/estimating/api/v1/estimates/{id}/thumbnails/ | Replace a part's thumbnail (PNG). |
| POST | /a/{team_slug}/estimating/api/v1/family-setup/{family}/ | Set up quoting for a product family: press, machines by role, the stock, tool rate cards and finishing by preset key, each with any of its fields. |
| GET | /a/{team_slug}/estimating/api/v1/finishing/ | Finishing operations: priced per piece, per 1,000, per sheet, by area, by perimeter, each or per job. |
| POST | /a/{team_slug}/estimating/api/v1/finishing/ | Finishing operations: priced per piece, per 1,000, per sheet, by area, by perimeter, each or per job. |
| GET | /a/{team_slug}/estimating/api/v1/finishing/{id}/ | Finishing operations: priced per piece, per 1,000, per sheet, by area, by perimeter, each or per job. |
| PATCH | /a/{team_slug}/estimating/api/v1/finishing/{id}/ | Finishing operations: priced per piece, per 1,000, per sheet, by area, by perimeter, each or per job. |
| DELETE | /a/{team_slug}/estimating/api/v1/finishing/{id}/ | Archives the row. |
| GET | /a/{team_slug}/estimating/api/v1/materials/ | estimating_materials_list |
| POST | /a/{team_slug}/estimating/api/v1/materials/ | estimating_materials_create |
| GET | /a/{team_slug}/estimating/api/v1/materials/{id}/ | estimating_materials_retrieve |
| PATCH | /a/{team_slug}/estimating/api/v1/materials/{id}/ | estimating_materials_partial_update |
| DELETE | /a/{team_slug}/estimating/api/v1/materials/{id}/ | Archives the material. |
| GET | /a/{team_slug}/estimating/api/v1/products/ | Product templates: saved parts with defaults. |
| POST | /a/{team_slug}/estimating/api/v1/products/ | Product templates: saved parts with defaults. |
| GET | /a/{team_slug}/estimating/api/v1/products/{id}/ | Product templates: saved parts with defaults. |
| PATCH | /a/{team_slug}/estimating/api/v1/products/{id}/ | Product templates: saved parts with defaults. |
| DELETE | /a/{team_slug}/estimating/api/v1/products/{id}/ | Archives the row. |
| POST | /a/{team_slug}/estimating/api/v1/products/{id}/used/ | Record that the product was picked (it sorts first in the picker). |