---
title: "Add objects"
method: POST
path: "/api/v2/projects/{projectId}/objects"
tags: ["Content"]
---

# Add objects

`POST /api/v2/projects/{projectId}/objects`

## Request

- Base URL: `https://davinci-app.com`
- URL: `https://davinci-app.com/api/v2/projects/{projectId}/objects`
- Auth: HTTP bearer

Adds objects to the running project, opening it if needed. The write goes
through the same path an interactive client uses, so parentage, layout, and
the broadcast to anyone else in the project all happen as normal.

The objects are in memory once this returns; they are in git only after a
commit. A response reporting fewer objects than were sent does not happen —
the request either applies in full or fails.

Every object needs a parent: its own `parent`, or the request's `parentId`.
Top-level model content goes in the Model package,
`00000000-0000-0000-0000-0000000model`, and references in the Library,
`00000000-0000-0000-0000-00000library`.

Every object is checked against the schema for its `type`, then against
the project the way the Davinci agent's own writes are: its parent has to
exist and be able to hold its type, its children have to exist, and its
relationship types have to be ones the project defines. One bad object
fails the whole request and the project is left untouched. Any type the
model defines can be written here; the 400 names what was wrong with each
object it refused.

## Query parameters

- `branch` string

## Request body

- AddObjectsRequest
  - `objects` object, required: Objects to add, keyed by the id each should take. A key is an id, so it must be a UUID — mint one per object. Ids must be unique within the project; reusing one overwrites, which is why guessable keys are not accepted. Each body is validated against the schema for its `type`. Fields differ by type, anything the type does not define is refused rather than dropped, and every field is optional except `type` and `parent`, which `parentId` can supply for the whole request — the model supplies the rest. `tags` is refused here rather than accepted and discarded: creation does not carry them. Assign them once the object exists.
  - `parentId` string, nullable: Parent for every object that does not name its own, such as `00000000-0000-0000-0000-0000000model` for the top of the Model package.

## Response `201`

Objects added.

- AddObjectsResponse
  - `addedCount` integer, required
  - `objectIds` string[], required

## Other responses

- `400`: Nothing was written. `INVALID_OBJECTS` means the `objects` map itself was missing, empty, or not a map. `INVALID_OBJECT` means at least one object was refused: `details.objects` maps each refused id to what is wrong with it — a field its schema does not allow, no parent, or a parent that does not exist or cannot hold its type — and `details.validTypes` lists every writable type when a `type` was the problem.
- `401`: No credential was supplied, or the supplied credential is malformed, expired, or revoked. A credential that is present but unusable is never downgraded to an anonymous request.
- `403`: Authenticated but not authorized. Either the acting user lacks the required resource permission, the key's scope ceiling excludes it, or the endpoint rejects this credential type (`CREDENTIAL_NOT_PERMITTED`).
- `404`: The resource does not exist in the parent named by the path, or is hidden from the caller. Absence and privacy denial are deliberately indistinguishable so project, organization, and private-team existence cannot be probed.
- `409`: The project stopped running between being opened for this request and the request reaching it. Error code is `PROJECT_NOT_RUNNING`. Retry: the next call opens it again.
- `429`: Request rate exceeded, either globally or for this key.
- `500`: Unexpected server error.
- `502`: The project accepted the request but applied none of it. Error code is `OBJECTS_NOT_APPLIED`. Nothing was written; the request can be retried.
- `503`: The project could not be opened in time, or no machine is currently available to run it. Error codes are `PROJECT_NOT_READY`, `SERVER_NOT_AVAILABLE`, and `SERVICE_UNAVAILABLE`. Retry after the interval in `Retry-After`.

## Changes

- **2026-11-04** (v2) `279218ca2e8d`: 1 breaking, 1 info
  - the `parentId` request property format changed from `uuid` to no format
  - the `objects/additionalProperties/parent` request property format was generalized from `uuid` to no format
- **2026-09-15** (v2) `67c8b8616dbb`: 9 info
  - the `success` response property const value `false` was added for the status `400`
  - the `success` response property const value `false` was added for the status `401`
  - the `success` response property const value `false` was added for the status `403`
  - the `success` response property const value `false` was added for the status `404`
  - …5 more
- **2026-09-15** (v2) `48948af37797`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/celedon-solutions/apis/davinci-public-api/changes/api/v2/projects/:projectId/objects/post.md)

---

[API](https://skmtc.dev/celedon-solutions/apis/davinci-public-api.md) - [All operations](https://skmtc.dev/celedon-solutions/apis/davinci-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/celedon-solutions/apis/davinci-public-api/revisions/279218ca2e8d?raw)
