{
 "openapi": "3.1.0",
 "info": {
  "title": "Marcana 3PL public API",
  "version": "2026-08-v1",
  "contact": {
   "name": "Marcana 3PL",
   "url": "https://marcana-3pl.com/contact",
   "email": "info@marcana-3pl.com"
  },
  "termsOfService": "https://marcana-3pl.com/privacy-terms",
  "x-versioning": "API-Version header equals the rate card version. Additive changes ship without notice; removals or renames are announced in /llms.txt at least 30 days ahead with Deprecation and Sunset headers.",
  "description": "Read-only pricing and estimate endpoints for AI assistants and agents, plus the website lead form. All prices are the published rates at https://marcana-3pl.com/pricing. No authentication. Do not send customer data to the estimate endpoint; it only needs volumes."
 },
 "servers": [
  {
   "url": "https://marcana-3pl.com"
  }
 ],
 "externalDocs": {
  "description": "Developer guide, MCP server and agent rules",
  "url": "https://marcana-3pl.com/developers/"
 },
 "components": {
  "schemas": {
   "Problem": {
    "type": "object",
    "description": "RFC 9457 problem details",
    "required": [
     "type",
     "title",
     "status"
    ],
    "properties": {
     "type": {
      "type": "string",
      "format": "uri"
     },
     "title": {
      "type": "string"
     },
     "status": {
      "type": "integer"
     },
     "detail": {
      "type": "string"
     },
     "code": {
      "type": "string",
      "enum": [
       "bad_body",
       "empty_batch",
       "batch_too_large",
       "not_found"
      ]
     },
     "docs": {
      "type": "string",
      "format": "uri"
     }
    }
   },
   "Estimate": {
    "type": "object",
    "properties": {
     "ok": {
      "type": "boolean"
     },
     "currency": {
      "type": "string"
     },
     "version": {
      "type": "string"
     },
     "recommended_plan": {
      "type": "object"
     },
     "priced_plan": {
      "type": "object"
     },
     "lines": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "label": {
         "type": "string"
        },
        "qty": {
         "type": "number"
        },
        "unit_price": {
         "type": "number"
        },
        "cost": {
         "type": "number"
        }
       }
      }
     },
     "usage_total": {
      "type": "number"
     },
     "estimated_monthly_total": {
      "type": "number"
     },
     "needs_custom_review": {
      "type": "boolean"
     },
     "custom_review_reasons": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "next_step_url": {
      "type": "string",
      "format": "uri"
     }
    }
   },
   "EstimateBatch": {
    "type": "object",
    "properties": {
     "ok": {
      "type": "boolean"
     },
     "count": {
      "type": "integer"
     },
     "results": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Estimate"
      }
     }
    }
   }
  }
 },
 "paths": {
  "/api/pricing.json": {
   "get": {
    "operationId": "getPricing",
    "summary": "Published rate card, plans, receiving hours and links",
    "responses": {
     "200": {
      "description": "Rate card JSON",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/api/estimate": {
   "get": {
    "operationId": "getEstimate",
    "summary": "Monthly estimate from volumes using the published rates",
    "parameters": [
     {
      "name": "boxes",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Inbound boxes per month"
     },
     {
      "name": "pallets_received",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Pallets received per month"
     },
     {
      "name": "pallets_stored",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Pallets of storage held on average"
     },
     {
      "name": "label_only_units",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Units per month that only need an FNSKU or UPC label"
     },
     {
      "name": "prep_units",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Units per month needing standard FBA or WFS prep"
     },
     {
      "name": "fragile_units",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Units per month needing fragile prep with bubble"
     },
     {
      "name": "orders",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Direct-to-consumer orders per month (Shopify, Amazon FBM, Walmart, TikTok Shop)"
     },
     {
      "name": "items_per_order",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Average items per order, default 1"
     },
     {
      "name": "pct_heavy",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Percent of orders over 2 lb, 0 to 100"
     },
     {
      "name": "inserts",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Orders per month that get a marketing insert"
     },
     {
      "name": "connections",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      },
      "description": "Number of connected sales channels"
     },
     {
      "name": "plan",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "essential",
        "growth",
        "scale"
       ]
      },
      "description": "Force a plan instead of the recommended one"
     },
     {
      "name": "container",
      "in": "query",
      "schema": {
       "type": "boolean"
      },
      "description": "Inventory arrives by container or floor-loaded freight"
     },
     {
      "name": "oversized",
      "in": "query",
      "schema": {
       "type": "boolean"
      },
      "description": "Oversized units"
     },
     {
      "name": "regulated",
      "in": "query",
      "schema": {
       "type": "boolean"
      },
      "description": "Regulated product (aerosol, alcohol, perfume, lithium, hazmat)"
     },
     {
      "name": "temperature",
      "in": "query",
      "schema": {
       "type": "boolean"
      },
      "description": "Temperature-sensitive product"
     },
     {
      "name": "lang",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "en",
        "es"
       ]
      },
      "description": "Language for the links returned"
     }
    ],
    "responses": {
     "200": {
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "recommended_plan": {
           "type": "object"
          },
          "lines": {
           "type": "array"
          },
          "estimated_monthly_total": {
           "type": "number"
          },
          "needs_custom_review": {
           "type": "boolean"
          },
          "next_step_url": {
           "type": "string"
          }
         }
        }
       }
      },
      "description": "Recommended plan, line items, estimated monthly total, and whether a custom review is needed"
     },
     "400": {
      "description": "Problem details",
      "content": {
       "application/problem+json": {
        "schema": {
         "$ref": "#/components/schemas/Problem"
        }
       }
      }
     }
    }
   },
   "post": {
    "operationId": "postEstimate",
    "summary": "Same as GET, with a JSON or form-encoded body. Send {\"scenarios\": [ ... ]} with up to 20 input objects to get one estimate per scenario (EstimateBatch).",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "boxes": {
          "type": "number",
          "minimum": 0
         },
         "pallets_received": {
          "type": "number",
          "minimum": 0
         },
         "pallets_stored": {
          "type": "number",
          "minimum": 0
         },
         "label_only_units": {
          "type": "number",
          "minimum": 0
         },
         "prep_units": {
          "type": "number",
          "minimum": 0
         },
         "fragile_units": {
          "type": "number",
          "minimum": 0
         },
         "orders": {
          "type": "number",
          "minimum": 0
         },
         "items_per_order": {
          "type": "number",
          "minimum": 0
         },
         "pct_heavy": {
          "type": "number",
          "minimum": 0
         },
         "inserts": {
          "type": "number",
          "minimum": 0
         },
         "connections": {
          "type": "number",
          "minimum": 0
         },
         "plan": {
          "type": "string",
          "enum": [
           "essential",
           "growth",
           "scale"
          ]
         },
         "container": {
          "type": "boolean"
         },
         "oversized": {
          "type": "boolean"
         },
         "regulated": {
          "type": "boolean"
         },
         "temperature": {
          "type": "boolean"
         },
         "lang": {
          "type": "string",
          "enum": [
           "en",
           "es"
          ]
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Estimate"
     },
     "400": {
      "description": "Unreadable body",
      "content": {
       "application/problem+json": {
        "schema": {
         "$ref": "#/components/schemas/Problem"
        }
       }
      }
     },
     "422": {
      "description": "Empty or oversized batch",
      "content": {
       "application/problem+json": {
        "schema": {
         "$ref": "#/components/schemas/Problem"
        }
       }
      }
     }
    }
   }
  },
  "/mcp": {
   "post": {
    "operationId": "mcp",
    "summary": "MCP server (Model Context Protocol, Streamable HTTP, JSON-RPC 2.0), read-only tools get_pricing, estimate_monthly_cost, list_services, get_contact_and_next_steps",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "jsonrpc",
         "method"
        ],
        "properties": {
         "jsonrpc": {
          "const": "2.0"
         },
         "id": {},
         "method": {
          "type": "string",
          "enum": [
           "initialize",
           "tools/list",
           "tools/call",
           "ping"
          ]
         },
         "params": {
          "type": "object"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "JSON-RPC response"
     },
     "202": {
      "description": "Notification accepted"
     },
     "400": {
      "description": "Parse error"
     }
    }
   }
  },
  "/.well-known/mcp.json": {
   "get": {
    "operationId": "getMcpServerCard",
    "summary": "MCP server card",
    "responses": {
     "200": {
      "description": "Server name, endpoint, transport and tools"
     }
    }
   }
  },
  "/api/leads": {
   "post": {
    "operationId": "submitLead",
    "summary": "Send a message or a quick review request to Marcana (creates a lead, emails the team, auto-replies to the sender)",
    "description": "Use only when a human has asked to contact Marcana and has provided their own details. Accepts JSON or application/x-www-form-urlencoded. Required: Email. Recommended: First name, Company, What you sell, Message, Need (fba, dtc, wfs, kitting, returns, container, other), _form_type (contact or quick_review), _lang (en or es).",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "Email"
        ],
        "properties": {
         "Email": {
          "type": "string",
          "format": "email"
         },
         "First name": {
          "type": "string"
         },
         "Last name": {
          "type": "string"
         },
         "Company": {
          "type": "string"
         },
         "Phone": {
          "type": "string"
         },
         "What you sell": {
          "type": "string"
         },
         "Message": {
          "type": "string"
         },
         "Need": {
          "type": "string"
         },
         "Units per month": {
          "type": "string"
         },
         "Boxes per month": {
          "type": "string"
         },
         "Pallets per month": {
          "type": "string"
         },
         "Timeline": {
          "type": "string"
         },
         "_form_type": {
          "type": "string",
          "enum": [
           "contact",
           "quick_review",
           "agent"
          ]
         },
         "_lang": {
          "type": "string",
          "enum": [
           "en",
           "es"
          ]
         }
        }
       }
      },
      "application/x-www-form-urlencoded": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ success: true, lead_id }"
     },
     "303": {
      "description": "Form posts without an Accept: application/json header are redirected back to the page"
     },
     "422": {
      "description": "Invalid email"
     },
     "429": {
      "description": "Rate limited, 5 leads per 10 minutes per IP"
     }
    }
   }
  }
 },
 "x-links": {
  "llms": "https://marcana-3pl.com/llms.txt",
  "llms_full": "https://marcana-3pl.com/llms-full.txt",
  "sitemap": "https://marcana-3pl.com/sitemap.xml",
  "pricing": "https://marcana-3pl.com/pricing",
  "plan_builder": "https://marcana-3pl.com/get-started/",
  "quick_review": "https://marcana-3pl.com/quick-review/",
  "whatsapp_community_es": "https://marcana-3pl.com/es/comunidad/"
 }
}