---
title: "Release Check"
method: POST
path: "/v1/time-entries/release/check"
tags: ["time-entries"]
---

# Release Check

`POST /v1/time-entries/release/check`

## Request

- Base URL: `https://app.tokumalabs.com/api`
- URL: `https://app.tokumalabs.com/api/v1/time-entries/release/check`
- Auth: OAuth 2
  - Password
  - Token URL: `v1/auth/token`

Preflight the release gate for the confirmation dialog.

Runs the same structural validation matrix as ``/release`` but
writes nothing. The desktop client calls this on dialog open and
refuses to show Confirm while ``failed`` is non-empty.

## Request body

- ReleaseTimeEntriesRequest: Request model for releasing multiple time entries.
  - `time_entry_ids` integer[], required: List of time entry IDs to release

## Response `200`

Successful Response

- ReleaseCheckResponse: Preflight result for the release confirmation dialog. The dialog calls ``POST /api/v1/time-entries/release/check`` before showing the irreversible Confirm button and refuses to proceed while ``failed`` is non-empty. The same validator runs here and inside ``release_time_entries_bulk`` so the preview and the authoritative gate cannot disagree.
  - `eligible_ids` integer[]: IDs that would be released on Confirm
  - `failed` FailedRelease[]: IDs that would be rejected, with codes
    - `time_entry_id` integer, required: ID of the time entry that failed to release
    - `code` 'INVALID_CREDENTIALS' | 'REFRESH_TOKEN_REQUIRED' | 'INVALID_REFRESH_TOKEN' | 'REFRESH_TOKEN_REUSE_DETECTED' | 'USER_NOT_FOUND' | 'NOT_AUTHENTICATED' | 'MS365_CONFIG_NOT_FOUND' | 'MS365_INVALID_STATE' | 'MS365_TOKEN_EXCHANGE_FAILED' | 'MS365_INVALID_USER' | 'MS365_GRAPH_REQUEST_FAILED' | 'MS365_CREDENTIALS_REJECTED' | 'MS365_PERMISSION_DENIED' | 'WRONG_AUTH_METHOD' | 'CAPABILITY_REQUIRED' | 'LAST_ADMINISTRATOR' | 'TOO_MANY_REQUESTS' | 'VALIDATION_ERROR' | 'NOT_FOUND' | 'CONFLICT' | 'ALREADY_EXISTS' | 'STALE_CURSOR' | 'INVALID_CURSOR' | 'DATA_WIPE_FORBIDDEN_ENV' | 'TIME_BLOCK_INVALID_TIME_RANGE' | 'TIME_BLOCK_INVALID_SEGMENT' | 'SEGMENT_NOT_ASSIGNABLE' | 'TIME_BLOCK_INVALID_ACTIVITY_CODE' | 'TIME_ENTRY_RELEASE_NOT_FOUND' | 'TIME_ENTRY_RELEASE_EMPTY' | 'TIME_ENTRY_RELEASE_NO_MATTER' | 'TIME_ENTRY_RELEASE_NO_ACTIVITY_CODE' | 'TIME_ENTRY_RELEASE_NARRATIVE_PENDING' | 'TIME_ENTRY_NO_BLOCKS' | 'TIME_ENTRY_MERGE_NOT_FOUND' | 'TIME_ENTRY_MERGE_RELEASED' | 'TIME_ENTRY_MERGE_DIFFERENT_DATE' | 'TIME_ENTRY_MERGE_SELF' | 'GENERATION_UNAVAILABLE' | 'GENERATION_AI_INVALID_RESPONSE' | 'GENERATION_AI_PROVIDER_ERROR' | 'GENERATION_INPUT_TOO_LARGE' | 'GENERATION_CONCURRENT' | 'GENERATION_IN_PROGRESS' | 'GENERATION_TIMEOUT_RECOVERED' | 'GENERATION_DISPATCH_FAILED' | 'GENERATION_DISPATCH_LOST' | 'GENERATION_FAILED' | 'SPAN_EVENT_DISPATCH_EXHAUSTED' | 'EXTRACTION_IMAGE_NOT_FOUND' | 'EXTRACTION_IMAGE_INVALID' | 'EXTRACTION_AI_INVALID_RESPONSE' | 'EXTRACTION_AI_PROVIDER_ERROR' | 'EXTRACTION_INPUT_TOO_LARGE' | 'REASSEMBLY_ENRICH_FAILED' | 'REASSEMBLY_REBUILD_FAILED' | 'REASSEMBLY_TIMEZONE_INVALID' | 'REASSEMBLY_FAILED' | 'SPAN_OWNERSHIP_MISMATCH' | 'SPAN_INGEST_FAILED' | 'CAPTURE_IMAGE_OWNERSHIP_MISMATCH' | 'DATABASE_UNAVAILABLE' | 'UNKNOWN_ERROR', required: Centralized error codes for the API.
    - `message` string, required: Default human-readable message paired with code

## Other responses

- `400`: Validation error or domain rule violation.
- `401`: Missing, expired, or invalid authentication.
- `403`: Authenticated but not permitted.
- `404`: Resource not found.
- `409`: Resource state conflict (duplicate, illegal transition).
- `422`: Request body failed schema validation.
- `500`: Server-side failure.

---

[API](https://skmtc.dev/tokumalabs/apis/tokuma-user-api.md) - [All operations](https://skmtc.dev/tokumalabs/apis/tokuma-user-api/llms.txt) - [OpenAPI document](https://skmtc.dev/tokumalabs/apis/tokuma-user-api/revisions/1f8201af459b?raw)
