{"openapi":"3.1.0","info":{"title":"PaxExact External API","version":"paxexact-estimate-v1","description":"Create and price estimates against PaxExact with your own PaxExact credentials. PaxExact never invents a price: when a line cannot be priced, the response says so, with a reason. See /developers/paxexact/docs for the full developer guide."},"servers":[{"url":"https://accurate-warmth-production-4f18.up.railway.app/v1/external"}],"components":{"securitySchemes":{"PaxExactApiKey":{"type":"http","scheme":"bearer","bearerFormat":"pxk_<env>_<key_id>_<secret>","description":"A PaxExact API key, issued through the API Center. Sandbox keys are self-service; live keys require an approved production request."}},"schemas":{"Msg":{"type":"object","required":["msg"],"properties":{"msg":{"type":"string"}}},"Error":{"type":"object","required":["detail"],"properties":{"detail":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Machine-readable error code, e.g. insufficient_scope."},"message":{"type":"string"},"request_id":{"type":"string"}},"additionalProperties":true}}},"MeResponse":{"type":"object","properties":{"organization_id":{"type":"string"},"organization_slug":{"type":"string"},"organization_name":{"type":"string"},"key_id":{"type":"string"},"key_prefix":{"type":"string"},"environment":{"type":"string","enum":["sandbox","live"]},"scopes":{"type":"array","items":{"type":"string"}},"rate_limit_per_minute":{"type":"integer"},"expires_at":{"type":["string","null"],"format":"date-time"},"contract_version":{"type":"string"},"request_id":{"type":"string"}}},"Contract":{"type":"object","description":"The closed vocabularies, money precision, and floors this contract version uses. Shape is defined by PaxExact's pricing engine, not restated field-by-field here.","additionalProperties":true},"PricingResolution":{"type":"object","properties":{"resolution_state":{"type":"string","enum":["PRICED","UNPRICED","INSUFFICIENT_DATA"]},"reason_code":{"type":["string","null"]}},"additionalProperties":true},"LineItemInput":{"type":"object","required":["description"],"properties":{"description":{"type":"string"},"quantity":{"type":"number","default":1,"description":"Defaults to 1 when omitted."},"unit":{"type":["string","null"]},"pricing_code":{"type":["string","null"]},"unit_cost":{"type":["number","null"],"description":"A human price. Omit to let PaxExact price the line."},"notes":{"type":["string","null"]},"category":{"type":["string","null"]}}},"RoomInput":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"room_type":{"type":["string","null"]},"line_items":{"type":"array","items":{"$ref":"#/components/schemas/LineItemInput"}}}},"EstimateCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"pricing_region":{"type":"string","description":"A state/region code. Omit and every coded line resolves NO_GEOGRAPHY against the national default."},"overhead_profit_percent":{"type":["number","null"]},"external_reference":{"type":["string","null"],"description":"Your own identifier for this estimate. Recorded as a prefix in the estimate's notes (e.g. \"[ref:CLM-2026-0917] ...\"); it is not a separate indexed field and is never returned as its own property on the Estimate response."},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/RoomInput"}}}},"EstimateUpdate":{"type":"object","properties":{"name":{"type":"string"},"notes":{"type":"string"},"pricing_region":{"type":"string"},"overhead_profit_percent":{"type":"number"},"status":{"type":"string"}}},"LineItemUpdate":{"type":"object","description":"Set unit_cost for a human price (source_class MANUAL), or pricing_code with unit_cost null to apply PaxExact pricing (CATALOG or OWN_DATA). A catalog price overrides a client-sent number on write.","properties":{"description":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string"},"pricing_code":{"type":["string","null"]},"unit_cost":{"type":["number","null"]}}},"LineItem":{"type":"object","properties":{"id":{"type":"string"},"description":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string"},"unit_cost":{"type":["number","null"]},"total_cost":{"type":["number","null"],"description":"null means unpriced — never 0."},"price_provenance":{"type":"string"},"pricing":{"type":"object","additionalProperties":true},"quantity_state":{"type":"object","additionalProperties":true}}},"Room":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"room_type":{"type":["string","null"]},"line_items":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}}}},"Estimate":{"type":"object","description":"Does NOT include external_reference as its own field — that value is folded into notes at creation time (see EstimateCreate.external_reference) and is never returned separately.","properties":{"id":{"type":"string"},"name":{"type":"string"},"pricing_region":{"type":["string","null"]},"overhead_profit_percent":{"type":["number","null"]},"property_zip":{"type":["string","null"],"description":"Always null for external estimates."},"property_geography":{"type":"object","additionalProperties":true},"contract_version":{"type":"string"},"status":{"type":"string"},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/Room"}},"totals":{"type":"object","additionalProperties":true}}},"EstimateListItem":{"type":"object","description":"The summary shape GET /estimates actually returns per item — NOT the full Estimate (no rooms/line items/pricing/totals).","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"estimate_mode":{"type":"string"},"pricing_region":{"type":["string","null"]},"total_cost":{"type":["number","null"]},"api_environment":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}}},"EstimateList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/EstimateListItem"}},"limit":{"type":"integer"},"offset":{"type":"integer"},"count":{"type":"integer","description":"Total matching estimates for this environment, independent of limit/offset."}}}}},"security":[{"PaxExactApiKey":[]}],"paths":{"/me":{"get":{"summary":"Describe the current key","description":"No scope required — any valid key may call this.","x-required-scope":null,"responses":{"200":{"description":"The key's organization, environment, and scopes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contract":{"get":{"summary":"Read the estimate contract","description":"Requires pricing:read.","x-required-scope":"pricing:read","responses":{"200":{"description":"The contract document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contract"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pricing/resolve":{"get":{"summary":"Probe pricing for a code/unit/region without writing","description":"Requires pricing:read. Always 200 — the same conditions on a write are 422.","x-required-scope":"pricing:read","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string"}},{"name":"unit","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"region","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"The resolution state and suggested price, if any.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingResolution"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/estimates":{"get":{"summary":"List your estimates (this environment)","description":"Requires estimates:read.","x-required-scope":"estimates:read","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"A page of estimates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateList"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create an estimate","description":"Requires estimates:write. Optionally nests rooms and line items in one call.","x-required-scope":"estimates:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateCreate"}}}},"responses":{"201":{"description":"The created estimate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Estimate"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/estimates/{estimate_id}":{"get":{"summary":"Read the full estimate tree","description":"Requires estimates:read. pricing, quantity_state, and totals are server-computed.","x-required-scope":"estimates:read","parameters":[{"name":"estimate_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The estimate, with rooms, line items, pricing, and totals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Estimate"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update estimate-level fields","description":"Requires estimates:write. name, notes, pricing_region, overhead_profit_percent, status.","x-required-scope":"estimates:write","parameters":[{"name":"estimate_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateUpdate"}}}},"responses":{"200":{"description":"The updated estimate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Estimate"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/estimates/{estimate_id}/rooms":{"post":{"summary":"Add a room","description":"Requires estimates:write. Optionally nests line items.","x-required-scope":"estimates:write","parameters":[{"name":"estimate_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomInput"}}}},"responses":{"201":{"description":"The created room.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Room"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/estimates/{estimate_id}/rooms/{room_id}/line-items":{"post":{"summary":"Add a line to a room","description":"Requires estimates:write.","x-required-scope":"estimates:write","parameters":[{"name":"estimate_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"room_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineItemInput"}}}},"responses":{"201":{"description":"The created line item.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineItem"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/estimates/{estimate_id}/line-items/{line_item_id}":{"put":{"summary":"Price or edit a line (override price / apply PaxExact price / edit)","description":"Requires estimates:write. A human price always wins over PaxExact's own-data suggestion; a catalog price overrides a client-sent number on write.","x-required-scope":"estimates:write","parameters":[{"name":"estimate_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"line_item_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineItemUpdate"}}}},"responses":{"200":{"description":"The updated line item.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineItem"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Remove a line","description":"Requires estimates:write.","x-required-scope":"estimates:write","parameters":[{"name":"estimate_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"line_item_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Removed. Returns a plain confirmation message, not an empty body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Msg"}}}},"401":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"An error, in PaxExact's uniform shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}