> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.awardspring.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.awardspring.com/_mcp/server.

# Errors

Failures return a JSON object under an `error` key.

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "donor_not_found",
    "message": "Donor 4MZ8RT2PW was not found.",
    "param": "donor_id",
    "doc_url": null,
    "recovery": "Confirm the identifier is correct and belongs to this institution, then retry.",
    "details": null
  }
}
```

| Field      | Use it for                                                                                                                                                             |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`     | Coarse category, for deciding whether to retry at all.                                                                                                                 |
| `code`     | **Branch on this.** Stable and machine-readable.                                                                                                                       |
| `message`  | Human-readable. Wording may change — never parse it.                                                                                                                   |
| `param`    | The field the error relates to, when it maps to one. A not-found or validation error caused by an [ID](/ids) that names no record always names the field that held it. |
| `doc_url`  | Link to documentation for this error, when one exists.                                                                                                                 |
| `recovery` | Plain-language guidance you can surface to a person.                                                                                                                   |
| `details`  | Per-field failures on a validation error. Absent otherwise.                                                                                                            |

## Types

| `type`                  | Meaning                                                      |
| ----------------------- | ------------------------------------------------------------ |
| `invalid_request_error` | Your input: bad parameters, validation, not-found, conflict. |
| `authentication_error`  | Missing or invalid credential.                               |
| `rate_limit_error`      | Throttled. Back off and retry.                               |
| `api_error`             | Server-side. Safe to retry.                                  |

## Status codes

| Status | When                                                                                                                                                                                                                           |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400`  | Malformed request, failed validation, or an unrecognised API key.                                                                                                                                                              |
| `401`  | Key missing or expired, or API access is not enabled for the institution.                                                                                                                                                      |
| `403`  | Key valid, but lacks the permission this endpoint needs, or the signed-in user's own AwardSpring permissions do not cover this information. At sign-in, the email and password are correct but the account cannot use the app. |
| `404`  | No such record belongs to this institution, or the feature is not turned on for it.                                                                                                                                            |
| `409`  | Conflicts with existing data, or an idempotent retry is still in flight.                                                                                                                                                       |
| `422`  | Well-formed but unprocessable — including unrecognised fields.                                                                                                                                                                 |
| `429`  | Rate limited. See [Rate limits](/rate-limits).                                                                                                                                                                                 |

## Codes

Branch on these. They are stable; new ones may be added.

| `code`                             | Status |
| ---------------------------------- | ------ |
| `validation_failed`                | `400`  |
| `invalid_cursor`                   | `400`  |
| `unsupported_activity_type`        | `400`  |
| `unauthorized`                     | `401`  |
| `invalid_credentials`              | `401`  |
| `invalid_refresh_token`            | `401`  |
| `permission_required`              | `403`  |
| `permission_denied`                | `403`  |
| `app_access_denied`                | `403`  |
| `donor_not_found`                  | `404`  |
| `student_not_found`                | `404`  |
| `person_not_found`                 | `404`  |
| `scholarship_not_found`            | `404`  |
| `award_cycle_not_found`            | `404`  |
| `fund_not_found`                   | `404`  |
| `gift_not_found`                   | `404`  |
| `activity_not_found`               | `404`  |
| `notification_not_found`           | `404`  |
| `institution_not_found`            | `404`  |
| `awarded_students_not_found`       | `404`  |
| `donor_questions_unavailable`      | `404`  |
| `app_endpoint_unavailable`         | `404`  |
| `email_already_exists`             | `409`  |
| `idempotency_key_in_flight`        | `409`  |
| `idempotency_key_request_mismatch` | `422`  |
| `rate_limit_exceeded`              | `429`  |
| `internal_error`                   | `500`  |

## Validation failures

A `validation_failed` error carries `details`, one entry per offending field. Show these against the fields they name rather than concatenating them into one message.

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_failed",
    "message": "One or more validation rules failed. See details for specifics.",
    "details": [
      { "field": "amount", "message": "Amount is required." },
      { "field": "gift_date", "message": "GiftDate is required." }
    ]
  }
}
```

## Accounts that cannot use the app

Signing in returns `app_access_denied` when the email and password are correct but belong only to a reviewer, student or donor account. Those accounts use the institution's AwardSpring website, not the app. Tell the person so instead of asking them to retype their password, and do not retry.

Every other failed sign-in returns `invalid_credentials`, whatever the reason: an unknown institution or email, a wrong password, a deactivated or archived account, or any other account the app cannot serve. That answer never says which, so it never reveals whether an email is registered.

## Sign-ins from the app

A sign-in from the app works only for the requests the app makes. Any other request made with it returns `app_endpoint_unavailable`; make that request with the institution's secret key instead.

## Unrecognised fields are rejected, not ignored

Send a field this API does not know and the request fails with the field named, rather than succeeding while quietly dropping your data. A typo in a field name is a loud error, which is the behaviour you want when the alternative is discovering months later that a column was never being saved.

## One exception worth coding around

**A `401` does not use the envelope above.** It returns a plain-text reason. A client that assumes JSON on every error path will throw while handling the very case it was written for. Check the status before parsing, or guard the parse.

Every other status on this page returns the JSON `error` object.