# Business Made · Documents

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /business-made/documents/employee-documents

**List employee documents**

`operationId: DocumentsController_getEmployeeDocuments`

HR documents across the org — contracts, right-to-work evidence, certificates. Sensitive personal data; restrict access.

#### Signature

```http
GET /business-made/documents/employee-documents () -> Employee documents
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Often includes identity documents. Access should be narrow and logged.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/employee-documents/employee/{employeeId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Employee documents |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents

**Upload an employee document**

`operationId: DocumentsController_createEmployeeDocument`

Records a document against an employee. Set an expiry where the document has one — that is what puts it on the expiring list later.

#### Signature

```http
POST /business-made/documents/employee-documents (body) -> The created document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/employee-documents/{id}/verify`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The document to record.

```json
{
  "employeeId": "EMP-4821",
  "category": "right-to-work",
  "title": "Passport",
  "fileUrl": "https://cdn.appmint.io/hr/emp-4821-passport.pdf",
  "expiresAt": "2030-04-12"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created document |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/employee-documents/expiring

**List expiring documents**

`operationId: DocumentsController_getExpiringDocuments`

Documents approaching or past their expiry — visas, work permits, professional registrations.

This is a compliance worklist rather than a convenience: continuing to employ someone whose right-to-work evidence has lapsed is an offence in many jurisdictions.

#### Signature

```http
GET /business-made/documents/employee-documents/expiring (days?: integer) -> Expiring documents
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/employee-documents/{id}/verify`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `daysAhead` | query | number | yes |  |
| `days` | query | integer | — | Look-ahead window in days. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Expiring documents |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/employee-documents/{id}/file

**Open a document's file**

`operationId: DocumentsController_getDocumentFile`

A short-lived signed link to the document's stored file. A document whose file is an external URL returns that URL; one with no file returns `url: null`.

#### Signature

```http
GET /business-made/documents/employee-documents/{id}/file (id: string) -> `{ url, name }`
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | DOCUMENT_NOT_FOUND | Document not found | No document has that id. | The body carries `code: "DOCUMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | `{ url, name }` |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Document not found — No document has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents/{id}/reject

**Reject a document**

`operationId: DocumentsController_rejectDocument`

Rejects an uploaded document with the reason the person sees, so they can upload it again.

#### Signature

```http
POST /business-made/documents/employee-documents/{id}/reject (id: string, body) -> The rejected document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | DOCUMENT_NOT_FOUND | Document not found | No document has that id. | The body carries `code: "DOCUMENT_NOT_FOUND"` and the id. |
| `400` | reason-required | Say why the document is rejected | `reason` is empty. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

```json
{
  "reason": "The scan is cut off — both sides are needed"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The rejected document |
| `400` | Say why the document is rejected — `reason` is empty. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Document not found — No document has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents/{id}/restore

**Restore an archived document**

`operationId: DocumentsController_restoreDocument`

Brings an archived document back.

#### Signature

```http
POST /business-made/documents/employee-documents/{id}/restore (id: string) -> The restored document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | DOCUMENT_NOT_FOUND | Document not found | No document has that id. | The body carries `code: "DOCUMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The restored document |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Document not found — No document has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/employee-documents/{id}

**Get an employee document**

`operationId: DocumentsController_getEmployeeDocument`

Fetches one document with its verification and signature state.

#### Signature

```http
GET /business-made/documents/employee-documents/{id} (id: string) -> The document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INVALID_ID | invalid id <id> | The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/employee-documents/{id}/verify`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The document |
| `400` | invalid id <id> — The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /business-made/documents/employee-documents/{id}

**Delete an employee document**

`operationId: DocumentsController_deleteEmployeeDocument`

Deletes a document. Some HR documents carry statutory retention periods — archive instead unless you are certain deletion is permitted.

#### Signature

```http
DELETE /business-made/documents/employee-documents/{id} (id: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Check retention obligations before deleting.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/employee-documents/{id}/archive`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents/update

**Update an employee document**

`operationId: DocumentsController_updateEmployeeDocument`

Updates a document record. Re-verify after replacing the underlying file — verification refers to what was checked, not to the record. **Replaces the stored record** — send the whole record as read (`sk` plus `data`), not just the changed fields.

#### Signature

```http
POST /business-made/documents/employee-documents/update (body) -> The updated document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/employee-documents/{id}/verify`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The document to update.

```json
{
  "sk": "DOC-4821",
  "data": {
    "expiresAt": "2032-04-12"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated document |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/employee-documents/employee/{employeeId}

**Get an employee's documents**

`operationId: DocumentsController_getDocumentsByEmployee`

Every document held for one employee.

#### Signature

```http
GET /business-made/documents/employee-documents/employee/{employeeId} (employeeId: string) -> The employee's documents
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/employee-documents/employee/{employeeId}/category/{category}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `employeeId` | path | string | yes | Employee id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The employee's documents |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/employee-documents/employee/{employeeId}/category/{category}

**Get an employee's documents by category**

`operationId: DocumentsController_getDocumentsByCategory`

One employee's documents within a category — right-to-work evidence, say, rather than everything on file.

#### Signature

```http
GET /business-made/documents/employee-documents/employee/{employeeId}/category/{category} (employeeId: string, category: string) -> Matching documents
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/employee-documents/expiring`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `employeeId` | path | string | yes | Employee id. |
| `category` | path | string | yes | Document category. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Matching documents |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents/{id}/verify

**Verify a document**

`operationId: DocumentsController_verifyDocument`

Records that someone checked the document against the original. For right-to-work evidence the verification — who checked, and when — is the defence, not the copy.

#### Signature

```http
POST /business-made/documents/employee-documents/{id}/verify (id: string, body) -> The verified document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | DOCUMENT_NOT_FOUND | Document not found | No document has that id. | The body carries `code: "DOCUMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/employee-documents/expiring`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Verification details.

```json
{
  "verifiedBy": "hr@acme.com",
  "verifiedDate": "2026-09-01",
  "method": "original-seen"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The verified document |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Document not found — No document has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents/{id}/sign

**Sign a document**

`operationId: DocumentsController_signDocument`

Records a signature on an employee document, such as a contract.

#### Signature

```http
POST /business-made/documents/employee-documents/{id}/sign (id: string, body) -> The signed document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | DOCUMENT_NOT_FOUND | Document not found | No document has that id. | The body carries `code: "DOCUMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /crm/signed-documents`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Signature details.

```json
{
  "signedBy": "EMP-4821",
  "signedDate": "2026-09-01"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The signed document |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Document not found — No document has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/employee-documents/{id}/archive

**Archive a document**

`operationId: DocumentsController_archiveDocument`

Retires a document while retaining it — the correct way to supersede one without breaching retention rules.

#### Signature

```http
POST /business-made/documents/employee-documents/{id}/archive (id: string) -> The archived document
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | DOCUMENT_NOT_FOUND | Document not found | No document has that id. | The body carries `code: "DOCUMENT_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /business-made/documents/employee-documents/{id}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The archived document |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Document not found — No document has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/policies

**List policies**

`operationId: DocumentsController_getPolicies`

Company policies, published or not.

#### Signature

```http
GET /business-made/documents/policies () -> Policies
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/policies/status/active`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Policies |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/policies

**Create a policy**

`operationId: DocumentsController_createPolicy`

Creates a policy as a draft. Publishing is what makes it effective, and assignment is what obliges people to acknowledge it.

#### Signature

```http
POST /business-made/documents/policies (body) -> The created policy
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/publish`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The policy to create.

```json
{
  "code": "SEC-01",
  "title": "Acceptable use policy",
  "category": "security",
  "content": "…",
  "version": "1.0"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created policy |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/policies/{id}

**Get a policy**

`operationId: DocumentsController_getPolicy`

Fetches one policy with its version and content.

#### Signature

```http
GET /business-made/documents/policies/{id} (id: string) -> The policy
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INVALID_ID | invalid id <id> | The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/version`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The policy |
| `400` | invalid id <id> — The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /business-made/documents/policies/{id}

**Delete a policy**

`operationId: DocumentsController_deletePolicy`

Deletes a policy. Acknowledgement records referencing it lose the text they refer to — archive instead.

#### Signature

```http
DELETE /business-made/documents/policies/{id} (id: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/archive`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/policies/update

**Update a policy**

`operationId: DocumentsController_updatePolicy`

Updates a policy in place.

For any substantive change, **create a new version instead**. Editing a published policy silently changes what people already acknowledged, and their acknowledgement then refers to text that no longer exists.

#### Signature

```http
POST /business-made/documents/policies/update (body) -> The updated policy
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Existing acknowledgements are not invalidated by an edit — that is why versioning exists.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/version`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The policy to update. **Replaces the stored record** — send the whole record as read (`sk` plus `data`), not just the changed fields.

```json
{
  "sk": "POL-sec01",
  "data": {
    "title": "Acceptable use policy (IT)"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated policy |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/policies/{id}/publish

**Publish a policy**

`operationId: DocumentsController_publishPolicy`

Brings a policy into force. Assign it afterwards to require acknowledgement — publishing alone does not tell anyone.

#### Signature

```http
POST /business-made/documents/policies/{id}/publish (id: string) -> The published policy
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | POLICY_NOT_FOUND | Policy not found | No policy has that id. | The body carries `code: "POLICY_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/assign`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The published policy |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy not found — No policy has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/policies/{id}/archive

**Archive a policy**

`operationId: DocumentsController_archivePolicy`

Retires a policy while keeping it and its acknowledgement history — necessary to show what was in force at a past date.

#### Signature

```http
POST /business-made/documents/policies/{id}/archive (id: string) -> The archived policy
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | POLICY_NOT_FOUND | Policy not found | No policy has that id. | The body carries `code: "POLICY_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /business-made/documents/policies/{id}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The archived policy |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy not found — No policy has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/policies/{id}/version

**Create a new policy version**

`operationId: DocumentsController_createPolicyVersion`

Creates a new version of a policy, preserving the old one and the acknowledgements against it.

This is the correct way to change a policy people have already agreed to: their acknowledgement stays attached to the text they actually saw, and the new version can be re-assigned for fresh acknowledgement.

#### Signature

```http
POST /business-made/documents/policies/{id}/version (id: string, body) -> The new version
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | POLICY_NOT_FOUND | Policy not found | No policy has that id. | The body carries `code: "POLICY_NOT_FOUND"` and the id. |
| `400` | CHANGES_REQUIRED | Say what changed in this version | `changes` is empty. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/assign`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

The new version.

```json
{
  "version": "2.0",
  "content": "…",
  "changeSummary": "Added remote-working provisions"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The new version |
| `400` | Say what changed in this version — `changes` is empty. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy not found — No policy has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/policies/status/active

**List active policies**

`operationId: DocumentsController_getActivePolicies`

Policies currently in force — what employees are actually bound by.

#### Signature

```http
GET /business-made/documents/policies/status/active () -> Active policies
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/assign`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Active policies |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/policies/category/{category}

**List policies by category**

`operationId: DocumentsController_getPoliciesByCategory`

Policies within one category.

#### Signature

```http
GET /business-made/documents/policies/category/{category} (category: string) -> Policies
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/policies`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `category` | path | string | yes | Policy category. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Policies |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/acknowledgements

**List policy acknowledgements**

`operationId: DocumentsController_getPolicyAcknowledgements`

Acknowledgement records across the org — who has confirmed which policy, and who has not. The compliance position.

#### Signature

```http
GET /business-made/documents/acknowledgements () -> Acknowledgements
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/acknowledgements/employee/{employeeId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Acknowledgements |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/acknowledgements

**Create an acknowledgement**

`operationId: DocumentsController_createPolicyAcknowledgement`

Creates a single acknowledgement requirement. Use the policy assign endpoint for a group.

#### Signature

```http
POST /business-made/documents/acknowledgements (body) -> The created acknowledgement
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/assign`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The acknowledgement to create.

```json
{
  "employeeId": "EMP-4821",
  "policyId": "POL-sec01",
  "dueDate": "2026-10-31"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created acknowledgement |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/acknowledgements/{id}

**Get an acknowledgement**

`operationId: DocumentsController_getPolicyAcknowledgement`

Fetches one acknowledgement record with its status and date.

#### Signature

```http
GET /business-made/documents/acknowledgements/{id} (id: string) -> The acknowledgement
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INVALID_ID | invalid id <id> | The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/acknowledgements/{id}/acknowledge`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The acknowledgement |
| `400` | invalid id <id> — The id is not a valid record id. A well-formed id that matches nothing returns an empty 200, not a 404. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/acknowledgements/{id}/acknowledge

**Acknowledge a policy**

`operationId: DocumentsController_acknowledgePolicy`

Records that an employee has read and accepted a policy — the evidence that they were bound by it.

The record ties the employee to a specific policy **version**, which is why substantive changes should be versioned rather than edited in place.

#### Signature

```http
POST /business-made/documents/acknowledgements/{id}/acknowledge (id: string, body) -> The acknowledgement
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ACK_NOT_FOUND | Policy acknowledgement not found | No acknowledgement has that id. | The body carries `code: "ACK_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/policies/{id}/version`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Optional detail.

```json
{
  "acknowledgedDate": "2026-10-05"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The acknowledgement |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy acknowledgement not found — No acknowledgement has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/acknowledgements/{id}/decline

**Decline a policy**

`operationId: DocumentsController_declinePolicy`

Records that an employee declined to acknowledge, with their reason. Worth capturing rather than leaving outstanding — a refusal is a different situation from an omission, and needs a different response.

#### Signature

```http
POST /business-made/documents/acknowledgements/{id}/decline (id: string, body) -> The declined acknowledgement
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ACK_NOT_FOUND | Policy acknowledgement not found | No acknowledgement has that id. | The body carries `code: "ACK_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/acknowledgements/{id}/acknowledge`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Why they declined.

```json
{
  "reason": "Disputes the monitoring clause"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The declined acknowledgement |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy acknowledgement not found — No acknowledgement has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/acknowledgements/{id}/waive

**Waive an acknowledgement**

`operationId: DocumentsController_waiveAcknowledgement`

Excuses an employee from acknowledging — a policy that does not apply to their role or location. Record why, so the gap in the compliance report is explained rather than merely absent.

#### Signature

```http
POST /business-made/documents/acknowledgements/{id}/waive (id: string, body) -> The waived acknowledgement
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ACK_NOT_FOUND | Policy acknowledgement not found | No acknowledgement has that id. | The body carries `code: "ACK_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/metrics`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Why it was waived.

```json
{
  "reason": "Contractor — covered by their own agency policy"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The waived acknowledgement |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy acknowledgement not found — No acknowledgement has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/acknowledgements/{id}/remind

**Send an acknowledgement reminder**

`operationId: DocumentsController_sendReminder`

Reminds an employee about an outstanding acknowledgement. Sends every time it is called — there is no cooldown.

#### Signature

```http
POST /business-made/documents/acknowledgements/{id}/remind (id: string) -> Dispatch result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | ACK_NOT_FOUND | Policy acknowledgement not found | No acknowledgement has that id. | The body carries `code: "ACK_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/acknowledgements/employee/{employeeId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Dispatch result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy acknowledgement not found — No acknowledgement has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/acknowledgements/employee/{employeeId}

**Get an employee's acknowledgements**

`operationId: DocumentsController_getEmployeeAcknowledgements`

What one employee has been asked to acknowledge and what remains outstanding.

#### Signature

```http
GET /business-made/documents/acknowledgements/employee/{employeeId} (employeeId: string) -> The employee's acknowledgements
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /business-made/documents/acknowledgements/{id}/remind`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `employeeId` | path | string | yes | Employee id. |
| `status` | query | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The employee's acknowledgements |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/documents/policies/{id}/assign

**Assign a policy for acknowledgement**

`operationId: DocumentsController_assignPolicyToEmployees`

Requires employees to acknowledge a policy, creating an acknowledgement record for each. The step that turns a published policy into an obligation.

#### Signature

```http
POST /business-made/documents/policies/{id}/assign (id: string, body) -> The created acknowledgements
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | POLICY_NOT_FOUND | Policy not found | No policy has that id. | The body carries `code: "POLICY_NOT_FOUND"` and the id. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/acknowledgements`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | Record id. |

### Request body

Who must acknowledge it.

```json
{
  "employeeIds": [
    "EMP-4821",
    "EMP-4822"
  ],
  "dueDate": "2026-10-31"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created acknowledgements |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Policy not found — No policy has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/documents/metrics

**Get documents metrics**

`operationId: DocumentsController_getDocumentsMetrics`

Compliance figures — acknowledgement coverage per policy, outstanding requirements and expiring documents.

#### Signature

```http
GET /business-made/documents/metrics () -> Documents metrics
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /business-made/documents/employee-documents/expiring`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Documents metrics |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

