AFN API documentation

One funnel for every fabrication process: quote → refine → checkout → track. Live processes: fdm_print and resin_print (3D printing), cnc, sheetmetal, laser_cut, decal (custom stickers), print (paper — cards, flyers, posters), and apparel, US shipping. AFN speaks UFP — the Universal Fabrication Protocol. The canonical schema reference is the protocol spec; the machine-readable version is openapi.json.

Authentication

curl -X POST https://agenticfabricationnetwork.ai/v1/agents -H 'content-type: application/json' -d '{"name":"my-agent"}'
# → { "api_key": "ufp_sk_..." }   (shown once — store it)
# Send on every call:   Authorization: Bearer ufp_sk_...

Endpoints

PathAuth
POST/v1/agentsSelf-serve API key issuance
GET/v1/capabilitiesProcesses, materials, cuts, size/qty ranges — live JSON
POST/v1/fileskeyUpload artwork/STL/STEP/DXF (multipart file) or register a URL (JSON {url})
POST/v1/quoteskeyFabrication request → ranked offers with prices, ETAs, previews. Streams: status "quoting" answers fast with the quickest vendors; the rest land on re-read
GET/v1/quotes/:idkeyRe-read a quote — LIVE state: offers stream in while status is quoting; previews resolve asynchronously
POST/v1/quotes/:id/refinekeyNarrow with added constraints (incl. a processes lane filter — null clears it), or change the spec ({spec:{material,color,finish,quantities}} — lanes requote warm; a finish rides finish-capable lanes, printer lanes keep the color); empty body = re-read
POST/v1/quotes/:id/previewkeyThe SOFT quote: refine's exact body, planned but never launched — how many distinct fabricators (and which lanes) the network would ask for the refined part, plus the exclusion notes. Creates nothing (no child quote, no vendor call, no supersede, no demand row): fire one per edit. 200, never 201
POST/v1/checkoutkeyCreate order + hosted payment link for the user
GET/v1/orderskeyYour agent's recent orders (newest first)
GET/v1/orders/:idkeyStatus, ETA, tracking, event log
POST/v1/orders/:id/reviewkeyVerified-purchase vendor review: {stars, comment?, facets?} — one per order, resubmit to update
GET/v1/parts/:idkeyInspect a part number; reorder via spec.part_number on /v1/quotes
GET/quotes/:id/designDownload just the bare design file
GET/v1/ufp/spec.schema.jsonJSON Schema of the .ufp part spec (ufp.json spec: material, color, finish, quantities, thickness_in, tapping, inserts, bends) — the exact record shapes refine accepts. Manifest schema: /v1/ufp/ufp.schema.json
Every offer carries vendor_rating{stars, review_count, facets} built from verified-purchase reviews only. The count is always the honest number of reviews on file.
More protocol docs: the vendor-hosted HTTP binding (/docs/vendor-binding.md — sell to agents by hosting five endpoints), reputation records and the reliability constraint (/docs/reputation.md), off-network transaction attestations (/docs/attestations.mdPOST /v1/attestations, vendor-key authed), and honest, cited materials intelligence — specs, stronger/hotter/outdoor ladders, finishes, caveats first (/docs/materials.md).

Quote request

POST /v1/quotes
{
  "process": "decal",                       // or "fdm_print" — or omit: AFN detects
                                            // the file kind and routes it (see below)
  "spec": {
    "file_id": "f_...",                     // from POST /v1/files
    "size_in": { "width": 3, "height": 3 }, // decal, optional (default 3x3)
    "cut": "triangle",                      // FREE-FORM — pass the user's words. Known cuts
                                            // (contour|square|oval|kiss_cut) match exactly;
                                            // anything else returns closest-match offers with
                                            // a substitutions note, and the ask is logged
    "material": "vinyl",                    // free-form too; omit = constraint-compliant options
    "quantities": [1]                       // ask for what the user wants, even 1 — vendors
                                            // with a higher minimum quote AT their minimum
                                            // and set requested_quantity on the offer
  },
  "constraints": {
    "ship_to_zip": "78701",                 // omit if unknown — prices stay all-in, shipped to
                                            // the network's assumed US destination, declared
                                            // on routing.ship_to { zip, assumed: true }
    "deadline": "2026-07-13",               // drop offers that can't arrive in time
    "processes": ["sheetmetal"],            // lane filter — quote ONLY these processes;
                                            // on refine: inherited, and null clears it
                                            // ("show everything again")
    "outdoor_rated": true,
    "submersible": true,                    // "must survive pool water"
    "max_budget_cents": 3500                // all-in cap
  }
}

For fdm_print: spec.file_id is an STL or STEP (converted server-side); optional material (pla|petg|asa), color, quantities.

For print: spec.file_id is print-ready artwork (PDF preferred, PNG/JPEG accepted); optional product (business_cards|flyers|posters — omit to quote every kind the artwork fits), free-form size ("letter", "24x36"), free-form paper ("matte", "glossy", "recycled"), sides (single|double), quantities. Deadline, budget, and durability constraints filter print offers like any other process; product kinds, sizes, and stocks are discoverable via GET /v1/capabilities.

For sheetmetal: spec.file_id is a DXF flat pattern or STEP model; free-form material (canonical mild_steel|aluminum_5052|stainless_304 — "steel", "5052", "stainless" resolve), optional thickness_in (quoted at the nearest stocked gauge), optional units (mm|in, DXF only, default mm), optional bend_count (> 0 prices CNC bending), free-form finish (as_cut default, deburred, powder_coat), quantities. Filterable criteria: outdoor_rated drops bare mild steel (it rusts) while aluminum/stainless pass — and upgrades unpinned mild steel to a protective powder_coat finish; submersible matches nothing (no vendor claim); deadline and budget narrow as usual. Material attributes, per-material thicknesses_in, and finishes are discoverable via GET /v1/capabilities.

Auto-routing

Omit process and AFN detects the file kind — artwork (png/jpg/svg/pdf), stl, step, dxf — and quotes every process that can make it, fanning out over a small default material set per process. The response adds a routing object: {detected_file_kind, candidates, also_possible, viewer_mesh_url}. also_possible lists processes AFN can't quote yet (e.g. pcb) with a reason; each is logged as a demand signal that drives vendor sourcing. viewer_mesh_url (mesh/BREP uploads only) serves a face-classified binary viewer mesh (AFVM v1) that derives lazily — poll it until 200. Passing process explicitly behaves exactly as before.

Offers include price_basis: vendor_api (live vendor quote), cached_matrix (AFN's continuously refreshed price table), or estimate (geometry-based). Caveat estimates to your user. Every offer carries a preview — the vendor's own product render of the artwork with those exact options; poll the quote until preview.status is ready.

Checkout

POST /v1/checkout
{
  "offer_id": "of_...",
  "shipping_option_id": "express",          // from the offer's shipping_options
  "ship_to": { "name": "...", "street1": "...", "city": "...", "state": "TX", "zip": "78701" },
  "contact": { "email": "buyer@example.com" },
  "coupon_code": "AFN-XXXXXX"               // optional — only if the user gave you one
}
# → { "order_id": "ord_...", "checkout_url": "https://checkout.stripe.com/...", "total_cents": 4230 }

Hand checkout_url to your user — never collect card details yourself. AFN is the merchant of record and places the vendor order automatically after payment. Lifecycle: pending_payment → paid → placing → placed → in_production → shipped → delivered.

Connect your agent (MCP)

AFN speaks standard MCP over Streamable HTTP — one endpoint serves ChatGPT, Claude, Gemini, Cursor, Copilot, and every other MCP client. Tools: get_fabrication_quote, refine_quote, create_checkout, get_order_status, list_orders, leave_review. ChatGPT additionally renders an embedded offer-comparison widget; every other client gets the same results as complete text.

ClientSetup
ChatGPTSettings → Apps & Connectors → create a connector with the /mcp URL
Claude Code / Desktop / claude.aiclaude mcp add --transport http ufp <mcp-host>/mcp (or add a custom connector in claude.ai settings)
Gemini CLIadd {"ufp": {"httpUrl": "<mcp-host>/mcp"}} under mcpServers in ~/.gemini/settings.json
Cursor / VS Code Copilot / othersadd a remote (Streamable HTTP) MCP server pointing at <mcp-host>/mcp
Custom agents (LangChain, Agents SDK, ADK…)use plain REST with openapi.json — same funnel, same offers
Design files without ChatGPT's attachment channel: pass a public https URL or a base64 data: URL in the design_file tool parameter — AFN fetches and stores it either way.