Free public API
MIT licensed
Parity tested

Schedule of Reductions calculation API

A public, source labeled implementation of the federal Direct Loan Schedule of Reductions calculation. Use it to inspect inputs, replay published scenarios, compare your own implementation, and challenge the math with a citation.

First request
curl https://sor.myproduct.life/api/public/v1/health

The API is anonymous, requires no key, and returns JSON for every successful response and handled error.

Quickstart

cURL
curl -X POST https://sor.myproduct.life/api/public/v1/calculate \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Request-Id: demo-sor-001" \
  -d "$(curl -s https://sor.myproduct.life/api/public/v1/scenarios | jq '.scenarios[0].input')"
JavaScript
const scenarios = await fetch("https://sor.myproduct.life/api/public/v1/scenarios")
  .then((response) => response.json());

const calculation = await fetch("https://sor.myproduct.life/api/public/v1/calculate", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Accept: "application/json",
    "X-Request-Id": "demo-sor-001",
  },
  body: JSON.stringify(scenarios.scenarios[0].input),
}).then((response) => response.json());

console.log(calculation.data);
Python
import requests

base = "https://sor.myproduct.life/api/public/v1"
scenarios = requests.get(f"{base}/scenarios", timeout=20).json()

response = requests.post(
    f"{base}/calculate",
    json=scenarios["scenarios"][0]["input"],
    headers={"X-Request-Id": "demo-sor-001"},
    timeout=20,
)

print(response.status_code)
print(response.json()["data"])

Endpoint Reference

MethodPathPurpose
GET/api/public/v1/healthCheck liveness, engine version, policy year, and deployed source commit.
GET/api/public/v1/scenariosFetch the public parity fixture catalog with inputs, expected outputs, and source IDs.
POST/api/public/v1/calculateRun the SOR engine against a caller supplied input payload.
GET/api/public/v1/openapi.jsonRead the OpenAPI 3.1 contract for tooling and integration review.

Response Contract

Successful calculations return a `data` block from the shared engine and a `meta` block with `engineVersion`, `policyYear`, `policySnapshotDate`, `sourceCommit`, `policyStatus`, `sourceSet`, `citations`, `computedAt`, and `requestId`.

The live API sets `Cache-Control: no-store` and supports a caller supplied `X-Request-Id` for reproducible issue reports.

Rate Limits And Safety

The public API is free and anonymous with a best effort limit of 30 requests per minute per client fingerprint. The limiter uses a daily salted hash so raw IPs are not stored by the application.

This is an educational and validation tool, not an official ED calculator, legal advice, or an institutional policy substitute.

The SOR API does not calculate NSLDS remaining aggregate limits, lifetime maximum eligibility, Parent PLUS remaining eligibility, or consolidation allocation. Apply those ceilings before relying on a graduate, professional, or Grad PLUS result.

Validation Codes

200
Calculation succeeded.
400
Malformed JSON or unreadable request body.
405
Wrong method. Calculate accepts POST and OPTIONS only.
406
Client requested a non JSON response.
413
Request body exceeds the documented size cap.
415
Content-Type is not application/json.
422
Well formed JSON failed the published input schema.
429
Best effort per isolate rate limit exceeded.
500
Unexpected calculation engine failure.

Source Status

confirmed

Final regulation or stable public guidance supports the rule.

preliminary

The behavior is supported by current public guidance, but may change after final federal guidance.

Challenge The Calculation

If a published scenario or API response looks wrong, open a Scenario Challenge with the exact input JSON, observed output, expected output, and a public regulatory citation. Accepted challenges become fixtures first, then code changes.

Open challenge