# How custom objects work

Learn how object definitions, records, versions, and events fit together.

Custom objects let you define your own data models on top of Stripe. This page covers the core concepts. The guides for each area show them in practice.

## Object definitions and records

Every custom object has a definition, and each instance of it is a record:

- **Object definition**: The schema for one type of object, including its API names, display names, and typed fields. For example, a `support_ticket` definition describes what every support ticket looks like.
- **Record**: A single instance of a definition. Each support ticket is a record. A record has an `id` (prefixed `objrec_`), a `fields` object that holds your data, and attributes that Stripe manages: `object`, `object_definition`, `created`, and `livemode`.
- **API names**: Every definition has a singular and a plural API name in `snake_case`, such as `support_ticket` and `support_tickets`. By default, both names come from your object’s class name, and you can set them yourself with `@apiName`. API paths use the plural name (`/v2/extend/objects/support_tickets`). A record’s object value and its event types use the singular name (`v2.extend.objects.support_ticket` and `v2.extend.objects.support_ticket.created`).

## Fields and data types

Every field has a type. Custom objects support strings, integers, decimals, Booleans, enums, datetimes, object references, currencies, monetary amounts, and arrays. You declare fields in TypeScript and can add validation, such as minimum and maximum values, lengths, or item counts. Stripe checks values against the field’s type and validation when you write a record. See [Define custom objects](https://docs.stripe.com/custom-objects/define.md).

## References

A reference field points to another object. This can be a Stripe object (`Ref<Customer>`) or another custom object in the same app (`Ref<Package>`). References return as `{ type, id, url }`, so you can follow them to the target object. Stripe doesn’t check that the target exists, and deleting the target doesn’t change the reference.

## Apps and definitions

You define objects in code and package them in a [Stripe app](https://docs.stripe.com/stripe-apps/how-stripe-apps-work.md). `stripe generate app` creates a project with a `custom-objects/` folder for your definitions. `stripe apps upload` registers your definitions, creates their API endpoints, and adds them to the Dashboard. Uploading your app is the only way to create or change object definitions during private preview.

## The API and the generated SDK

Every custom object gets the same set of endpoints under `/v2/extend/objects/<plural_name>`. You can call them directly, or generate a typed Node.js SDK from your definitions so that record fields are typed in your code. See [Create and manage records](https://docs.stripe.com/custom-objects/records.md).

## Versioning

Your custom object definitions change over time. All the custom object definitions in your app share one semantic version. Each record request names the version it uses, except a delete, which removes the record for every version. Reads return the fields that version declares, and writes are validated against it. Stripe stores each record once, so clients on different versions read and write the same records. See [Version your custom objects](https://docs.stripe.com/custom-objects/versioning.md).

## Events

When a record changes, Stripe creates an event named for its object definition, for example `v2.extend.objects.support_ticket.created`. Events tell you which record changed, so you can start a workflow or update your other systems. See [React to custom object events](https://docs.stripe.com/custom-objects/events.md).

## Workflows and Stripe Apps

A [workflow](https://docs.stripe.com/workflows.md) can start when a record is created or updated, and it can create and update records as steps. A Stripe app can show your records in the Dashboard and let your team change them, including in a full-page app that gives your records their own Dashboard page. See [Use custom objects with Stripe Apps and Workflows](https://docs.stripe.com/custom-objects/apps-and-workflows.md).

## How it fits together

You define objects and package them in an app, and you work with records through the API or SDK. Events, Workflows, and Stripe Apps let you act on changes, and versioning lets your schema change without breaking existing integrations. You can see your records in the Dashboard. For end-to-end examples, see [Custom objects use cases](https://docs.stripe.com/custom-objects/use-cases.md).
