---
title: Create, update and restore records | Lightfield
description: Create CRM records, verify field changes, and recover a record moved to trash.
---

Use these operations to keep an external system in sync with Lightfield accounts, contacts, opportunities, notes, tasks and custom objects. For choosing the right record type, start with [Object types](/using-the-api/object-types/index.md). Meetings have a narrower write contract; use [Manage meeting records](/using-the-api/manage-meetings/index.md).

## Before you write

Use an [API key](/using-the-api/api-keys/index.md) with the selected resource’s read scope and the create, update or delete scope needed for your operation. Restore and listing trashed records require the resource’s `:restore` scope. Custom objects use `custom_objects:*` scopes, including `custom_objects:restore`, and their configured slug.

Find custom object slugs with [List object definitions](/api/resources/object/methods/listDefinitions/index.md), then read the object’s [field and relationship definitions](/using-the-api/fields-and-relationships/#discovering-definitions/index.md). Writes take bare values; reads return `fields[key].value`. Use the returned IDs for relationships, not display names. The examples below use fictional IDs; replace them with records in your workspace.

For imports, look for an existing record with a stable identifier before creating one. A find-then-create check alone is not atomic: serialize writes for the same source record and reuse its [idempotency key](/using-the-api/idempotency/index.md) when retrying.

## Create a record

This request creates an account without starting enrichment. Set `skipEnrichment` to `true` for imports whose data is already complete; omit it when you want Lightfield to enrich the new account.

Terminal window

```
curl https://api.lightfield.app/v1/accounts \
  -H "Authorization: Bearer $LIGHTFIELD_API_KEY" \
  -H "Lightfield-Version: 2026-03-01" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: import-northwind-account-001" \
  -d '{"fields":{"$name":"Northwind","$website":["https://northwind.example"]},"skipEnrichment":true}'
```

Save `id` from the response. An account response includes a value such as `fields.$name.value: "Northwind"`; use that returned `id` for the next request.

Use the same headers with the appropriate path and JSON body below. Each linked operation defines its complete writable fields.

| Create operation                                                      | Path                               | Example body and difference                                                                                                                                                                                  |
| --------------------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Account](/api/resources/account/methods/create/index.md)             | `/v1/accounts`                     | The request above requires `$name`; enrichment is optional.                                                                                                                                                  |
| [Contact](/api/resources/contact/methods/create/index.md)             | `/v1/contacts`                     | `{"fields":{"$name":{"firstName":"Ada","lastName":"Chen"},"$email":["ada@northwind.example"]},"skipEnrichment":true}`. A contact name is an object; email is an array.                                       |
| [Opportunity](/api/resources/opportunity/methods/create/index.md)     | `/v1/opportunities`                | `{"fields":{"$name":"Northwind renewal"},"relationships":{"$account":"acc_northwind"}}`. The account relationship is required; Stage is optional.                                                            |
| [Note](/api/resources/note/methods/create/index.md)                   | `/v1/notes`                        | `{"fields":{"$title":"Renewal call","$content":"Ada wants a proposal by Friday."},"relationships":{"$account":"acc_northwind"}}`. The author is set from the caller.                                         |
| [Task](/api/resources/task/methods/create/index.md)                   | `/v1/tasks`                        | `{"fields":{"$title":"Send renewal proposal","$status":"TODO"},"relationships":{"$assignedTo":"mem_ada","$account":"acc_northwind"}}`. Resolve the assignee with [Members](/using-the-api/members/index.md). |
| [Custom object record](/api/resources/object/methods/create/index.md) | `/v1/objects/subscriptions/values` | `{"fields":{"name":"Northwind annual subscription"}}`, **only if** your `subscriptions` definition has a writable text field named `name`; choose your actual slug and fields from definitions.              |

## Retrieve and update it

Retrieve by ID to verify a write immediately. Search-backed lists can lag. For an account:

Terminal window

```
curl "https://api.lightfield.app/v1/accounts/$RECORD_ID" \
  -H "Authorization: Bearer $LIGHTFIELD_API_KEY" \
  -H "Lightfield-Version: 2026-03-01"


curl "https://api.lightfield.app/v1/accounts/$RECORD_ID" \
  -X POST \
  -H "Authorization: Bearer $LIGHTFIELD_API_KEY" \
  -H "Lightfield-Version: 2026-03-01" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: rename-northwind-001" \
  -d '{"fields":{"$name":"Northwind Europe"}}'
```

Confirm the same `id` and the new `fields.$name.value` in the response. Only supplied fields change. Omission preserves a value; `null` clears it only where the schema permits null. Relationship updates use `add`, `remove` or `replace` as explained in [Fields and relationships](/using-the-api/fields-and-relationships/index.md).

| Resource      | Retrieve                                                                                      | Update                                                               | Example update body                                                        |
| ------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Account       | [GET `/v1/accounts/{id}`](/api/resources/account/methods/retrieve/index.md)                   | [POST same path](/api/resources/account/methods/update/index.md)     | `{"fields":{"$name":"Northwind Europe"}}`                                  |
| Contact       | [GET `/v1/contacts/{id}`](/api/resources/contact/methods/retrieve/index.md)                   | [POST same path](/api/resources/contact/methods/update/index.md)     | `{"fields":{"$name":{"firstName":"Ada","lastName":"Chen"}}}`               |
| Opportunity   | [GET `/v1/opportunities/{id}`](/api/resources/opportunity/methods/retrieve/index.md)          | [POST same path](/api/resources/opportunity/methods/update/index.md) | `{"fields":{"$name":"Northwind expansion"}}`                               |
| Note          | [GET `/v1/notes/{id}`](/api/resources/note/methods/retrieve/index.md)                         | [POST same path](/api/resources/note/methods/update/index.md)        | `{"fields":{"$content":"Proposal sent; follow up Friday."}}`               |
| Task          | [GET `/v1/tasks/{id}`](/api/resources/task/methods/retrieve/index.md)                         | [POST same path](/api/resources/task/methods/update/index.md)        | `{"fields":{"$status":"COMPLETE"}}`                                        |
| Custom object | [GET `/v1/objects/{entitySlug}/values/{id}`](/api/resources/object/methods/retrieve/index.md) | [POST same path](/api/resources/object/methods/update/index.md)      | `{"fields":{"name":"Northwind renewal"}}`, using an actual writable field. |

Use [list methods](/using-the-api/list-endpoints/index.md) to discover IDs: [accounts](/api/resources/account/methods/list/index.md), [contacts](/api/resources/contact/methods/list/index.md), [opportunities](/api/resources/opportunity/methods/list/index.md), [notes](/api/resources/note/methods/list/index.md), [tasks](/api/resources/task/methods/list/index.md) or [custom objects](/api/resources/object/methods/list/index.md). Custom-object listing uses `/v1/objects/{entitySlug}`, without `/values`.

## Delete and restore

Deletion moves the record to trash. Keep its ID so you can restore it; do not create a replacement to undo a deletion. Deleting an account through the API does not delete its associated contacts, tasks or notes.

Terminal window

```
curl "https://api.lightfield.app/v1/accounts/$RECORD_ID" \
  -X DELETE \
  -H "Authorization: Bearer $LIGHTFIELD_API_KEY" \
  -H "Lightfield-Version: 2026-03-01"


curl "https://api.lightfield.app/v1/accounts/$RECORD_ID/restore" \
  -X POST \
  -H "Authorization: Bearer $LIGHTFIELD_API_KEY" \
  -H "Lightfield-Version: 2026-03-01"
```

For each resource below, DELETE uses its retrieve path from the table above; restore uses POST to that path plus `/restore`.

| Resource      | Delete contract                                              | Restore contract                                               |
| ------------- | ------------------------------------------------------------ | -------------------------------------------------------------- |
| Account       | [Delete](/api/resources/account/methods/delete/index.md)     | [Restore](/api/resources/account/methods/restore/index.md)     |
| Contact       | [Delete](/api/resources/contact/methods/delete/index.md)     | [Restore](/api/resources/contact/methods/restore/index.md)     |
| Opportunity   | [Delete](/api/resources/opportunity/methods/delete/index.md) | [Restore](/api/resources/opportunity/methods/restore/index.md) |
| Note          | [Delete](/api/resources/note/methods/delete/index.md)        | [Restore](/api/resources/note/methods/restore/index.md)        |
| Task          | [Delete](/api/resources/task/methods/delete/index.md)        | [Restore](/api/resources/task/methods/restore/index.md)        |
| Custom object | [Delete](/api/resources/object/methods/delete/index.md)      | [Restore](/api/resources/object/methods/restore/index.md)      |

Check the deletion response for the same ID, then use the list endpoint with `status=trashed` to locate it. After restoration, retrieve it again. Deleting an already-trashed record and restoring an active record are no-ops for these resources. Custom-object restore must name the object’s actual slug.

## Recover from a rejected write

- **400:** check field keys, value types and writable fields against definitions. For a task, use a supported status and a member ID for the assignee.
- **403:** check the operation’s scopes and the caller’s role. A read-only role cannot write, even with a write scope.
- **404:** check the workspace, record type and ID before creating anything new. An unavailable record is not evidence that a duplicate should be created.
- **409 or uncertain network result:** follow the operation’s [retry rules](/using-the-api/idempotency/index.md); reuse the original key for supported writes.

Use [Merge duplicate records](/using-the-api/merge-records/index.md) when two existing IDs represent the same entity. Product users can manage the same records through [Lightfield basics](/help/getting-started/index.md) and [Deleted items](/help/deleted-items/index.md).
