> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getkato.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Record sections API

> Configure object sections and import record-owned repeatable entries.

<img src="https://mintcdn.com/kato-18a08ddc/iklvkRn2D9L2yTP0/images/changelog/configurable-record-sections.webp?fit=max&auto=format&n=iklvkRn2D9L2yTP0&q=85&s=3e7433968edd09b61a417bb85abb80ad" alt="Isometric panels showing draggable attributes, grouped record details, and repeatable entries connected by mint lines." width={1774} height={887} loading="lazy" data-path="images/changelog/configurable-record-sections.webp" />

<Note>These endpoints are part of the upcoming record-sections release. Deploy the API with migrations 0135 and 0136 before using them.</Note>

Sections are shared object configuration. Integrations define their own business fields; Kato does not infer sections from workspace names or field prefixes. Paths are relative to `https://api.getkato.io/v1` and require a developer access key.

| Method | Path                                       | Scope           |
| ------ | ------------------------------------------ | --------------- |
| GET    | `/objects/:object/sections`                | `objects:read`  |
| PUT    | `/objects/:object/sections`                | `objects:write` |
| PUT    | `/records/:id/sections/:sectionId/entries` | `records:write` |

## Read and save a layout

`:object` accepts an object ID or slug. GET returns `{ "data": { "sections": [], "revision": 0 } }` for an unconfigured object. PUT replaces the layout and requires the most recently read revision. Preserve sections you want to keep; removing a section retains its saved answers. Successful PUT returns the saved sections and incremented revision. Stale or simultaneous saves return 409; reload and reconcile before retrying. Record-scoped keys cannot write object layouts.

A field section uses ordinary object field IDs in display order:

```json theme={null}
{
  "revision": 0,
  "sections": [{
    "id": "6c5aecb2-7762-42cc-8cff-32506a5e1bb7",
    "title": "Contact details",
    "fieldIds": ["object-field-id"]
  }]
}
```

A repeatable section defines child fields once. Child IDs are UUIDs, independent of ordinary object field IDs. Its `fieldIds` must be empty:

```json theme={null}
{
  "revision": 0,
  "sections": [{
    "id": "6c5aecb2-7762-42cc-8cff-32506a5e1bb7",
    "title": "Locations",
    "fieldIds": [],
    "repeatable": {
      "itemName": "location",
      "fields": [{
        "id": "db733f27-2b61-40b4-a848-c2c9742390ca",
        "name": "Name",
        "fieldType": "text"
      }]
    }
  }]
}
```

Layouts support up to 50 sections, 200 ordinary fields per field section, and 50 child fields per repeatable section. Titles are required (100 characters maximum); entry names are required (60 maximum). Duplicate fields within a section are invalid, but an ordinary field can appear in multiple sections. Saved section and child-field types cannot be changed in place. Layout bodies are limited to 256 KiB.

Child types: `text`, `number`, `date`, `email`, `phone`, `url`, `checkbox`, `select`. Select fields define `options: [{id, label, color}]`; values use option IDs. Fields are optional; null represents an empty value on a new entry. Reimporting an existing ID does not change its values. Dates use `YYYY-MM-DD`. Values must match the configured type.

## Import entries

Configure the repeatable section first, then import source entries using stable IDs:

```json theme={null}
{
  "entries": [{
    "id": "488afabb-085e-4400-b755-115735fb2e12",
    "values": {
      "db733f27-2b61-40b4-a848-c2c9742390ca": "Main office"
    }
  }]
}
```

Use UUID entry IDs. Imported entries belong to exactly one workspace, record and section. A batch accepts up to 100 unique IDs and a 2 MiB body. Values are keyed by child-field ID, never names or slugs. Unknown children or invalid values return 400.

Success returns `{ "data": { "imported": 1 } }`. The count means accepted submissions, including previously accepted IDs. This is an **insert-only source import**: retrying an ID preserves staff edits and removal tombstones. It does not replace all entries or delete entries omitted from a batch. A conflicting ID owned by another record or section returns 409 and rolls back the batch. Record-scoped keys may import only into their pinned record. Missing/deleted records and missing sections return 404.

Legacy integrations can explicitly configure `repeatable.legacyGroups: [{id, bindings}]`, where bindings map child UUIDs to object-local scalar field IDs. Populated legacy answers are projected until materialized. Legacy source IDs must be exactly `recordId:groupId`. This compatibility mechanism is explicit; new integrations should use ordinary UUID entry IDs.

## Errors and retries

Route validation, permission, lookup and conflict errors use `{ "error": { "code": "invalid_request|insufficient_scope|not_found|conflict", "message": "..." } }`. Authentication, body-size and rate-limit handling follow the [shared API conventions](/api-reference/authentication).

Retry transient transport errors, 408, 429 and 5xx with the same entry IDs and payload. Treat an incomplete or malformed success response as unacknowledged. Fix 400/403/404/409 causes before retrying. Never regenerate source IDs on a retry.
