# Overview

Read a company's employee training records, deadlines, completions and certificates from your own server.

- **Base URL:** `https://api.kapiworks.com/v1`
- **Contract:** OpenAPI 3.1.0, revision 1.2.0. [Download](https://api.kapiworks.com/v1/openapi.json)
- **Access:** Company API keys, from your server. Read-only.

## Make your first call

1. A company owner or admin creates a key in Works Studio, under **Settings → API keys**.
2. You store it in your server's secret manager as `KAPI_WORKS_API_KEY`.
3. Your server reads the first page of training records. Every page of one pull comes from the same snapshot of the company's records.

The [Quickstart](https://docs.kapiworks.com/quickstart) walks through each step.

**curl**

```bash
# Supply the key from your server's secret manager. Do not log it.
# curl reads the header from stdin, keeping the key out of its arguments.
printf 'header = "Authorization: Bearer %s"\n' "$KAPI_WORKS_API_KEY" |
  curl --config - --silent --show-error --fail-with-body \
  'https://api.kapiworks.com/v1/training-records?limit=200'
```

**Node**

```js
// Node 24, as an ES module (first-call.mjs). KAPI_WORKS_API_KEY comes from your secret manager.
const response = await fetch("https://api.kapiworks.com/v1/training-records?limit=200", {
  headers: { Authorization: `Bearer ${process.env.KAPI_WORKS_API_KEY}`, Accept: "application/json" },
  redirect: "error",
  signal: AbortSignal.timeout(30_000),
});
const requestId = response.headers.get("x-request-id");
const body = await response.json();
if (!response.ok) throw new Error(`HTTP ${response.status} ${body.code}; request ID ${requestId}`);
console.log(JSON.stringify(body, null, 2));
```

**Python**

```python
# Python 3, standard library only. KAPI_WORKS_API_KEY comes from your secret manager.
import json, os, urllib.error, urllib.request

class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, *args):  # do not resend the key to another address
        return None

request = urllib.request.Request(
    "https://api.kapiworks.com/v1/training-records?limit=200",
    headers={"Authorization": "Bearer " + os.environ["KAPI_WORKS_API_KEY"], "Accept": "application/json"},
)
try:
    with urllib.request.build_opener(NoRedirect).open(request, timeout=30) as response:
        print(json.dumps(json.load(response), indent=2))
except urllib.error.HTTPError as error:
    problem = json.load(error)
    raise SystemExit(f"HTTP {error.code} {problem['code']}; request ID {error.headers['X-Request-Id']}")
```

## What you can read

| Endpoint | Returns | Scope |
| --- | --- | --- |
| [`GET /v1/training-records`](https://docs.kapiworks.com/reference/list-training-records) | Training records at a moment | `training:read` |
| [`GET /v1/training-records/period`](https://docs.kapiworks.com/reference/list-period-training-records) | Every training record owed during a period | `training:read` |
| [`GET /v1/certificates`](https://docs.kapiworks.com/reference/list-certificates) | Certificates at a moment | `certificates:read` |
| [`GET /v1/people`](https://docs.kapiworks.com/reference/list-people) | Employees and invitations during a period | `people:read` |
| [`GET /v1/courses`](https://docs.kapiworks.com/reference/list-courses) | Course versions referenced by employee records | `training:read` |
| [`GET /v1/snapshot`](https://docs.kapiworks.com/reference/get-snapshot) | Check whether anything changed | Any |

Every call is a `GET` that answers with JSON. Keys are company keys for your server, not OAuth tokens, and the API sends no CORS headers, so it is for servers rather than browsers.

## Find your way

- [Quickstart](https://docs.kapiworks.com/quickstart): Create a key and make a first call.
- [Keeping data in sync](https://docs.kapiworks.com/guides/sync): Read every page of a snapshot, and replace your copy only after a complete pull.
- [Training evidence](https://docs.kapiworks.com/guides/training-evidence): Outcomes, certificates and check codes, and what each one means.
- [API reference](https://docs.kapiworks.com/reference): Every operation, parameter and field, generated from the OpenAPI contract.
- [Errors](https://docs.kapiworks.com/errors): Every error code, what it means and what to do.
- [AI tools](https://docs.kapiworks.com/ai-tools): Markdown pages, llms.txt and a docs MCP server.
