SG Ground Truth

read after write

Every write ignores ?fields. A create returns what you sent plus the server defaults, an update returns the whole record, and neither resolves a dotted path, so re-read for those and after an upload.

API

Q What does a write return, and what must be re-read?

Endpoint POST /entity/versions ; PUT /entity/versions/{id} ; POST /entity/_batch ; POST {field}/_upload complete_upload ; DELETE /entity/versions/{id}

Docs claim The REST docs describe ?fields on reads only, and document no batch endpoint at all.

Actual

asked for on every verb: ['code', 'description', 'sg_status_list', 'created_at', 'created_by',
                          'project.Project.name', 'entity.Shot.code', 'sg_not_a_field']
read   POST _search        200  absent: ['sg_not_a_field']            <- dotted paths resolve
create POST                201  attributes=9  relationships=15  absent: ['project.Project.name', 'entity.Shot.code', 'sg_not_a_field']
create POST ?fields=...    201  attributes=9  relationships=15  absent: the same three
create POST, 3 more fields 201  attributes=12 relationships=15
update PUT                 200  attributes=52 relationships=20  absent: the same three
update PUT ?fields=...     200  attributes=52 relationships=20  absent: the same three
update PATCH               404  {"status": 404, "code": 103, "title": "Not Found", "detail": null}
  relationships.entity, identical on create and update:
    {"data": {"id": 7514, "name": "sh010", "type": "Shot"}, "links": {"self": ..., "related": ...}}

POST /entity/_batch
  415 Unsupported Content-Type 'application/vnd+shotgun.api3_array+json'  {"content_type": "Content-Type must be one of: 'application/json'."}
  400 Invalid JSON body. Expected Hash but received Array.
  400 Request Parameters invalid. {"requests": ["requests is missing"]}
  400 Request Parameters invalid. {"requests": {"0": {"entity": ["entity is missing"]}}}
  400 Request Parameters invalid. {"data": ["data hash containing field/value pairs is required for the given request"]}
  400 Request Parameters invalid. {"requests": {"0": {"request_type": ["request_type must be one of: create, update, delete"]}}}
  404 update keyed on entity_id rather than record_id: "Entity of type [Version] with id=0 does not exist."
  200 create row  outer keys ['data']                    attributes=9  relationships=15
  200 update row  outer keys ['data', 'links', 'status'] attributes=52 relationships=20
  200 delete row  {"request_type": "delete", "type": "Version", "id": N, "uuid": "...", "did_delete": true}
  404 a good create + a bad update: "Entity of type [Version] with id=999999999 does not exist."
      rows the good create left behind: 0

POST complete_upload -> 201, body 1 byte, a single space
  t+0.3s, 2.6s, 5.9s, 11.2s, 21.4s   image = <site>/images/status/transient/thumbnail_pending.png
  t+41.7s                            image = a presigned URL
DELETE -> 204, empty body. GET the same id -> 404

Teaches

  • There is no conditional write. If-Match, If-Unmodified-Since and If-None-Match are ignored and the update applies at 200, though a GET returns a weak ETag.
  • Echoing updated_at back is refused with API update() Task.updated_at is editable on create only. So a read-then-write guard narrows the race window and never closes it, and exactness needs serialisation outside the API (recipes/005).
operation the response returns it omits how to get the rest
POST /entity/<type> the fields of the request body, the server-set ones (created_at, updated_at, cached_display_name), and every relationship as {id, name, type} every field left at its default, and every dotted path GET /entity/<type>/{id}?fields=...
PUT /entity/<type>/{id} the whole record, changed fields and untouched ones alike dotted paths only the same follow-up GET
PATCH /entity/<type>/{id} nothing: 404 with a null detail everything use PUT
batch create row the same subset a single create returns as a single create one GET per created id
batch update row the whole record, wrapped with links and status dotted paths only the same follow-up GET
batch delete row did_delete, id, uuid any field value nothing to re-read
_upload complete_upload 201 with a one-byte body the stored path and the final URL poll the field until it stops matching /images/status/transient/
DELETE /entity/<type>/{id} 204, empty body everything the id answers 404 from then on
  • Trap. ?fields on a write is accepted and ignored, plain names and dotted paths alike, with no error, the same quiet drop a bogus ?fields name gets on a read (probe 004).

  • The reported create-versus-update asymmetry is real but inverted: the create response is the thin one. Neither verb resolves project.Project.name or entity.Shot.code, and both return the link's own name under relationships, so a second call is needed only for a linked entity's other fields.

  • On the probed site a Version create answers 9 attributes and 15 relationships and an update answers 52 and 20. The counts are site-specific; the ratio is the rule. A create body of 3 extra fields answered 12 attributes, so the create response is what you sent plus the server defaults, not a fixed list.

  • A batch endpoint does exist, undocumented: POST /entity/_batch, and it takes plain application/json, not the vendor Content-Type _search requires (probe 004).

    {"requests": [{"request_type": "create", "entity": "Version", "data": {...}},
                  {"request_type": "update", "entity": "Version", "record_id": N, "data": {...}},
                  {"request_type": "delete", "entity": "Version", "record_id": N}]}
    

    entity is the singular schema name, not the URL slug; the id key is record_id, and entity_id is read as 0 and 404s. One failing row rolls the whole batch back: a good create paired with an update of id 999999999 left 0 rows behind. The response is data, one row per request, in order.

  • Transcoding is the only write whose result is not readable at all on return (probe 013). On the probed site a 16x16 PNG thumbnail stayed at /images/status/transient/thumbnail_pending.png past t+21s and resolved by t+42s, so poll on the path prefix and never on elapsed time.

  • Unsettled. One team reports a newly created Version's linked-entity field reading back empty at the moment of its own creation event, and built a diagnostic to fail loudly on it.

  • This repo has no event listener, so the claim is untested here and a negative result would prove nothing. Settling it needs a listener reading the entity from inside the event callback and comparing against a read a second later.

Every entry on this site is the output of a probe in probes/. The corpus is generated by running those probes against a live Flow Production Tracking site, not written from memory.

Not affiliated with or endorsed by Autodesk. Flow Production Tracking is their product; this is an independent record of how its REST API answers.