---
title: "Move Time Block"
method: PATCH
path: "/v1/time-blocks/{time_block_id}"
tags: ["time-blocks"]
---

# Move Time Block

`PATCH /v1/time-blocks/{time_block_id}`

## Request

- Base URL: `https://app.tokumalabs.com/api`
- URL: `https://app.tokumalabs.com/api/v1/time-blocks/{time_block_id}`
- Auth: OAuth 2
  - Password
  - Token URL: `v1/auth/token`

Move a time block to a different entry or detach it.

Returns the updated block plus every entry whose duration was
recalculated, in the cursor-sync wire shape so the desktop client
can apply the response directly to its local SQLite mirror.

## Path parameters

- `time_block_id` integer, required

## Request body

- UpdateTimeBlockRequest: Request model for moving a time block to a different entry or detaching it.
  - `time_entry_id` integer, nullable, required: Target time entry ID. Set to null to detach from entry.

## Response `200`

Successful Response

- MoveTimeBlockResponse: Response model for moving a time block between entries. Returns the modified block plus every entry whose duration or membership changed (source + target). Both in the cursor-sync wire shape so the desktop client can apply the response directly to local SQLite.
  - `time_block` TimeBlockSyncDto, required: A time block as seen by the cursor sync feed. ``matter_segment`` is a denormalized snapshot of the segment + matter info at the time the row was returned. The desktop client renders directly from this; segment/matter renames take effect for a row only when the row's own ``version`` advances. Accepted as the rename-staleness compromise of the denormalized design. ``version`` is the trigger-bumped global cursor counter (BIGINT). Local mirror's apply predicate compares it as the freshness signal (``WHERE excluded.version > target.version``). ``updated_at`` is informational only. ``artifacts`` is projected from the internal ``time_blocks.facts`` fact sheet by ``dto_builders.block_artifacts_dto`` — ``BlockFacts`` itself is deliberately NOT on the wire, so it stays refactorable. Only ``artifacts`` is projected today; ``sub_app`` / ``action`` / ``counterparties`` / ``has_external`` have no client consumer, and per this module's contract we ship only what the client consumes. Adding one later is a DTO line plus a mapper line — the client stores the blob opaquely, so no migration is involved.
    - `id` integer, required
    - `organization_id` string, required
    - `user_id` string, required
    - `start_time` string, date-time, required
    - `end_time` string, date-time, required
    - `headline` string, required
    - `is_live` boolean, required
    - `app_id` string, nullable
    - `app_name` string, nullable
    - `segment_id` string, nullable
    - `matter_segment` MatterSegmentSummaryDto: Summary of matter and segment for time blocks.
      - `matter_id` string, required: Matter ID
      - `matter_name` string, required: Matter name
      - `segment_id` string, required: Segment ID
      - `segment_name` string, required: Segment name
      - `segment_order` integer, required: Display order of the segment within the matter
      - `is_root` boolean, required: Whether this is the root segment
      - `root_segment_id` string, nullable: Root segment ID of the matter
    - `activity_code` string, nullable
    - `time_entry_id` integer, nullable
    - `source_type` 'APP' | 'MS365_CALL' | 'MS365_EMAIL' | 'MS365_CALENDAR_EVENT', required: Source of a time block.
    - `headline_attempt_status` 'not_attempted' | 'succeeded' | 'skipped_no_signal' | 'failed_terminal': Vocabulary for `time_blocks.headline_attempt_status`. Stored as a `(str, Enum)` so the cursor-sync wire DTO can type the field as the enum and Pydantic v2 serializes to the bare value ('not_attempted' etc.) — the qualified-name footgun of plain `str(EnumMember)` is avoided.
    - `artifacts` BlockArtifactsDto: Artifacts for one block: a capped list plus the honest total. ``total`` is the pre-cap count of displayed (doc+email) artifacts — the same population as ``items`` — so a client showing the first N can render an honest "+more" without the wire ever implying the capped list is complete.
      - `items` ArtifactDto[]
        - `kind` 'doc' | 'email', required
        - `title` string, required
        - `location` string, nullable
      - `total` integer
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `deleted_at` string, date-time, nullable
    - `version` integer, required
  - `affected_time_entries` TimeEntrySyncDto[]: Entries whose tracked_duration_minutes (or membership) changed
    - `id` integer, required
    - `organization_id` string, required
    - `user_id` string, required
    - `date` string, date, required
    - `legal_time_minutes` integer, required
    - `legal_time_is_computed` boolean, required
    - `tracked_duration_minutes` integer, required
    - `narrative` string, nullable, required
    - `narrative_suggestions` string[], nullable
    - `activity_code` string, nullable
    - `segment_id` string, nullable
    - `matter_segment` MatterSegmentSummaryDto: Summary of matter and segment for time blocks.
      - `matter_id` string, required: Matter ID
      - `matter_name` string, required: Matter name
      - `segment_id` string, required: Segment ID
      - `segment_name` string, required: Segment name
      - `segment_order` integer, required: Display order of the segment within the matter
      - `is_root` boolean, required: Whether this is the root segment
      - `root_segment_id` string, nullable: Root segment ID of the matter
    - `is_billable` boolean, required
    - `legal_time_pinned` boolean, required
    - `legal_time_resnapped_from` integer, nullable
    - `is_user_created` boolean, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `deleted_at` string, date-time, nullable
    - `version` integer, required

## 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)
