
## Close workday

`POST /v1/workday/close`

Finishes the current workday and records its duration. The call supports a report for the day and a finish point.

## Request fields (body)

All parameters are optional. The body may be empty: `{}`.

| Field | Type | Req. | Description |
|------|-----|:-----:|---------|
| `userId` | number | no | Employee identifier. Defaults to the user who owns the key's tokens. Other employees' `userId` is available only to Bitrix24 account administrators and the employee's direct managers — otherwise Bitrix24 returns an access error |
| `time` | string | no | Finish date and time in ISO 8601 format (for example `2026-05-05T18:00:00+00:00`). The date must match the day's start date — the `timeStart` value from [`GET /v1/workday/status`](/docs/workday/status). When this field is set, `report` becomes required |
| `report` | string | no | Final report for the day. Required when `time` is set and for employees on a fixed work schedule |
| `lat` | number | no | Geographic latitude of the finish point |
| `lon` | number | no | Geographic longitude of the finish point |

## Examples

### curl — personal key

```bash
curl -X POST https://vibecode.bitrix24.com/v1/workday/close \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "report": "Closed 5 deals, processed 12 leads" }'
```

### curl — OAuth application

```bash
curl -X POST https://vibecode.bitrix24.com/v1/workday/close \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "report": "Closed 5 deals, processed 12 leads" }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/workday/close', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    report: 'Closed 5 deals, processed 12 leads',
  }),
})
const { data } = await res.json()
console.log('Day duration:', data.duration)
console.log('Breaks:', data.timeLeaks)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/workday/close', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    report: 'Closed 5 deals, processed 12 leads',
  }),
})
const { data } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | `true` on successful closing |
| `data.status` | string | Status after closing — `CLOSED` |
| `data.timeStart` | string | Day start date and time (ISO 8601) |
| `data.timeFinish` | string | Day finish date and time (ISO 8601) |
| `data.duration` | string | Day duration in `HH:MM:SS` format, excluding pauses |
| `data.timeLeaks` | string | Total duration of pauses for the day in `HH:MM:SS` format |
| `data.active` | boolean | Active workday record flag |
| `data.ipOpen` | string | IP address of the day start |
| `data.ipClose` | string | IP address of the day finish |
| `data.latOpen` | number | Geographic latitude of the start point. `0` — coordinates were not passed |
| `data.lonOpen` | number | Geographic longitude of the start point |
| `data.latClose` | number | Geographic latitude of the finish point |
| `data.lonClose` | number | Geographic longitude of the finish point |
| `data.tzOffset` | number | Employee's time zone offset in seconds (depends on the employee's settings in the Bitrix24 account; the example `0` corresponds to UTC) |

## Response example

```json
{
  "success": true,
  "data": {
    "status": "CLOSED",
    "timeStart": "2026-05-05T09:00:00+00:00",
    "timeFinish": "2026-05-05T18:00:00+00:00",
    "duration": "08:00:00",
    "timeLeaks": "00:30:00",
    "active": true,
    "ipOpen": "203.0.113.10",
    "ipClose": "203.0.113.10",
    "latOpen": 0,
    "lonOpen": 0,
    "latClose": 0,
    "lonClose": 0,
    "tzOffset": 0
  }
}
```

## Error response example

422 — an attempt to close an already closed day:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Cannot perform the action"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | The `userId` field is not a positive integer, or Bitrix24 rejected a request field validation |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |
| 401 | `INVALID_API_KEY` | Invalid API key |
| 401 | `KEY_EXPIRED` | The API key has expired |
| 401 | `TOKEN_MISSING` | The key has no OAuth tokens configured for the portal |
| 402 | `ACCOUNT_FROZEN` | The portal balance is frozen |
| 403 | `SCOPE_DENIED` | The key lacks the `timeman` scope |
| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request — text is in `message`. Possible causes: the day is already closed, the `time` date does not match the day's start date, `report` is missing when `time` is set |
| 429 | `RATE_LIMITED` | The request limit to Bitrix24 was exceeded |
| 502 | `BITRIX_UNAVAILABLE` | The Bitrix24 portal is unavailable |

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

## Known specifics

- **Closing while paused.** If the day is in the `PAUSED` status, the call closes the day, recording `timeFinish` at the moment of closing. The duration of pauses is included in `timeLeaks`.
- **The sum of `duration` and `timeLeaks` equals the difference between `timeFinish` and `timeStart`** — that is, the total time since the day was opened is split into worked time and breaks with no loss.

## See also

- [Open workday](/docs/workday/open) — `POST /v1/workday/open`.
- [Pause](/docs/workday/pause) — `POST /v1/workday/pause`.
- [Current status](/docs/workday/status) — `GET /v1/workday/status`.
- [Workday](/docs/workday) — section overview.
