---
title: "Customize data model identifiers"
section: "build-a-backend/data/data-modeling"
platforms: ["android", "angular", "flutter", "javascript", "nextjs", "react", "react-native", "swift", "vue"]
gen: 2
last-updated: "2024-06-06T19:31:52.000Z"
url: "https://docs.amplify.aws/react/build-a-backend/data/data-modeling/identifiers/"
---

Identifiers are defined using the `.identifier()` method on a model definition. Usage of the `.identifier()` method is optional; when it's not present, the model will automatically have a field called `id` of type `ID` that is automatically generated unless manually specified.

```typescript
const schema = a.schema({
  Todo: a.model({
    content: a.string(),
    completed: a.boolean(),
  })
  .authorization(allow => [allow.publicApiKey()]),
});
```

<!-- Platform: javascript, angular, react-native, react, nextjs, vue, android, flutter -->
```ts
const client = generateClient<Schema>();

const todo = await client.models.Todo.create({ content: 'Buy Milk', completed: false });
console.log(`New Todo created: ${todo.id}`); // New Todo created: 5DB6B4CC-CD41-49F5-9844-57C0AB506B69
```
<!-- /Platform -->

<!-- Platform: swift -->
```swift
let todo = Todo(
    content: "Buy Milk", 
    completed: false)
let createdTodo = try await Amplify.API.mutate(request: .create(todo)).get()
print("New Todo created: \(createdTodo)")
```
<!-- /Platform -->

If you want, you can use Amplify Data to define single-field and composite identifiers:
- Single-field identifier with a consumer-provided value (type: `id` or `string`, and must be marked `required`)
- Composite identifier with a set of consumer-provided values (type: `id` or `string`, and must be marked `required`)

## Single-field identifier

If the default `id` identifier field needs to be customized, you can do so by passing the name of another field.

```typescript
const schema = a.schema({
  Todo: a.model({
    todoId: a.id().required(),
    content: a.string(),
    completed: a.boolean(),
  })
  .identifier(['todoId'])
  .authorization(allow => [allow.publicApiKey()]),
});
```

<!-- Platform: javascript, angular, react-native, react, nextjs, vue, android, flutter -->
```ts
const client = generateClient<Schema>();

const { data: todo, errors } = await client.models.Todo.create({ todoId: 'MyUniqueTodoId', content: 'Buy Milk', completed: false });
console.log(`New Todo created: ${todo.todoId}`); // New Todo created: MyUniqueTodoId
```
<!-- /Platform -->

<!-- Platform: swift -->
```swift
let todo = Todo(
    todoId: "MyUniqueTodoId",
    content: "Buy Milk",
    completed: false)
let createdTodo = try await Amplify.API.mutate(request: .create(todo)).get()
print("New Todo created: \(createdTodo)")
```
<!-- /Platform -->

## Composite identifier

For cases where items are uniquely identified by more than a single field, you can pass an array of the field names to the `identifier()` function:

```typescript
const schema = a.schema({
  StoreBranch: a.model({
    geoId: a.id().required(),
    name: a.string().required(),
    country: a.string(),
    state: a.string(),
    city: a.string(),
    zipCode: a.string(),
    streetAddress: a.string(),
  }).identifier(['geoId', 'name'])
  .authorization(allow => [allow.publicApiKey()]),
});
```
<!-- Platform: javascript, angular, react-native, react, nextjs, vue, android, flutter -->
```ts
const client = generateClient<Schema>();

const branch = await client.models.StoreBranch.get({ geoId: '123', name: 'Downtown' }); // All identifier fields are required when retrieving an item
```
<!-- /Platform -->

<!-- Platform: swift -->
```swift
let queriedStoreBranch = try await Amplify.API.query(
  request: .get(
      StoreBranch.self,
      byIdentifier: .identifier(
          geoId: "123",
          name: "Downtown")))
```
<!-- /Platform -->
