---
title: "Financial aid appeal letter"
method: POST
path: "/v1/tools/appeal"
---

# Financial aid appeal letter

`POST /v1/tools/appeal`

## Request

- Base URL: `https://api.counselorai.app`
- URL: `https://api.counselorai.app/v1/tools/appeal`
- Auth: HTTP bearer

Draft a financial aid appeal letter to a college financial aid office. Call this when a family needs to ask for a review of an award: income dropped, an expense appeared, another school offered more, or the FAFSA was wrong. Returns the letter, not advice on whether to appeal. Runs a 5-step drafting pipeline, so it is the most expensive tool here and the slowest, typically 30 to 60 seconds.

## Headers

- `Idempotency-Key` string
- `X-Max-Credits` integer

## Request body

- object
  - `studentName` string: The student this is about. Used in the output text.
  - `counselorName` string: Who the letter is from. The counselor stays the author; this tool drafts, it does not sign.
  - `schoolName` string: The institution the appeal goes to.
  - `appealType` 'changed_circumstances' | 'financial_hardship' | 'competing_offer' | 'special_circumstances' | 'error_correction': What the appeal rests on. changed_circumstances is income loss or a new expense since the FAFSA, competing_offer is a match request, special_circumstances asks for a Professional Judgment review, error_correction fixes bad data on the original filing. financial_hardship is a legacy alias for changed_circumstances.
  - `currentAward` string: What the school offered, as written on the award letter.
  - `amountNeeded` string: The gap being asked for.
  - `keyDetails` string, required: The circumstances, in the counselor or family's own words. This is what the letter is built out of, so specifics beat summaries.
  - `competing` string: A competing offer to cite, if there is one.
  - `status` string[]: Student circumstances the letter should carry without labeling them. homeless and housing_insecure are the same category.
  - `length` 'short' | 'standard' | 'detailed': Roughly 330, 440 or 560 words.
  - `naturalness` integer: How plainly the letter should read. 1 is formal institutional, 5 is conversational.

## Response `200`

Tool output

- object
  - `request_id` string
  - `tool` string
  - `output` object
    - `text` string, required: The generated output.
    - `meta` object: Pipeline metadata (pipeline, verify status, fix pass).
    - `verification` object: Whether a model verify pass checked this text, and its verdict.
      - `checked` boolean
      - `method` string, nullable
      - `status` 'PASS' | 'FAIL' | 'null', nullable
      - `score` integer, nullable
      - `fix_applied` boolean, nullable
    - `grounding` object: What the generation was anchored to. fact_sheet is the exact ground truth the verify pass checked dollar figures, names, and dates against; null for tools without a fact-grounded verify pass.
      - `fact_sheet` string, nullable
      - `fields_reflected_in_prompt` string[]
      - `fields_mapped_or_transformed` string[]
      - `fields_not_reflected` string[]
    - `input_fidelity` string: 'strict': this lane never truncates silently; an over-limit input is rejected with a validation error, so the output was built on exactly what was sent.
  - `billing` object
    - `status` 'settled' | 'pending'
    - `credits_charged` integer, nullable
    - `credits_remaining` integer, nullable

## Other responses

- `402`: Insufficient credits or approved spending limit exceeded. Inspect error.code.
- `429`: Rate limited. Retry after the Retry-After header.

---

[API](https://skmtc.dev/counselorai/apis/counselorai-api.md) · [All operations](https://skmtc.dev/counselorai/apis/counselorai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/counselorai/apis/counselorai-api/revisions/1d93eed35463?raw)
