# Entity Operations (/reference/sdk/entities)



Every entity exposes the same CRUD interface plus domain-specific verbs. CRUD is automatic -- you never define it. Custom verbs are declared in the `Noun()` definition and follow the same calling convention.

CRUD Methods [#crud-methods]

```typescript
import { Contact } from '@headlessly/crm'

// Create — returns the new entity with generated ID
const contact = await Contact.create({
  name: 'Alice Chen',
  email: 'alice@acme.com',
  stage: 'Lead',
})
// => { id: 'contact_fX9bL5nRd', name: 'Alice Chen', ... }

// Get — fetch a single entity by ID
const found = await Contact.get('contact_fX9bL5nRd')

// Find — query with filters, returns an array
const leads = await Contact.find({ stage: 'Lead' }, { limit: 25 })

// Update — partial update, returns the updated entity
const updated = await Contact.update('contact_fX9bL5nRd', {
  stage: 'Qualified',
})

// Delete — soft delete (immutable log preserved), returns void
await Contact.delete('contact_fX9bL5nRd')
```

Method Signatures [#method-signatures]

| Method   | Signature                                          | Returns              |
| -------- | -------------------------------------------------- | -------------------- |
| `create` | `create(data: Partial<T>)`                         | `Promise<T>`         |
| `get`    | `get(id: string)`                                  | `Promise<T \| null>` |
| `find`   | `find(filter?: Filter<T>, options?: QueryOptions)` | `Promise<T[]>`       |
| `update` | `update(id: string, data: Partial<T>)`             | `Promise<T>`         |
| `delete` | `delete(id: string)`                               | `Promise<void>`      |
| `count`  | `count(filter?: Filter<T>)`                        | `Promise<number>`    |

Custom Verbs [#custom-verbs]

Custom verbs follow the same pattern as CRUD but express domain-specific transitions. Every verb has a full lifecycle: execute, BEFORE hook, AFTER hook, and reverse reference.

```typescript
import { Contact } from '@headlessly/crm'
import { Deal } from '@headlessly/crm'

// Execute a verb — pass the entity ID and any additional data
await Contact.qualify({ id: 'contact_fX9bL5nRd' })
await Deal.close({ id: 'deal_k7TmPvQx', wonAmount: 50000 })

// Verb lifecycle
Contact.qualifying(contact => { /* BEFORE hook — validate, transform, reject */ })
Contact.qualified(contact => { /* AFTER hook — react, trigger side effects */ })
```

Entity ID Format [#entity-id-format]

All IDs follow the `{type}_{sqid}` pattern. The prefix is the lowercase entity type. The suffix is a [sqid](https://sqids.org/) -- short, unique, URL-safe, with a built-in blocklist.

```typescript
'contact_fX9bL5nRd'    // Contact
'deal_k7TmPvQx'        // Deal
'project_e5JhLzXc'     // Project
'invoice_mW3vRtYn'     // Invoice
'ticket_pQ8xNfKm'      // Ticket
```

Entities by Domain [#entities-by-domain]

Identity [#identity]

`@headlessly/sdk` -- User, ApiKey

| Entity     | Custom Verbs                        |
| ---------- | ----------------------------------- |
| **User**   | `activate`, `suspend`, `deactivate` |
| **ApiKey** | `rotate`, `revoke`                  |

CRM [#crm]

`@headlessly/crm` -- Organization, Contact, Lead, Deal, Activity, Pipeline

| Entity           | Custom Verbs                                |
| ---------------- | ------------------------------------------- |
| **Organization** | `verify`, `enrich`                          |
| **Contact**      | `qualify`, `convert`, `churn`, `reactivate` |
| **Lead**         | `qualify`, `disqualify`, `convert`          |
| **Deal**         | `advance`, `close`, `lose`                  |
| **Activity**     | `complete`, `cancel`                        |
| **Pipeline**     | `activate`, `archive`                       |

```typescript
import { Contact, Organization, Deal, Activity } from '@headlessly/crm'

await Contact.qualify({ id: 'contact_fX9bL5nRd' })
await Deal.close({ id: 'deal_k7TmPvQx' })
await Activity.complete({ id: 'activity_jR5nLwXp' })
```

Billing [#billing]

`@headlessly/billing` -- Customer, Product, Plan, Price, Subscription, Invoice, Payment

| Entity           | Custom Verbs                              |
| ---------------- | ----------------------------------------- |
| **Customer**     | `verify`, `suspend`, `reactivate`         |
| **Product**      | `publish`, `archive`                      |
| **Plan**         | `activate`, `deprecate`                   |
| **Price**        | `activate`, `archive`                     |
| **Subscription** | `upgrade`, `downgrade`, `cancel`, `renew` |
| **Invoice**      | `finalize`, `void`, `refund`              |
| **Payment**      | `capture`, `refund`                       |

```typescript
import { Subscription, Invoice } from '@headlessly/billing'

await Subscription.upgrade({ id: 'sub_nR4wKpYm', plan: 'enterprise' })
await Invoice.finalize({ id: 'invoice_mW3vRtYn' })
```

Projects [#projects]

`@headlessly/projects` -- Project, Issue, Comment

| Entity      | Custom Verbs                           |
| ----------- | -------------------------------------- |
| **Project** | `archive`, `complete`                  |
| **Issue**   | `assign`, `start`, `complete`, `block` |
| **Comment** | `resolve`, `pin`                       |

```typescript
import { Issue, Project } from '@headlessly/projects'

await Issue.assign({ id: 'issue_bN7xKmRw', assignee: 'contact_fX9bL5nRd' })
await Project.complete({ id: 'project_e5JhLzXc' })
```

Content [#content]

`@headlessly/content` -- Content, Asset, Site

| Entity      | Custom Verbs                                  |
| ----------- | --------------------------------------------- |
| **Content** | `publish`, `unpublish`, `schedule`, `archive` |
| **Asset**   | `process`, `tag`                              |
| **Site**    | `publish`, `deploy`                           |

Support [#support]

`@headlessly/support` -- Ticket

| Entity     | Custom Verbs                              |
| ---------- | ----------------------------------------- |
| **Ticket** | `assign`, `escalate`, `resolve`, `reopen` |

Analytics [#analytics]

`@headlessly/analytics` -- Event, Metric, Funnel, Goal

| Entity     | Custom Verbs                   |
| ---------- | ------------------------------ |
| **Event**  | -- (immutable, create only)    |
| **Metric** | `snapshot`, `reset`            |
| **Funnel** | `activate`, `pause`            |
| **Goal**   | `achieve`, `extend`, `abandon` |

Marketing [#marketing]

`@headlessly/marketing` -- Campaign, Segment, Form

| Entity       | Custom Verbs                  |
| ------------ | ----------------------------- |
| **Campaign** | `launch`, `pause`, `complete` |
| **Segment**  | `refresh`, `freeze`           |
| **Form**     | `publish`, `unpublish`        |

Experiments [#experiments]

`@headlessly/experiments` -- Experiment, FeatureFlag

| Entity          | Custom Verbs                   |
| --------------- | ------------------------------ |
| **Experiment**  | `start`, `conclude`, `abort`   |
| **FeatureFlag** | `enable`, `disable`, `rollout` |

Platform [#platform]

`@headlessly/platform` -- Workflow, Integration, Agent

| Entity          | Custom Verbs                    |
| --------------- | ------------------------------- |
| **Workflow**    | `activate`, `pause`, `trigger`  |
| **Integration** | `connect`, `disconnect`, `sync` |
| **Agent**       | `deploy`, `pause`, `invoke`     |

```typescript
import { Workflow, Agent } from '@headlessly/platform'

await Workflow.activate({ id: 'workflow_tP6yMnVk' })
await Agent.deploy({ id: 'agent_wQ2xLrHj' })
```

Communication [#communication]

`@headlessly/sdk` -- Message

| Entity      | Custom Verbs                         |
| ----------- | ------------------------------------ |
| **Message** | `send`, `deliver`, `read`, `archive` |
