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://fregal-api.flamenco-dev.com/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,quantities}} — lanes requote warm); empty body = re-read
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
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" }
}
# → { "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.