API: laterally loaded pile
POST /v1/lateral — request and response fields for the COM624P p-y analysis, with runnable curl, JavaScript, and Python examples.
Solves a laterally loaded single pile by the p-y method — a beam supported by nonlinear soil springs, solved with the COM624P finite-difference formulation (Wang & Reese, FHWA-SA-91-048), the same engine behind LPILE and RSPile. It returns head response, maxima, and the full deflection / moment / shear profile. The method and every input are explained in Laterally loaded piles (p-y); the same analysis runs interactively at the lateral tool.
Endpoint
https://api.pilecalc.com/v1/lateral/v1/lateral?key=…&req=…&fields=…(for header-less callers)The request has three required parts: the pile (uniform, or sectioned with depth-varying diameter/ei), the soil profile (a stack of layers, each tagged with a p-y model — Matlock soft clay, Reese stiff clay, Reese or API sand, weak rock, elastic, or user-defined curves), and the head boundary condition (five variants covering free, fixed, and rotationally restrained heads). Optional fields add an axial load, cyclic loading, distributed loads, ground slope, a p-multiplier, and free-field soil movement. Two more options change what comes back: sweep solves a series of proportionally scaled head loads (a pushover curve) in one call, and section + material replace the constant pile EI with the section's fiber-integrated moment–curvature stiffness (cracked-section nonlinear EI) — see Load sweep and Cracked section.
Authentication, rate limits, and the error envelope are shared by every endpoint — see the API overview. Requests are unit-agnostic: any self-consistent unit system works, and results come back in the same units. The examples below use SI (m, kN, kPa, kN/m³).
Request fields
This table is generated from the same schema that validates the request, so it cannot drift. Where a field appears once per variant row, it belongs to that variant only.
| Field | Type | Required | Constraints |
|---|---|---|---|
unitSystem | "si" | "us" | yes | |
pile | object | yes | |
pile.kind = "uniform" | variant | no | |
pile.length | number | yes | > 0 |
pile.diameter | number | yes | > 0 |
pile.ei | number | yes | > 0 |
pile.groundSurfaceDepth | number | no | ≥ 0 |
pile.kind = "sectioned" | variant | yes | |
pile.sections | object | object[] | yes | min 1 item |
pile.groundSurfaceDepth | number | no | ≥ 0 |
soil | object | yes | |
soil.layers[] | object[] | yes | min 1 item |
soil.layers[].model = "soft-clay" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].c | number | yes | > 0 |
soil.layers[].cBottom | number | no | > 0 |
soil.layers[].e50 | number | yes | > 0 |
soil.layers[].e50Bottom | number | no | > 0 |
soil.layers[].j | number | no | > 0 |
soil.layers[].model = "stiff-clay-above-water" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].c | number | yes | > 0 |
soil.layers[].cBottom | number | no | > 0 |
soil.layers[].e50 | number | yes | > 0 |
soil.layers[].e50Bottom | number | no | > 0 |
soil.layers[].j | number | no | > 0 |
soil.layers[].k | number | no | > 0 |
soil.layers[].kBottom | number | no | > 0 |
soil.layers[].model = "stiff-clay-below-water" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].c | number | yes | > 0 |
soil.layers[].cBottom | number | no | > 0 |
soil.layers[].e50 | number | yes | > 0 |
soil.layers[].e50Bottom | number | no | > 0 |
soil.layers[].k | number | yes | > 0 |
soil.layers[].kBottom | number | no | > 0 |
soil.layers[].model = "sand-reese" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].phi | number | yes | 0 – 60 |
soil.layers[].phiBottom | number | no | 0 – 60 |
soil.layers[].k | number | yes | > 0 |
soil.layers[].kBottom | number | no | > 0 |
soil.layers[].model = "sand-api" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].phi | number | yes | 0 – 60 |
soil.layers[].phiBottom | number | no | 0 – 60 |
soil.layers[].k | number | yes | > 0 |
soil.layers[].kBottom | number | no | > 0 |
soil.layers[].model = "weak-rock" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].qu | number | yes | > 0 |
soil.layers[].quBottom | number | no | > 0 |
soil.layers[].eir | number | yes | > 0 |
soil.layers[].eirBottom | number | no | > 0 |
soil.layers[].rqd | number | yes | 0 – 100 |
soil.layers[].rqdBottom | number | no | 0 – 100 |
soil.layers[].krm | number | no | > 0 |
soil.layers[].model = "elastic" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].esTop | number | yes | ≥ 0 |
soil.layers[].esBottom | number | no | ≥ 0 |
soil.layers[].model = "user" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].es | number | no | ≥ 0 |
soil.layers[].curves[] | object[] | no | |
soil.layers[].curves[].depth | number | yes | ≥ 0 |
soil.layers[].curves[].points[] | object[] | yes | min 2 items |
soil.layers[].curves[].points[].y | number | yes | ≥ 0 |
soil.layers[].curves[].points[].p | number | yes | ≥ 0 |
soil.layers[].model = "liquefied-sand" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].units | "SI" | "US" | yes | |
soil.layers[].model = "silt-cphi" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].c | number | yes | > 0 |
soil.layers[].cBottom | number | no | > 0 |
soil.layers[].phi | number | yes | 0 – 60 |
soil.layers[].phiBottom | number | no | 0 – 60 |
soil.layers[].k | number | yes | > 0 |
soil.layers[].kBottom | number | no | > 0 |
soil.layers[].j | number | no | > 0 |
soil.layers[].model = "piedmont-residual" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].esi | number | yes | > 0 |
soil.layers[].esiBottom | number | no | > 0 |
soil.layers[].lambda | number | no | > 0 |
soil.layers[].model = "iso-clay" | variant | yes | |
soil.layers[].top | number | yes | ≥ 0 |
soil.layers[].bottom | number | yes | > 0 |
soil.layers[].gamma | number | yes | > 0 |
soil.layers[].gammaBottom | number | no | > 0 |
soil.layers[].su | number | yes | > 0 |
soil.layers[].suBottom | number | no | > 0 |
soil.layers[].alpha | number | no | 0 – 1 |
soil.layers[].gap | "open" | "closed" | no | |
soil.layers[].clayType | "soft" | "stiff" | no | |
soil.cycles | number | no | integer, > 0 |
head | object | yes | |
head.kind = "shear-moment" | variant | yes | |
head.shear | number | yes | |
head.moment | number | yes | |
head.kind = "shear-slope" | variant | yes | |
head.shear | number | yes | |
head.slope | number | yes | |
head.kind = "shear-rotational" | variant | yes | |
head.shear | number | yes | |
head.rotationalStiffness | number | yes | ≥ 0 |
head.kind = "deflection-moment" | variant | yes | |
head.deflection | number | yes | |
head.moment | number | yes | |
head.kind = "deflection-slope" | variant | yes | |
head.deflection | number | yes | |
head.slope | number | yes | |
tip | object | no | |
tip.shear | number | no | |
tip.moment | number | no | |
axialLoad | number | no | |
loadType | "static" | "cyclic" | no | |
increments | number | no | integer, 10 – 800 |
layering | "direct" | "georgiadis" | no | |
groundSlopeDeg | number | no | 0 – 45 |
pMultiplier | number | no | 0 – 1 |
pMultiplierProfile[] | object[] | no | min 2 items |
pMultiplierProfile[].depth | number | yes | ≥ 0 |
pMultiplierProfile[].factor | number | yes | 0 – 1 |
tipShearCurve[] | object[] | no | min 2 items |
tipShearCurve[].deflection | number | yes | ≥ 0 |
tipShearCurve[].shear | number | yes | ≥ 0 |
distributedLoad | object | no | |
distributedLoad.intensity | number | yes | |
distributedLoad.top | number | no | ≥ 0 |
distributedLoad.bottom | number | no | ≥ 0 |
soilMovement | object | no | |
soilMovement.magnitude | number | yes | |
soilMovement.slidingDepth | number | yes | > 0 |
sweep | object | no | |
sweep.steps | number | yes | integer, 2 – 50 |
sweep.maxShear | number | no | |
sweep.maxMoment | number | no | |
section | object | no | |
section.kind = "solid-circular" | variant | yes | |
section.diameter | number | yes | > 0 |
section.kind = "pipe" | variant | yes | |
section.outerDiameter | number | yes | > 0 |
section.wallThickness | number | yes | > 0 |
section.kind = "rectangular" | variant | yes | |
section.width | number | yes | > 0 |
section.height | number | yes | > 0 |
section.kind = "round-concrete" | variant | yes | |
section.diameter | number | yes | > 0 |
section.cage | object | no | |
section.cage.count | number | yes | integer, 1 – 200 |
section.cage.area | number | yes | > 0 |
section.cage.barDiameter | number | yes | > 0 |
section.cage.barCircleRadius | number | yes | > 0 |
section.cage.yieldStress | number | yes | > 0 |
section.cage.elasticModulus | number | yes | > 0 |
section.cage.effectivePrestrain | number | no | ≥ 0 |
section.cage.hardeningRatio | number | no | 0 – 1 |
section.cage.tensionRuptureStrain | number | no | > 0 |
section.rebarConcreteDisplacement | "subtract" | "overlap" | no | |
section.casing | object | no | |
section.casing.outerDiameter | number | yes | > 0 |
section.casing.wallThickness | number | yes | > 0 |
section.casing.yieldStress | number | yes | > 0 |
section.casing.elasticModulus | number | yes | > 0 |
section.casing.hardeningRatio | number | no | 0 – 1 |
section.casing.tensionRuptureStrain | number | no | > 0 |
section.core | object | no | |
section.core.outerDiameter | number | yes | > 0 |
section.core.wallThickness | number | yes | > 0 |
section.core.yieldStress | number | yes | > 0 |
section.core.elasticModulus | number | yes | > 0 |
section.core.hardeningRatio | number | no | 0 – 1 |
section.core.tensionRuptureStrain | number | no | > 0 |
section.kind = "rectangular-concrete" | variant | yes | |
section.width | number | yes | > 0 |
section.height | number | yes | > 0 |
section.reinforcement | object | no | |
section.reinforcement.layout | "perimeter" | yes | |
section.reinforcement.barsPerFace | number | yes | integer, 2 – 100 |
section.reinforcement.barsPerSide | number | yes | integer, 0 – 99 |
section.reinforcement.area | number | yes | > 0 |
section.reinforcement.barDiameter | number | yes | > 0 |
section.reinforcement.clearCover | number | yes | > 0 |
section.reinforcement.yieldStress | number | yes | > 0 |
section.reinforcement.elasticModulus | number | yes | > 0 |
section.reinforcement.effectivePrestrain | number | no | ≥ 0 |
section.reinforcement.hardeningRatio | number | no | 0 – 1 |
section.reinforcement.tensionRuptureStrain | number | no | > 0 |
section.rebarConcreteDisplacement | "subtract" | "overlap" | no | |
section.confinedCore | object | no | |
section.confinedCore.coverDepth | number | yes | > 0 |
section.confinedCore.material | object | yes | |
section.confinedCore.material.kind | "concrete" | yes | |
section.confinedCore.material.compressiveStrength | number | yes | > 0 |
section.confinedCore.material.elasticModulus | number | no | > 0 |
section.confinedCore.material.peakStrain | number | no | > 0 |
section.confinedCore.material.ultimateStrain | number | no | > 0 |
section.confinedCore.material.descendingStrain | number | no | > 0 |
section.confinedCore.material.tensileStrength | number | no | ≥ 0 |
section.confinedCore.material.model | "todeschini" | "hognestad" | "concrete01" | no | |
section.confinedCore.material.residualStrength | number | no | ≥ 0 |
material | object | no | |
material.kind = "concrete" | variant | yes | |
material.compressiveStrength | number | yes | > 0 |
material.elasticModulus | number | no | > 0 |
material.peakStrain | number | no | > 0 |
material.ultimateStrain | number | no | > 0 |
material.descendingStrain | number | no | > 0 |
material.tensileStrength | number | no | ≥ 0 |
material.model | "todeschini" | "hognestad" | "concrete01" | no | |
material.residualStrength | number | no | ≥ 0 |
material.kind = "steel" | variant | no | |
material.elasticModulus | number | yes | > 0 |
material.yieldStress | number | yes | > 0 |
material.hardeningRatio | number | no | 0 – 1 |
material.ultimateStrain | number | no | > 0 |
eiCurve[] | object[] | no | min 2 items |
eiCurve[].moment | number | yes | > 0 |
eiCurve[].curvature | number | yes | > 0 |
momentCapacity | number | object[] | no | |
lrfd | object | no | |
lrfd.loads[] | object[] | yes | min 1 item |
lrfd.loads[].type | "dead" | "live" | "earthquake" | "impact" | "wind" | "water" | "ice" | "soil-pressure" | "live-roof" | "rain" | "snow" | "temperature" | "special" | yes | |
lrfd.loads[].shear | number | yes | |
lrfd.loads[].axial | number | no | |
lrfd.loads[].moment | number | no | |
lrfd.loads[].distributed | number | no | |
lrfd.cases[] | object[] | no | min 1 item |
lrfd.cases[].name | string | yes | |
lrfd.cases[].factors | object | yes | |
lrfd.cases[].phiFlexure | number | yes | 0 – 1 |
lrfd.cases[].phiShear | number | no | 0 – 1 |
lrfd.phiFlexure | number | no | 0 – 1 |
lrfd.phiShear | number | no | 0 – 1 |
lrfd.nominalMoment | number | no | > 0 |
lrfd.shearCapacity | number | no | > 0 |
Response fields
| Field | Type | Description |
|---|---|---|
converged | boolean | Whether the nonlinear p-y iteration converged. Treat a non-converged result as unusable. |
iterations | number | Iterations the solver needed. |
head.deflection | number | Pile-head lateral deflection (m). |
head.slope | number | Pile-head slope (rad). |
head.moment | number | Moment at the head (kN·m). |
head.shear | number | Shear at the head (kN). |
maxMoment.value | number | Largest-magnitude bending moment along the pile (kN·m). |
maxMoment.depth | number | Depth of the maximum moment, from the pile head (m). |
maxDeflection.value / .depth | number | Largest-magnitude deflection (m) and its depth (m). |
maxShear.value / .depth | number | Largest-magnitude shear (kN) and its depth (m). |
equilibrium.residual | number | Unbalanced force after convergence (kN) — a solution-quality check against equilibrium.applied. |
equilibrium.applied | number | Total applied lateral load (kN). |
nodes[] | object[] | The full solution, one entry per finite-difference node from head to tip. |
nodes[].depth | number | Depth from the pile head (m). |
nodes[].soilDepth | number | Depth below the ground surface (m) — differs from depth when the head is above grade. |
nodes[].deflection | number | Lateral deflection y (m). |
nodes[].slope | number | Slope dy/dz (rad). |
nodes[].moment | number | Bending moment (kN·m). |
nodes[].shear | number | Shear force (kN). |
nodes[].soilReaction | number | Mobilized soil reaction p (kN/m); opposes the deflection. |
sweep[] | object[] | Present when the request set sweep — one entry per pushover step, each an independent solution at the proportionally scaled head load: shear, moment, headDeflection, headSlope, maxMoment, maxMomentDepth, maxDeflection, converged. |
sectionProperties | object | Present when the request set section + material (cracked-section nonlinear EI): the fiber-integrated section's elasticEI (kN·m²), yieldMoment, and plasticMoment (kN·m). |
Code examples
A complete, runnable request. Replace YOUR_API_KEY (or set PILECALC_API_KEY in your environment).
curl https://api.pilecalc.com/v1/lateral \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"unitSystem": "si",
"pile": {
"kind": "uniform",
"length": 15,
"diameter": 0.61,
"ei": 143000,
"groundSurfaceDepth": 0
},
"soil": {
"layers": [
{
"model": "soft-clay",
"top": 0,
"bottom": 4,
"gamma": 8.5,
"c": 24,
"e50": 0.02
},
{
"model": "sand-reese",
"top": 4,
"bottom": 15,
"gamma": 9.5,
"phi": 34,
"k": 16300
}
]
},
"head": {
"kind": "shear-moment",
"shear": 312,
"moment": 0
},
"axialLoad": 1200,
"loadType": "cyclic",
"layering": "direct",
"increments": 120
}'The GET variant returns head.deflection,maxMoment.value as a plain-text CSV line — made for Excel's WEBSERVICE() and Sheets' IMPORTDATA() (see Use PileCalc in Excel). Omit fields to get the full JSON response.
Interpreting results
- Check
convergedfirst. If false, the pile is likely failing (soil fully mobilized) or too short — the numbers are not an equilibrium solution. - Deflections and moments follow the sign of the applied load; see Units & sign conventions.
nodeshasincrements + 1entries (default 121). For plots, usenodes[].depthvs.deflection/moment/shear.equilibrium.residualshould be small relative toequilibrium.applied; a large residual withconverged: trueis a red flag worth reporting.
Sizing runs
sweep (e.g. { "steps": 20 }) instead of sweeping head.shear across calls — the whole pushover curve comes back in sweep[] and costs a single request of your monthly quota.