## Explain an absence

`POST /v1/workday/time-control/reports/:absenceId`

Records an explanation for an absence listed in the monthly time-control report: the text, the type and, if needed, an event in the employee's calendar. A repeated call replaces the previous explanation and returns the same response.

Requires the `timeman` scope. The explanation is recorded on behalf of the credential owner: an employee explains their own absence; an administrator explains any employee's absence by passing that employee's `userId`. An employee needs access to the monthly report: while time control is switched off (`active: false` in the [time-control settings](/docs/workday/time-control-settings)), they get `403 BITRIX_ACCESS_DENIED`. This does not apply to an administrator or a department head. READONLY keys cannot record an explanation.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|----------|
| `absenceId` (path) | integer | yes | — | Absence ID — `report.days[].reports[].id` from the `/v1/workday/time-control/reports` response on the [Get the monthly absence report](/docs/workday/time-control-reports) page |

## Request fields (body)

| Field | Type | Required | Default | Description |
|------|-----|:-----:|-----------|----------|
| `text` | string | yes | — | Explanation text; must not be empty |
| `month` | integer | yes | — | Month of the absence, from 1 to 12. The absence is looked up in the employee's monthly report by month and year |
| `year` | integer | yes | — | Year of the absence, from 1900 to 3000 |
| `type` | string | no | `PRIVATE` | Explanation type: `WORK` — work-related, `PRIVATE` — personal |
| `calendar` | boolean | no | `true` | Create an event in the employee's calendar for the duration of the absence, with the explanation text. With `type: PRIVATE` the event is private |
| `userId` | integer | no | credential owner | ID of the employee whose absence is explained. Honored only for an administrator, ignored for everyone else. List: [`GET /v1/users`](/docs/entities/users/list), department employees — [`GET /v1/workday/time-control/users`](/docs/workday/time-control-users) |

## Examples

### curl — personal key

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/workday/time-control/reports/153" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Meeting with a client", "month": 10, "year": 2026, "type": "WORK", "calendar": false}'
```

### curl — OAuth application

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/workday/time-control/reports/153" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "Meeting with a client", "month": 10, "year": 2026, "type": "WORK", "calendar": false}'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/workday/time-control/reports/153', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ text: 'Meeting with a client', month: 10, year: 2026, type: 'WORK', calendar: false }),
})
const { success } = await res.json()
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/workday/time-control/reports/153', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ text: 'Meeting with a client', month: 10, year: 2026, type: 'WORK', calendar: false }),
})
const { success } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | `true` when the explanation is recorded |
| `data` | boolean | Always `true`. The recorded explanation is visible in the `reportType` and `reportText` fields of the absence in the [monthly report](/docs/workday/time-control-reports) |

## Response example

```json
{
  "success": true,
  "data": true
}
```

## Error response example

404 — no absence with this `absenceId` in the employee's report for the given month:

```json
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "Absence not found for this user and month"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | `absenceId` is not a positive integer, `text` is empty, `type` is neither `WORK` nor `PRIVATE`, `calendar` is not a boolean, `month` or `year` is missing or out of range, `userId` is not a positive integer, or the request body is not an object |
| 404 | `ENTITY_NOT_FOUND` | No absence with this `absenceId` in the employee's report for the given month: another month, someone else's absence, or a nonexistent `userId` passed by an administrator |
| 403 | `BITRIX_ACCESS_DENIED` | The employee has no access to the monthly report: time control is switched off (`active: false` in the [time-control settings](/docs/workday/time-control-settings)). A disabled Time Management tool on the portal returns 409, not this code |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is in read-only mode |
| 409 | `TIMEMAN_MODULE_NOT_ENABLED` | Time Management is not available on this portal: the Time Management tool is switched off in the portal settings, or the module is not included in the plan |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a response of an unexpected shape |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |
| 401 | `TOKEN_MISSING` | An app key was sent without a session token in `Authorization: Bearer` |
| 401 | `INVALID_SESSION` | The session token is invalid or has expired |
| 403 | `SCOPE_DENIED` | The key lacks the `timeman` scope |
| 429 | `RATE_LIMITED` | The general request limit was exceeded; the retry delay is in the `Retry-After` header |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

**The calendar event is independent of the explanation.** With `calendar: true` the event is created in the employee's personal calendar for the absence interval; its ID is not returned in the response. A repeated explanation neither changes nor deletes the previous event, and with `calendar: true` it creates another one. To find these events, search the employee's [calendar events](/docs/entities/calendar-events) by the explanation text and the absence time; delete them with [`DELETE /v1/calendar-events/:id`](/docs/entities/calendar-events/delete).

## See also

- [Get the monthly absence report](/docs/workday/time-control-reports)
- [List department employees](/docs/workday/time-control-users)
- [Time-control settings](/docs/workday/time-control-settings)
- [Calendar events](/docs/entities/calendar-events)
- [Workday](/docs/workday)
