> ## Documentation Index
> Fetch the complete documentation index at: https://help.skillsdb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The Training Record object

> A training against a person's skill: status, evidence, expiry, approval decisions and renewal history

<Info>
  **Quick Summary:** A training belongs to a **person skill** — the skill must already be on the person's profile before a training can be recorded. Approval is a full request-and-decide workflow with delegation; renewal supersedes records without deleting them.
</Info>

## Attributes

| Field                                                   | Type           | Description                                                                                                                                                    |
| ------------------------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                                    | string         | Opaque training record id                                                                                                                                      |
| `person` / `skill`                                      | object         | References `{ id, name }`                                                                                                                                      |
| `trainingDate`                                          | string \| null | When the training took place                                                                                                                                   |
| `trainer`                                               | string \| null | **Free text, never a person reference.** Who trained is unvalidated; who *approved* is the person in `decision`; who *may train* is a trainer-designating flag |
| `status`                                                | string         | See the status table below                                                                                                                                     |
| `isNotApplicable`                                       | boolean        | Excluded without being deleted                                                                                                                                 |
| `evidenceNote`                                          | string \| null | The text half of evidence; files come through `/trainings/{id}/evidence` as time-limited links                                                                 |
| `expiresAt` / `isExpired`                               | —              | Expiry is a **date**; the expired state is derived from it, never a lifecycle status the API sets                                                              |
| `skillVersionId`                                        | string \| null | The skill version the training was completed against — what makes a superseded record identifiably stale                                                       |
| `requestedById` / `requestedAt` / `delegatedApproverId` | —              | The submission side                                                                                                                                            |
| `decision`                                              | object \| null | `{ outcome, decidedById, decidedAt, reason }` once decided                                                                                                     |
| `isSuperseded`                                          | boolean        | True when the record was replaced by a renewal and lives in training history                                                                                   |

## Statuses

| Status                                                   | Written by                                                                                               |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `awaiting_approval`, `approved`, `rejected`, `cancelled` | Application flow and this API                                                                            |
| `needs_reapproval`                                       | Renewal (the internal name "Update" gives no hint of that)                                               |
| `expired`, `pending`, `submitted`                        | **Only the CSV history importer** — reads can return them, but no API write produces or transitions them |

## Approval

* `GET /training-approvals?status=` covers every decidable state, not just the pending queue.
* `GET /trainings/{id}/potential-approvers` unions three unrelated authorities: global-admin/full-access users, the submitter's entire chain of command, and holders of a trainer-designating skill flag (`expertsOnly=true` returns just the flag holders).
* `GET /people/{id}/approval-activity` lists everything a person decided; `GET /people/{id}/approval-requests` is the other side.

<Warning>
  **Entitlement is point-in-time and not retained.** The decision records who decided, never under which authority — flags get removed, reporting lines change. Whether an approval came from a trainer flag or the chain of command cannot be reconstructed later.
</Warning>

## Renewal supersedes, it does not delete

`POST /skills/{id}/renew-training` marks affected trainings `needs_reapproval` across everyone holding the skill — a fan-out counted against the **bulk** rate-limit bucket. Preview first with `GET /skills/{id}/renew-training/preview`. Superseded records stay readable through `GET /people/{personId}/skills/{skillId}/training-log`, the only read that spans live and superseded records together.
