Bulk CSV walkthrough
The bulk endpoint accepts a single CSV with one row per (student, term) and returns a CSV with one row per result term plus one error row per failed student.
Why one row per term
Each student can have multiple enrollment periods. Keeping one row per term means you don't need a custom flat-file schema with a variable number of columns; you can produce the input from any SQL SELECT over your enrollment tables.
Endpoint
curl -X POST https://loanlimit.app/v1/calculate/bulk \
-H 'content-type: text/csv' \
-H 'accept: text/csv' \
--data-binary @students.csv \
> results.csv
Both application/json (when we add a JSON codec in the future) and text/csv will be supported via content-type negotiation. Today only text/csv is wired in both directions.
Input columns
See the full CSV schema for the column-by-column reference. The summary:
- Per-student columns (must be identical across every row for the same
student_id):dependency_status,degree_level,grade_level,subsidized_amount,plus_denied,is_legacy_borrower,cost_of_attendance,total_limit. - Per-term columns (one per row):
term_label,term_ft_credits,term_credits_enrolled,term_actual_final_credits,term_prior_disbursement_sub,term_prior_disbursement_unsub,term_prior_disbursement_grad_plus. - Identity column:
student_id. Rows are grouped by this value. If omitted, the API auto-assignsrow:<N>based on input position.
Download the sample template for the canonical column order.
Output columns
Each result row carries the per-term result for one student. The columns are:
student_id, term_label, term_enrollment_status, term_equal_subsidized, term_equal_unsubsidized, term_equal_grad_plus, term_proportional_subsidized, term_proportional_unsubsidized, term_proportional_grad_plus, annual_ft_credits, reduced_annual_pct, total_equal_subsidized, total_equal_unsubsidized, total_equal_grad_plus, total_proportional_subsidized, total_proportional_unsubsidized, total_proportional_grad_plus, error.
The error column is empty on success and carries a human-readable error message when a student row group failed to process (in which case all numeric columns are empty for that student).
Per-student consistency
If you submit two rows for the same student_id with different values for any per-student column (e.g., one row says grade_level=first_year and another says grade_level=second_year), the API returns a single error row for that student:
Inconsistent value for 'grade_level' across rows for student STU042: row 1 has 'first_year', row 3 has 'second_year'
The other students in the request are unaffected.
Handling errors
Always read the error column for every result row. A student that fails validation does not stop the batch — other students still get computed and returned. Plan your downstream logic around partial success.
What is not supported (yet)
- JSON request/response on this endpoint.
- File upload via
multipart/form-data(the web upload UI at loanlimit.app/bulk uses that, but the public API expects the CSV directly in the request body). - Streaming responses for very large batches.