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

# Ingestion features

> Learn how to ingest and remove instances in your graph using apply, patch, replace, and delete operations.

This section describes how to ingest and remove instances in a graph using the [/model/instances](/api-reference/concepts/20230101/instances) and [/delete](/api-reference/concepts/20230101/instances) endpoints.

## Applying instances

This example `apply` request attempts to ingest a node with the external ID `pump42` into the space `equipment`, and set the `Pump/v1.producer` view property to "Acme Inc.".

```yaml theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
items:
  - instanceType: node
    space: equipment
    externalId: pump42
    sources:
      - source:
          type: view
          space: equipment
          externalId: Pump
          version: v1
        properties:
          producer: 'Acme Inc.'
```

You can also ingest properties directly into containers. All instances in a request are applied atomically, and you can apply a mix of nodes and edges. Consequently, all instances in a request are applied, or the entire request fails.

### Create, patch, and replace

When you apply instances, you can use three distinct modes depending on the existing state and the request parameters.

* If the instance does not exist at the time of ingestion, it will be **created**. This means that all required properties must be set.

* If the instance already exists, you have two updating methods: **`patch`** and **`replace`**. You choose the method by setting the value of the `replace` flag. The value can be `true` or `false`, and the default value is `false`.

  With `patch`, only the properties that are provided in the `sources` section of the request will be updated, leaving all other properties unchanged.

With `replace`, all properties will be updated, and omitted properties will be set to null. Consequently, all required properties must have a value specified in the request body when you update an instance with `replace=true`.

### Autocreate nodes

When ingesting instances, you can autocreate the targets of direct relation properties and ingest a graph without worrying about the order in which you ingest the instances. Use these properties to control this behavior:

* `autoCreateDirectRelations`: automatically create all missing direct relation target nodes (default: `true`.)
* `autoCreateStartNodes`: when set to `true`, automatically create any missing start nodes for the edge (default: `false`.) When the parameter is set to `false` and the indicated start node is not present, the request will fail with a HTTP status code of 409, indicating a conflict with the current state of the service.
* `autoCreateEndNodes`: when set to `true`, automatically create any missing end nodes for the edge (default: `false`.) When the parameter is set to `false` and the indicated end node is not present, the request will fail with a HTTP status code of 409, indicating a conflict with the current state of the service.

You need write access to a space to autocreate nodes in it.

### Optimistic concurrency control

Every instance has a version number. It starts at `version: 1` and increments by 1 each time the instance is changed. The `apply` endpoint supports optimistic concurrency control and allows you to specify an expected **existing** version on the instance. If an actual version is greater than the expected version, the request fails with status code `409`.

The following example creates a pump node with the external ID "pump42". We set `existingVersion` to `0` to make sure the node does not exist, and that you will be **creating** the node.

If the node `equipment.pump42` already exists, the request will fail. If it doesn't exist, the node is created.

```yaml theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
items:
  - instanceType: node
    space: equipment
    externalId: pump42
    existingVersion: 0
```

The next example illustrates a case where you want to update the node `equipment.pump42` and set the `Pump/v1.producer` property to "Acme Inc.", but only if the `producer` property is currently null, to prevent you from overwriting someone else's changes.

First, read the node and verify that the `producer` property is null and then apply the update specifying `existingVersion=$currentVersion`. If the first read request returns `version: 1`, you can apply the instance:

```yaml theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
items:
  - instanceType: node
    space: equipment
    externalId: pump42
    existingVersion: 1
    sources:
      - source:
          type: view
          space: equipment
          externalId: Pump
          version: v1
        properties:
          producer: 'Acme Inc.'
```

If someone has set the `producer` property in the meantime, their request has bumped the node's version to 2. Because you specified `existingVersion: 1`, but the actual value is `version: 2`, the request fails with status code `409`. You can read the node again, check if the `producer` property is null, and repeat the process with `existingVersion` set to 2.

You can also **not** fail the entire request when there are version conflicts, and instead ignore updates to the instances that have version conflicts. You do this by setting `skipOnVersionConflict` to `true` in the request.

<Note>
  Sending an update request that will **not** update the instance's properties will **not** bump the `version` or `lastUpdatedTime` of the instance.
</Note>

## Deleting instances

<Warning>
  If you have stored data across multiple containers using the **same** space and externalId combination, calling delete will delete all the data pertaining to the node.
</Warning>

To delete nodes and edges from the graph, you send a list of fully qualified external IDs to the `/delete` endpoint. This example deletes a node and an edge:

```yaml theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
items:
  - instanceType: node
    space: equipment
    externalId: pump42
  - instanceType: edge
    space: equipment
    externalId: i-dont-exist
```

The response from this request contains only the successfully deleted instances. In this case, only the node `equipment.pump42`, since the `equipment.i-dont-exist` edge does not exist:

```yaml theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
items:
  - instanceType: node
    space: equipment
    externalId: pump42
```

### Soft deletion

To support syncing deletes to secondary stores, instances are always soft deleted at first. The soft-deleted instances will be returned by the [/sync](/cdf/dm/dm_concepts/dm_querying#syncing---subscribing-to-changes) endpoint with `deletedTime` set to a non-null value.

After a grace period (3 days by default), the instances are deleted by the system. Soft deleted instances count towards the total instance [limits](/cdf/dm/dm_reference/dm_limits_and_restrictions#limits) for you CDF project.

<Note>
  You can not restore soft deleted instances.
</Note>

### Delete edges before nodes

Deleting a node will delete all edges connected to that node. It is a best practice to delete the edges before the nodes in order to avoid long running cascading deletes. It is critical to delete edges before the nodes when you have nodes with a large number of edges pointing to/from them.
