myproduct.life
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"])

Developer Tools

Import URL: https://sor.myproduct.life/api/public/v2/openapi.json
Agent integration: the read-only remote MCP server is available at https://sor.myproduct.life/mcp. It exposes list_scenarios, calculate_sor, compare_sor, advanced_student_estimate, and compare_sor_versions, including the optional V56 child/module allocation layer. MCP clients must support remote MCP and may require workspace or administrator approval. Streamable HTTP clients should send Accept: application/json, text/event-stream and retain the MCP session identifier returned during initialization. Parent PLUS aggregate usage and remaining eligibility are external checks and are identified in the calculation response rather than inferred by this service.

Endpoint Reference

MethodPathPurpose
GET/api/public/v2/healthCheck liveness, V56 engine and MCP versions, release, policy snapshot, and source commit.
GET/api/public/v2/scenariosFetch the public parity fixture catalog with inputs, expected outputs, and source IDs.
POST/api/public/v2/calculateRun the V56 SOR engine with calculation stages, warnings, and release metadata.
POST/api/public/v2/student-estimateEstimate a standard two-term student scenario with explicit school-review boundaries.
POST/api/public/v2/compareCompare two complete scenarios through independent shared-engine runs without storing payloads.
POST/api/public/v2/student-advancedRun an institution-specific advanced student projection with stages, warnings, and external checks.
POST/api/public/v2/migration-compareCompare an approved V55 baseline fixture with the current V56 result.
GET/api/public/v2/openapi.jsonRead the V2 OpenAPI 3.1 contract for tooling and integration review.
POST/mcpUse the read-only remote MCP server to discover scenarios and run the same V56 engine with follow-up questions and explanations.

Response Contract

Successful calculations return a `data` block from the shared engine and a `meta` block with `engineVersion`, `policyYear`, `policySnapshotDate`, `deploymentMarker`, `sourceCommit` (null), `sourceCommitStatus`, `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