---
tags: [write, version, create, entity-field]
endpoints: [POST /entity/<type>, GET /schema/<Type>/fields]
phase: write
scope: api
measured: sandbox project, Versions and Shots created and deleted
verdict: The schema's mandatory flags are not the create contract: on every project-scoped type measured, `project` is required and the identity field is optional, server-generated and not unique.
---

# 012_create_version

**Q** What does creating a Version require, and how are entity links written on create?

**Endpoint** `POST /api/v1/entity/versions ; POST /api/v1/entity/shots ; GET /schema/Version/fields`

**Docs claim** Versions need a project; entity links are written as `{type, id}`.

**Actual**

```
sandbox project id: 1180
Version mandatory fields: ['code']
POST /entity/shots -> 201
shot id: 7444
  201 minimal (project + code): id=26262 rels=['created_by', 'cuts', 'notes', 'open_notes', 'playlists', 'project', 'published_files', 'sg_deliveries', 'tags', 'tasks', 'updated_by', 'user']
  201 with entity link: id=26263 rels=['created_by', 'cuts', 'entity', 'notes', 'open_notes', 'playlists', 'project', 'published_files', 'sg_deliveries', 'tags', 'tasks', 'updated_by', 'user']
  400 entity as bare id (no type): null
  400 no project at all: null
```

**Teaches**
- **Trap.** `/schema/Version/fields` marks only `code` mandatory, yet a body without `project` 400s.
- An entity link is a hash: `"entity": {"type": "Shot", "id": N}` creates, `"entity": <id>` 400s.
  `project` takes the identical shape, and reads return both under `relationships` (probe 004).
- The 201 `relationships` block lists slots that were never set (`cuts`, `playlists`, `tags`), so its keys
  are not a record of your input. `entity` appears only when it was written, the one usable confirmation.
- Both 400s recorded as `null`: the probe captured `errors[0].detail` and these errors have none. The
  status codes are verified; the message text is `<unverified>`.

**The create contract, every type measured since.** Version is not a special case. One row per card,
`entity_types/<Type>`:

| type | identity field | flagged `mandatory` | actually required | omitted identity becomes | `unique` |
|---|---|---|---|---|---|
| Version | `code` | yes | no | `New Version <id>` | no |
| Shot | `code` | yes | no | `New Shot <id>` | no |
| Asset | `code` | yes | no | `New Asset <id>` | no |
| Sequence | `code` | yes | no | `New Sequence <id>` | no |
| Task | `content` | yes | no | `New Task <id>` | unmeasured |
| Playlist | `code` | yes | no | `New Playlist <id>` | no |
| PublishedFile | `code` | yes | no | `New Published File <id>` | no |
| Note | `subject` | yes | no | nothing; the row has no title | no |
| TimeLog | none | only `id` | n/a | n/a; `description` reads `New Time Log` | no |
| Delivery | `title` | yes | no | `New Delivery <id>` | no |

For a project-scoped type, `project` is the requirement and is flagged `mandatory: false`; the identity
field is flagged `mandatory: true` and is optional, generated by the server when omitted. `{}` and the
identity field alone both answer 400 `API create() missing 'project' attribute:` with the body echoed.
Nothing is unique on any of them, so keying on `code` is wrong on every type measured: match on `id`, and
treat a `code` lookup as a query that can return more than one row.

Omitting the key and sending an empty one are different. `{"code": ""}` on a create is 400 code 104
`Create failed for [Shot]: Cannot set identifier field to empty. (Shot)` (`entity_types/Shot`), and
Sequence answers the same message for `""` and for `null` (`entity_types/Sequence`).

Site-wide types are the boundary, not the rule. `Project` has no `project` field at all, and its identity
`name` is the one field flagged both `mandatory` and `unique`, so a create there is not idempotent
(`entity_types/Project`).

`editable` is the same shape of flag and the same shape of wrong. `created_at` and `updated_at` are
flagged `editable: false` on Note, Reply, Task and Version, and a create body sets both (probe 070).
Neither flag describes the create path; send the body and read the 400.
