---
title: "A device posts its entries and the intervals they cover, idempotent on the entry id"
method: POST
path: "/v1/entries"
tags: ["entries"]
---

# A device posts its entries and the intervals they cover, idempotent on the entry id

`POST /v1/entries`

## Request

- Base URL: `https://api.sixminute.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.sixminute.ai/v1/entries`
- Auth: HTTP bearer

Carries the device header (X-Six-Minute-Device); the body's `device_id` must be that device. Each entry is answered with one outcome: `applied` (written), `unchanged` (the row was already exactly this, so a replayed batch is not an error) or `refused` with a sentence saying what to fix. The cloud refuses an entry whose `edited_at` is set, because it is the person's from their first edit and the engine may not replace it (Row E); an accounting field moved on a released row; a row under another member's name; a matter that is not this firm's; and a hand-made entry (no `as_judged`) whose narrative is longer than the firm's length, `narrative.max_chars` or else 240, which an engine-written draft is not held to here (D-230). A body carrying a local-only field of an entry (`summary`, `idle_ratio`, `observation_ids`, `assignment`, `assignment_ref`, `assigned_at`, `recording_id`) is a 422 for the whole batch: those never leave the device (D-85). Each item carries the intervals its entry covers (D-215): each lies inside the entry's block, with every observation made during it, tagged by source and with no cap (a `screen` item is `{source, t_start, t_end, app, bundle, title, host}`, `bundle` being the application's identity, a Mac bundle id or a Windows app id or executable name, `""` when unknown), and the text the judgment read, both sealed under the tenant key; the text is not stored under the `confidential` tier. The intervals are written with an applied item only: a refused or unchanged item writes none, and the replacement of an engine-owned draft replaces the intervals inside its block. An item whose intervals would overlap a stored interval of the author is refused. A new row's edges are checked on the grid at that point (D-219): a stored interval's edge, the item's own included, or a line of the day's unit (the firm's when the day opened, or now for a day not opened yet), never inside a stored interval; the stored intervals of the posting device and the earlier ids X-Six-Minute-Device-Known names, as the page snaps a hand-made entry (O12). An entry carries no billing field, no price and no durations: its hours are its block (D-218).

## Request body

- object
  - `device_id` string, required
  - `entries` object[], required
    - `entry` object, required
      - `id` string, required
      - `day` string, required
      - `time_zone` string, required
      - `timekeeper_id` string, required
      - `t_start` string, date-time, required
      - `t_end` string, date-time, required
      - `parts` object[]
        - `t_start` string, date-time, required
        - `t_end` string, date-time, required
      - `narrative` string, required
      - `matter_id` string, nullable
      - `attributes` object
      - `internal_note` string, nullable
      - `status` 'draft' | 'released'
      - `created_at` string, date-time, required
      - `updated_at` string, date-time, required
      - `released_at` string, date-time, nullable
      - `edited_at` string, date-time, nullable
      - `override_seconds` integer, nullable
      - `as_judged` object, nullable
        - `day` string, required
        - `time_zone` string, required
        - `timekeeper_id` string, required
        - `t_start` string, date-time, required
        - `t_end` string, date-time, required
        - `parts` object[]
          - `t_start` string, date-time, required
          - `t_end` string, date-time, required
        - `narrative` string, required
        - `matter_id` string, nullable
        - `attributes` object
        - `internal_note` string, nullable
        - `activity_type` string, nullable
        - `judged_at` string, date-time, required
    - `intervals` object[]
      - `t_start` string, date-time, required
      - `t_end` string, date-time, required
      - `evidence` object[], required
        - `t_start` string, date-time, required
        - `t_end` string, date-time, required
        - `app` string, required
        - `bundle` string
        - `title` string, required
        - `host` string, nullable, required
        - `source` 'screen', required
        - `microphone` boolean
        - `camera` boolean
      - `text` string, nullable, required
      - `summary` string, nullable
      - `activity` object, nullable
        - `key` string, required
        - `label` string, nullable, required
      - `stripped` boolean
    - `how` 'drag' | 'form'

## Response `200`

One outcome per entry of the batch, in no promised order.

- object
  - `results` object[], required
    - `id` string, required
    - `outcome` 'applied' | 'unchanged' | 'refused', required
    - `reason` string

## Other responses

- `400`: The body, query or path did not validate; `errors` lists the fields.
- `401`: No bearer token, or one that does not verify or has expired.
- `403`: The token verified but may not do this: no organisation, not provisioned, wrong role, or a device problem.
- `422`: The request is well-formed but cannot be carried out as it stands.

---

[API](https://skmtc.dev/sixminute/apis/sixminute-api.md) - [All operations](https://skmtc.dev/sixminute/apis/sixminute-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sixminute/apis/sixminute-api/revisions/605577eadc10?raw)
