Integraph

API reference

All REST routes exposed by the ACS concrete and fire modules — path, method, cost, and required selectors.

Overview

This page lists every REST route in the concrete designer and fire modules. Routes follow the platform’s C-11 convention: payload routes accept a JSON body and compute stateless results; derived reads accept a design-option ID in the path and read all physics inputs from the persisted section.


Payload routes (concrete)

Only reference-data calculations remain body-addressed. Section analyses use the persisted, id-addressed reads below so materialised geometry and selectors cannot be substituted by callers.

RouteMethodCost (µ$)Notes
/api/v1/concrete/tendon-materialPOST20Resolve strand material properties
/api/v1/concrete/stress-strain-curvePOST40Constitutive curve for a declared material model

:::note[Route name corrections (August 2026) — both names now 404] Two former payload routes were renamed in August 2026 (momentCurvaturemoment-curvature, creepCoefficientcreep-coefficient) and then retired in September. Both spellings return 404 — the kebab-case name is not a working replacement for the camelCase one, and a stored URL updated to it still fails.

Use the derived reads instead: GET /api/v1/concrete/design-options/{designOptionId}/moment-curvature and GET /api/v1/concrete/design-options/{designOptionId}/creep-coefficient?combination={id}. :::

:::caution[Section-analysis payload routes retired (September 2026)] The former section-analysis POST routes have been removed and now return 404. This includes properties, flexure, interaction, shear, mk-interaction, moment-curvature, stress-distribution, sls-stress-field, time-dependent, stress-check, crack-width and deflection-params, together with their blob MCP tools. The earlier ULS tool set included CalculateConcreteProperties, CalculateConcreteFlexure, CalculateInteractionDiagram, CalculateBiaxialInteraction, CalculateConcreteShear, CalculateMkInteractionSurface — the interaction route carried two tools.

Use the corresponding GET /api/v1/concrete/design-options/{designOptionId}/{quantity} derived read listed below.

Why, and what changes for you. The retired routes accepted resolved bar coordinates in the request body. Producing those correctly means reproducing the platform’s BarResolver — corner classification, the cover chain, fitment interaction — outside the platform. A caller that gets that wrong receives a ϕMu\phi M_u that is plausible, internally consistent and wrong, with nothing in the response revealing the substitution. The derived read takes a designOptionId and resolves every one of those inputs on the saved section, so the mistake is not expressible.

The practical differences when you migrate:

  • Save the section first. Every physics input comes off the persisted row.
  • Name the load combination. The combination-scoped reads take a required ?combination={id}. properties, durability-cover, analyze, time-dependent, pt-losses and batch-design-check do not.
  • Choose an M–κ plane. moment-curvature requires ?plane=major|minor|demand and computes one charged plane per call; it never silently selects a default.
  • Persist Time-Dependent configuration first. time-dependent reads the saved AEMM inputs and refuses missing or incomplete configuration by name.
  • flexure returns BOTH axes. Omit axis and you get an x and a y entry, each labelled, at the same price as one — the route computes both regardless. Send ?axis=x only if you want the other discarded.
  • mk-interaction requires numAngles, numAxialLevels and numFibres. The retired route defaulted them to 24 / 20 / 60; the derived read refuses an omitted one (sweep_resolution_required), because each is a discretisation choice that moves the surface. It also requires a ULS combination — the surface is an ultimate-strength envelope, so a utilisation published against it under a serviceability heading would be a ULS verdict wearing another limit state’s label.
  • Selectors are refused, not assumed. A section missing stressModel, memberType or (under AS 3600) the Table 2.2.2 kϕk_\phi class is refused by name rather than computed with a substituted value. See API error codes. :::

Derived reads (concrete)

These routes are id-addressed: the design-option ID is in the path and every physics input is read from the persisted section. No body is accepted. They are the recommended form for agents and integrations working against saved designs because they cannot silently substitute a materialised parameter — every required selector (designCode, stressModel, memberType, exposureClass, etc.) and every material property (fcf'_c, fyf_y, EsE_s, and the tendon strand properties on a PT section) must be saved on the section or the route refuses by name. The same holds field by field inside a saved sub-configuration, on the route that reads it: a Time-Dependent configuration that exists but leaves an AEMM input undeclared answers …/time-dependent with time_dependent_config_incomplete rather than filling the gap with a platform literal, and leaves the other reads on that section alone. See API error codes for the full refusal code listing.

:::note[Cover derivability refusal on derived reads — August 2026 (#5238)] All concrete derived reads that need to derive a code-based cover from the section’s saved configuration now return cover_not_derivable (400) when the stored configuration is insufficient to compute it — for example, when no exposure class is saved on a section whose design code requires one, or when the member type is absent. Previously these reads either proceeded with a silently assumed cover or propagated an internal exception; the typed code makes the gap explicit and actionable.

If you see cover_not_derivable on a derived read, open the section in the editor, confirm that the Exposure Class (and, for AS 3600, the Member Type) is saved in the General tab, then retry the call. :::

:::note[stressModel and memberType are never substituted — August 2026 (#4943)] Neither value is ever defaulted for you: omitting one is a refusal, not a fall back to the design code’s default model or to "beam". A derived read names a saved-state code — stress_model_not_set, member_type_not_set — because its subject is a persisted section you can open and fix.

This note used to describe the payload routes’ half of the same rule (a plain 400 naming the missing field, because the subject was the body you had just sent), together with two deliberate exceptions on POST /concrete/interaction and POST /concrete/mk-interaction where memberType was required only when the request carried a design point. Every concrete payload compute route is retired (#5035, #5036, #5038 — September 2026), so there is no payload half and no exception left: the derived reads take both values off the persisted section, where each is required outright. :::

RouteMethodCost (µ$)Fan-outNotes
/api/v1/concrete/design-options/{id}/propertiesGET40Gross, transformed, and four cracked cases in one response
/api/v1/concrete/design-options/{id}/analyzeGET110Runner output over every checked combination
/api/v1/concrete/design-options/{id}/flexureGET80?axis=x|y (both if omitted)Flat-priced at 80 = 2 × 40 whether one or both axes are returned
/api/v1/concrete/design-options/{id}/interactionGET110?combination={id} required; carries the biaxial surface and designActions (see below)
/api/v1/concrete/design-options/{id}/shearGET40?combination={id} required
/api/v1/concrete/design-options/{id}/durability-coverGET20Derives maxBarDiameterMm from drawn bars
/api/v1/concrete/design-options/{id}/moment-curvatureGET110?combination={id} and ?plane=major|minor|demand both required; one plane per call; response includes the plane name and the angle it was solved at. The constitutive law follows the combination: a ULS combination integrates the section’s saved stress model, an SLS one the code’s linear-elastic cracked-transformed law (with long-term creep applied where the combination calls for it, disclosed on the response), and a fire combination is refused — fire capacity is evaluated against the heated section elsewhere
/api/v1/concrete/design-options/{id}/creep-coefficientGET40?combination={id} required; derives h0 from geometry
/api/v1/concrete/design-options/{id}/mk-interactionGET110?combination={id}, ?numAngles=, ?numAxialLevels=, ?numFibres= all required. The combination must be a ULS one — the fibre surface is an ultimate-strength envelope, so a serviceability or fire combination is refused with not_applicable_for_combination rather than answered under the wrong heading — and on an AS 3600 section it must carry a saved kϕk_\phi class, or the read refuses with k_phi_not_set as interaction does. designActions carries that one addressed combination as a checked point: its floored design moments, utilisation, resultant-plane curve and capacityBasis
/api/v1/concrete/design-options/{id}/stress-distributionGET40?combination={id} required
/api/v1/concrete/design-options/{id}/sls-stress-fieldGET40?combination={id} and ?numFibres= required
/api/v1/concrete/design-options/{id}/time-dependentGET110Requires saved TimeDependentConfig
/api/v1/concrete/design-options/{id}/stress-checkGET40?combination={id} required
/api/v1/concrete/design-options/{id}/crack-widthGET40?combination={id} required
/api/v1/concrete/design-options/{id}/deflection-paramsGET40?combination={id} required
/api/v1/concrete/design-options/{id}/pt-lossesGET40Takes no ?combination= and needs none — losses are a property of the tendon layout and the member as built, so this answers for a section with no load combinations saved. Per tendontendons[] carries each tendon’s own breakdown beside the first tendon’s top-level scalars, and warnings discloses the Cl 3.4.2.4 spread
/api/v1/concrete/design-options/{id}/pt-stressesGET40?combination={id} required; each tendon’s force is built from its own losses, so alternate-end stressing and differing drapes move the prestress resultant
/api/v1/concrete/design-options/{id}/batch-design-checkGET380ULS/SLS utilisation roll-up over every checked combination, with the governing-combination envelope; takes no ?combination=

Response envelope

Every derived-read response wraps its result in a ConcreteDerivedRead<T> envelope that carries:

  • The result payload itself
  • designCode, stressModel, memberType — the selectors used to compute it
  • creepEnvironment and relativeHumidity — the AS 3600 k4 environment that governed the run (for every quantity, not only creep-sensitive ones)
  • combination — the persisted load combination the result was addressed to (null for load-independent quantities such as properties and durability-cover)
  • sectionWarnings — the section-level advisories that apply to the run: assumptions the engine had to make about the section itself, such as an undeclared tendon bond state being read as bonded. Always present, empty when there are none, and distinct from any per-combination or per-quantity warning list inside the result payload — these hold whichever quantity you asked for

The section rowVersion is not a field on the envelope: it is an input to the cache key, which the ETag is derived from, so an edit to the section invalidates both and a repeat request re-runs instead of 304-ing onto stale numbers.

Fan-out on flexure

?axis=x\|y is optional. Omitting it returns both axes, labelled. Supplying a value outside {x, y} is a 400 (unknown_axis). The +/- moment sense is not an axis parameter — it is carried by the sign of the combination’s MM^* and is already in the response. The route is priced flat at 80 regardless of how many axes are returned.

Why moment-curvature requires ?plane= instead of fanning out

?plane= is required and takes exactly one of major, minor or demand. Omitting it is a 400 (bending_plane_required); a value outside the set is a 400 (unknown_bending_plane), never a fall back to the major axis.

This looks like it should be a fan-out and deliberately is not. All three values derive from persisted state — major and minor are the section’s intrinsic bending axes and demand is the plane of the addressed combination’s own signed MxM^*_x / MyM^*_y resultant — which is the same test ?axis= passes on flexure. The difference is compute, and therefore price. The runner computes both flexural axes on a single pass, so flexure can be priced flat at 80 whether one axis is asked for or both. Each bending plane here is an independent fibre integration, and the metering layer fixes an endpoint’s cost before the request is handled — so a fanned response would charge one plane’s price for three planes’ work. Requiring the parameter makes the 110 µ$ exactly right in both directions: one plane computed, one plane charged, with no over-charge on a narrow call either.

The response names the plane and the angle it was solved at, so a caller never re-derives the angle it is labelling a curve with.

Discretisation parameters on mk-interaction and sls-stress-field

numAngles, numAxialLevels, and numFibres are required on mk-interaction; numFibres is required on sls-stress-field. None is defaulted: each moves the result and a substituted value changes the analysis the engineer requested. Ranges: numAngles 4–72, numAxialLevels 5–50, numFibres 10–200. A value outside its range is refused with sweep_resolution_out_of_range, never clamped — a clamped resolution integrates a different surface from the one requested and returns it under the resolution you asked for.

Biaxial results on interaction

The derived read returns the full biaxial surface for every reinforced ULS combination — including one whose design MyM^*_y is zero. The surface is a property of the section, not of the demand: it is the same ϕ\phi-reduced N-Mx-My envelope whatever load is checked against it, and the 3D viewer, the 2D N-Mx curve, the Cl 8.1.3 Note 2 capacity basis and the ϕNu0\phi N_{u0} marker are all read off it. That is why this read costs 110 and is rate-limited while flexure costs 40 — a uniaxial combination pays for the full sweep here. Use flexure if you only want a uniaxial capacity.

Alongside the uniaxial N-M curve the response carries:

  • biaxial — the angle slices forming the 3D N-Mx-My surface, the contours at constant axial levels, the N-My curve, the AS 3600 Cl 8.1.3 Note 2-free axis curves, the rigorous utilisation, and both Bresler checks (breslerReciprocal, breslerContour). Both Bresler fields are omitted for a demand with no biaxial bending (Mx=My=0M^*_x = M^*_y = 0): Bresler is a biaxial bending interaction, so for a pure-axial demand there is nothing to check and a reported ratio would be a fabricated 0.0000.000 PASS. breslerReciprocal is omitted at N=0N^* = 0 for the same reason — it is an axial-capacity formula. The rigorous utilisation covers the axial leg as N/ϕNu0N^*/\phi N_{u0} in both cases.
  • designActions — the section’s applied load actions as demand markers: one entry per active ULS combination, plus the addressed combination itself whatever its active flag. Every entry carries n, mx, my (the design moments, after any code minimum-moment floor, with minimumMoments disclosing the entered pair beside them), momentAngleDeg, limitState and its own active. At most one entry has solved: true — the addressed combination, and only when a biaxial surface was built for it; only that entry carries utilisation, curve and capacityBasis. The rest are not interpolated off the addressed combination’s surface, because ϕ\phi is per-combination through the AS 3600 Table 2.2.2 kϕk_\phi class: combination B measured against combination A’s ϕ\phi-reduced surface is a plausible number computed with the wrong capacity reduction factor. Fire combinations are not markers here — they are checked on the fire capacity read’s own heated surface.
  • minimumMoments — the code minimum-moment floor applied to this combination, carried outside the biaxial block so the disclosure does not depend on that block existing.

biaxial is null, never empty, and only where no surface can exist at all — a section with neither bars nor tendons, or a non-ULS combination. An empty surface would read as “this section has no biaxial capacity”, which is a different and false statement.

designActions is persisted demand rather than a surface interpolation, so it is present regardless — an absent surface removes the solved entry’s capacity fields, not the markers themselves. It always carries at least one marker: the addressed combination is unioned into the set unconditionally, and it is selected from the same list ?combination= was resolved against. A design option with no combination to name is refused earlier, with combination_not_found.

:::caution[designPoints is capacity; designActions is demand] These are two different things and the names are easy to transpose:

  • nominalPoints / designPoints are points on the capacity curve — nominal, and ϕ\phi-reduced respectively. They carry a neutral-axis depth and a ϕ\phi, and have no identity.
  • designActions are the engineer’s applied load actions — the demand. Each names the load combination it came from.

One name never serves both. Reading designPoints as the demand yields a plausible, wholly wrong utilisation. :::

Capacity context on flexure

Each axis entry carries the at-state flexural result plus the context needed to read it, all of which the engine computes on the same pass:

  • utilisationRatio — the Bresler P–M utilisation for that axis.
  • axialBoundsϕNu0\phi N_{u0} / ϕNu,tens\phi N_{u,tens} and their nominal twins, with axialBoundsUnavailable naming why when they are absent.
  • minimumMoment — the code floor for that axis only (clauseRef, mMin, mStarDesign, governs). Per-axis rather than both axes’ floors together, so an xx-axis consumer is never handed My,minM_{y,\min} beside Mx,minM_{x,\min}.
  • conditionalUseGate — the AS 3600 Cl 8.1.5 verdict, present only when the gate triggers.
  • pureBendingUltimateMuoM_{uo} / ϕMuo\phi M_{uo} about that axis: the pure-bending (N=0N = 0) anchor, independent of the load combination, and the value to compare against hand calculations.

Absent means absent, and it says why. Every field above is nullable, and null never stands for zero:

fieldnull means
flexure, utilisationRatiothat axis was not checked — the engine evaluates yy only when the (floored) design MyM^*_y is non-zero
axialBoundssee axialBoundsUnavailable below
minimumMomentno code floor applied to that axis
conditionalUseGatethe gate did not trigger — a real answer about the section, not a missing one
pureBendingUltimatesee pureBendingUltimateUnavailable below

axialBoundsUnavailable is a closed vocabulary, and clients should branch on it rather than on the null alone:

valuemeaning
no_reinforcementthe section carries neither bars nor tendons. ϕNu0\phi N_{u0} and ϕNu,tens\phi N_{u,tens} (AS 3600 Cl. 10.6.2.2 and its ACI / EN equivalents) are reinforced-member provisions
tendons_without_effective_prestressthe section’s only reinforcement is prestressing steel, and its effective prestress σp.ef\sigma_{p.ef} is not set — so the Cl. 10.6.2.2 tendon terms have nothing to price

A post-tensioned section with tendons and no passive bars gets computed bounds, not a reason: the squash deducts the tendon footprint from AcA_c and the pure-tension endpoint carries fpyAp\sum f_{py} A_p, which are the same two end-caps the interaction diagram already draws for it. Only the second row above still withholds, and it withholds because pricing the tendon terms with no σp.ef\sigma_{p.ef} would return a pure-tension bound of exactly zero — which reads as a passing axial check against a tension demand.

pureBendingUltimateUnavailable is likewise a closed vocabulary:

valuemeaning
not_applicable_for_design_codea deliberate skip: MuoM_{uo} has no consumer for a reinforced ACI 318 / EN 1992 section, so it is not solved
solve_failedthe solve threw
did_not_convergethe solve ran and did not converge
tendon_over_straineda bonded tendon exceeds its strain limit — AgtA_{gt}, or εud=0.9Agt\varepsilon_{ud} = 0.9 A_{gt} under EN 1992-1-1 — at every positive εcu\varepsilon_{cu}, i.e. under its locked-in prestrain alone, before any load is applied. The section has no ultimate to report
prestress_unavailablethe section’s effective prestress could not be resolved

The first is a design decision and the rest are outcomes. Distinguishing them is the point: a bare null would report a crash and a deliberate skip identically.

tendon_over_strained is held apart from did_not_converge for the same reason, one level down: both are non-convergence, but they have different fixes. did_not_converge means NN^* lies outside the section’s axial range and is answered by changing the load; tendon_over_strained means the strand cannot be used at this prestress and is answered by changing the grade, its declared AgtA_{gt}, or σp.ef\sigma_{p.ef}. Collapsing the two left an engineer unable to tell which problem they had.

:::caution[This table is the only thing pinning that vocabulary] The platform’s code contract (C-9) covers error codes declared in a route’s Zod responses, and a parity test fails the build in both directions. pureBendingUltimateUnavailable is a response field enum, not an error code — and response field shape has no parity guard in this repo. So nothing fails if a fifth value is added to the enum and not to this table.

If you add a case, add it here in the same change. Documented here, enforced nowhere.

These values are not ProblemDetails error codes and must not be declared in a route’s errorSchemas.withCodes(...). They are field values on a 200, and they borrow the error-code vocabulary’s shape because they answer the same kind of question — nothing here ever reaches problem.Extensions["code"]. :::

Charge disclosure on refusal

A refused (4xx) request on a derived read is still charged the route’s declared cost — the **Cost (µ)** column in the tables on this page — in full, with no refund. This holds for **every derived read listed on this page**: each `GET …/design-options/{id}/{quantity}` row in the [concrete](#derived-reads-concrete) and [fire](#fire-routes) tables. (`GET …/design-options/{id}/report` is a derived read too since #5518, and its 110 µ follows the same rule.) It holds however the refusal is reached: one decidable before any database read — a missing required ?combination= — is charged, and so is one that fires only after the section was materialised and the analysis had already run, which is the case on most of the runner-backed routes.

Since August 2026 (#4884) every one of those routes’ OpenAPI descriptions ends with a sentence stating this, so the disclosure is visible in the OpenAPI document and the Scalar reference; the sentence is worded per route to match where in that route’s refusal path the charge is incurred. The refusal response itself is the standard ProblemDetails body with its code (see API error codes) — it carries no charge field. The amount charged is the route’s declared cost, reported the same way as on a successful call: in the X-Api-Cost-Credits response header (and its deprecated X-Api-Cost-Micro-Dollars twin, which carries the same number until 31 March 2027), which a refused response carries too (see Tracking usage). The MCP tools apply the same rule — see MCP server — Refused requests are still charged.

analyze: the payload route is retired

POST /api/v1/concrete/analyze has been removed and returns 404. Use the derived read GET /api/v1/concrete/design-options/{id}/analyze instead.

The derived read costs 110 µ$ and reads all inputs — design code, stress model, member type, load combinations and material properties — from the persisted section. The retired payload route accepted all of those in the request body; if you have a stored request body for the old route, save the section first and address the derived read by its ID.

durability-cover: the payload route is retired

POST /api/v1/concrete/durability-cover has been removed and returns 404. Use the derived read GET /api/v1/concrete/design-options/{id}/durability-cover instead. The derived read costs 20 µ$ and resolves the exposure class, aggregate size, and bar geometry from the persisted section.

creep-coefficient: the payload route is retired

POST /api/v1/concrete/creep-coefficient has been removed and returns 404. Use the derived read GET /api/v1/concrete/design-options/{id}/creep-coefficient?combination={id} instead.

The derived read costs 40 micro-dollars — twice what the retired payload POST was priced at — because it runs the full ConcreteAnalysisRunner pass over the named combination — matching what every other runner-backed route does — where the payload route evaluated the ϕcc\phi_{cc} formula alone on a caller-supplied body.

Expect ϕcc\phi_{cc} to differ from the retired route’s answer for the same section, and to be the correct one. The payload route substituted h0=200h_0 = 200 mm whenever the caller omitted notionalSize. The derived read has the geometry, so it derives h0=2Ac/uh_0 = 2A_c/u through the same resolver the report uses, and discloses the resolved h0h_0, t0t_0, tt and RH in the response envelope. Any section whose true h0h_0 is not 200 mm previously saw the panel and the report disagree; they now agree by construction.

batch-design-check: the payload route is retired

POST /api/v1/concrete/batch-design-check has been removed and returns 404. Use the derived read GET /api/v1/concrete/design-options/{id}/batch-design-check instead — the Design Summary’s own source, and the all-combinations answer (no ?combination=).

Unchecked combinations are excluded from every whole-section read

analyze, batch-design-check, time-dependent and pt-losses run over the combinations left checked on the Actions tab — the combination’s persisted active flag. An unchecked combination produces no result item, enters no governing envelope, and cannot fail the ulsPass / slsPass badges (#5957). Only an explicit "active": false excludes. A combination persisted with no active flag — a saved design predating the field, or a payload from an API or MCP caller that omits it — is checked, the same rule LGS applies and the same default shared/routes.ts declares (active: z.boolean().default(true)). Omitting the flag never silently removes a combination from your design.

The combination-scoped reads are unaffected: ?combination={id} resolves an unchecked combination, computes it, and reports combination.active: false alongside the answer rather than refusing it. Naming a combination is an explicit request for that combination; the flag is disclosed, not enforced.

If every combination on a design option is unchecked, the whole-section reads refuse with combination_not_found and a detail saying so — distinct from a design option that has no combinations saved at all.

Expect PT capacities to move, and to be the correct answer. The payload route accepted each tendon’s post-loss effective prestress (σp.ef\sigma_{p.ef}) directly in the request body. The derived read never accepts that: persisted tendons carry the jacking stress, and σp.ef\sigma_{p.ef} is derived through the same AS 3600 Cl 3.4.2 loss model the report and the pt-losses derived read use. A prestressed section’s ULS/SLS ratios move down where the retired route’s caller-supplied value overstated the effective prestress; non-PT sections are unaffected.

Expect SLS crack width to move on some sections, in either direction. The retired route bound the wire’s per-edge EdgeCover shape against a 4-face {top, bottom, left, right} record with 40 mm constructor defaults, so every section’s SLS crack-width check silently ran at 40 mm cover regardless of the design cover actually saved on the section (#5368). The derived read resolves cover from the persisted section like every other route, so a section whose true cover is not 40 mm now sees its crack width move to the correct value.

pt-losses and pt-stresses: the payload routes are retired

POST /api/v1/concrete/pt-losses and POST /api/v1/concrete/pt-stresses have been removed and return 404. Use the derived reads GET /api/v1/concrete/design-options/{id}/pt-losses and GET /api/v1/concrete/design-options/{id}/pt-stresses?combination={id} instead. The two CalculatePtLosses and CalculatePtStresses MCP tools are removed with them; their id-addressed replacements are GetConcretePtLossesByDesignOption and GetConcretePtStressesByDesignOption.

Expect the prestress numbers to differ from the retired routes’ answers for the same section, and to be the correct ones. The retired routes took the two things a prestress calculation is most sensitive to as givens on the wire:

  • pt-stresses accepted stressAtTransfer and effectiveStress per tendon. The derived read derives both, from the persisted jacking stress through the AS 3600 Cl. 3.4.2 loss calculation — the same derivation the PDF report runs. A caller who supplied a pre-loss stress as effectiveStress was overstating the prestress, and nothing in the response said so.
  • pt-losses fabricated a duct diameter (50 mm for an unbonded tendon, 0 otherwise) for any caller who sent none, which made every bonded tendon read as pretensioned and suppressed its Cl. 3.4.2.4 friction loss entirely. The derived read carries the duct you saved on the tendon, verbatim.

Both reads are per tendon. tendons[] carries each tendon’s own loss breakdown beside the first tendon’s top-level scalars, and warnings discloses the Cl. 3.4.2.4 spread when the group’s effective prestress differs by more than 0.5 MPa — so alternate-end stressing and differing drapes move the prestress resultant and its eccentricity, as they physically do.

pt-losses and pt-stresses both cost 40 µ$ — the bucket the retired POST peers carried. pt-stresses requires ?combination={id}: the service stage is evaluated against the actions of one persisted load combination, and there is no default.

pt-losses takes no ?combination=, and unlike analyze or time-dependent that is not because it sweeps every combination — it reads none. Losses are a property of the tendon layout and the member as built, not a load effect: friction and anchorage draw-in are Cl. 3.4.2.4 duct geometry, shrinkage is εcs\varepsilon_{cs} with the Cl. 3.4.3.2 restraint divisor, relaxation is EN 1992-1-1 Cl. 3.3.2(7) at the long-term reference, elastic shortening is the prestress at transfer, and creep takes σci\sigma_{ci} from the prestress alone. So the read answers for a design option with no load combinations saved at all — the section you are still detailing — and returns the same numbers the PDF report prints for it. It was priced at 110 µ$ and refused that section until #6132; both followed from a full ConcreteAnalysisRunner pass whose result the route then discarded.

warnings on the response discloses that σci\sigma_{ci} carries no sustained applied load. AS 3600 Cl. 3.4.3.3 defines it as the sustained concrete stress at the tendon centroid, which includes that term; a cross-section tool has no span or support condition to derive one. Because a tendon sits on the tension face, sustained load relieves compression at its level — so the omission overstates the creep loss and understates σp.ef\sigma_{p.ef}: conservative for flexural capacity, McrM_{cr} and deflection, but not where a higher effective prestress is the adverse case.


Fire routes

RouteMethodCost (µ$)Notes
/api/v1/fire/design-options/{id}/capacityGET750Derived read — reads section from DB
/api/v1/fire/design-options/{id}/heat-transferGET750Derived read — reads section from DB

The fire derived reads carry the same ApiToolAccess:concrete-designer entitlement gate as the concrete derived reads.


  • API error codes — machine-readable refusal codes and how to resolve them
  • Durability cover — the save-then-compute cycle for the cover route
  • MCP server — using these routes as id-addressed MCP tools