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

# Save objects

> Adds or replaces records.

export const Legacy = ({title, href}) => {
  return <Note>

    This page documents an earlier version of the API client.
    For the latest version, see <a href={href}>{title}</a>.

    </Note>;
};

<Legacy title="Save records" href="/doc/libraries/sdk/methods/search/save-objects" />

**Required ACL:** `addObject`

Adds records to an [index](/doc/guides/sending-and-managing-data/prepare-your-data/in-depth/prepare-data-in-depth#algolia-index) or replaces them.

If a record doesn't contain an `objectID`, Algolia automatically adds it.
If you specify an existing `objectID`, it completely replaces all the attributes except for `objectID`.

To update only *some* attributes of an existing record, use [`partialUpdateObjects`](/doc/libraries/sdk/v1/methods/partial-update-objects) instead.
To add a single record, use the `saveObject` method.

**C#, Go, Java, JavaScript, PHP, Python only:**
To ensure good performance, `saveObjects` automatically sends batches of 1,000 records.
If you're indexing many records and have a stable, high-speed internet connection,
[increase the batch size](#increase-the-default-batch-size) to send more records per request and shorten your indexing time.

<Info>
  When updating large numbers of records, be aware of the [rate limitations](/doc/guides/scaling/algolia-service-limits#application-record-and-index-limits) on these processes and the [impact on your analytics data](/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/concepts/indices-analytics).
</Info>

## Examples

### Replace all attributes in existing records

<CodeGroup>
  ```cs C# theme={"system"}
  List<Contact> contacts = new List<Contact>
  {
      new Contact { ObjectID = "myID1", Firstname = "Jimmie", Lastname = "Barninger" },
      new Contact { ObjectID = "myID2", Firstname = "Warren", Lastname = "Speach" }
  };

  index.SaveObjects(contacts);

  // Asynchronous
  await index.SaveObjectsAsync(contacts);
  ```

  ```go Go theme={"system"}
  type Contact struct {
    ObjectID  string `json:"objectID"`
    Firstname string `json:"firstname"`
    Lastname  string `json:"lastname"`
  }

  contacts := []Contact{
    {ObjectID: "myID1", Firstname: "Jimmie", Lastname: "Barninger"},
    {ObjectID: "myID2", Firstname: "Ray", Lastname: "Charles"},
  }

  res, err := index.SaveObjects(contacts)
  ```

  ```java Java theme={"system"}
  // Sync version
  index.saveObjects(Arrays.asList(
      new Contact()
      .setFirstName("Jimmie")
      .setLastName("Barninger")
      .setObjectID("myID"),

      new Contact()
      .setFirstName("Warren")
      .setLastName("Speach")
      .setObjectID("myID2")
  ));

  // Async version
  index.saveObjectsAsync(Arrays.asList(
      new Contact()
      .setFirstName("Jimmie")
      .setLastName("Barninger")
      .setObjectID("myID"),

      new Contact()
      .setFirstName("Warren")
      .setLastName("Speach")
      .setObjectID("myID2")
  ));
  ```

  ```js JavaScript theme={"system"}
  const objects = [{
    firstname: 'Jimmie',
    lastname: 'Barninger',
    objectID: 'myID1'
  }, {
    firstname: 'Warren',
    lastname: 'Speach',
    objectID: 'myID2'
  }];

  index.saveObjects(objects).then(({ objectIDs }) => {
    console.log(objectIDs);
  });
  ```

  ```kotlin Kotlin theme={"system"}
  // With JsonObject
  val json = listOf(
      buildJsonObject {
          put("firstname", "Jimmie")
          put("lastname", "Barninger")
          put("objectID", "myID1")
      },
      buildJsonObject {
          put("firstname", "Warren")
          put("lastname", "Speach")
          put("objectID", "myID2")
      }
  )
  index.saveObjects(json)

  // With serializable class
  val contacts = listOf(
      MyContact("Jimmie", "Barninger", "myID1"),
      MyContact("Warren", "Speach", "myID2")
  )

  index.saveObjects(MyContact.serializer(), contacts)
  ```

  ```php PHP theme={"system"}
  $res = $index->saveObjects(
    [
      [
        'objectID'  => 'myID1',
        'firstname' => 'Jimmie',
        'lastname'  => 'Barninger'
      ],
      [
        'objectID'  => 'myID2',
        'firstname' => 'Warren',
        'lastname'  => 'Speach'
      ]
    ]
  );
  ```

  ```python Python theme={"system"}
  res = index.save_objects([
      {'firstname': 'Jimmie', 'lastname': 'Barninger', 'objectID': 'myID1'},
      {'firstname': 'Warren', 'lastname': 'Speach', 'objectID': 'myID2'}
  ])
  ```

  ```ruby Ruby theme={"system"}
  res = index.save_objects([{
    firstname: 'Jimmie',
    lastname:  'Barninger',
    objectID:  'myID1'
  }, {
    firstname: 'Warren',
    lastname:  'Speach',
    objectID:  'myID2'
  }])
  ```

  ```scala Scala theme={"system"}
  client.execute {
    index into "index1" objects Seq(
      Contact("myID1", "Jimmie", "Barninger"),
      Contact("myID2", "Warren", "Speach")
    )
  }
  ```

  ```swift Swift theme={"system"}
  struct Contact: Encodable {
    let objectID: ObjectID
    let firstname: String
    let lastname: String
  }

  let contacts: [Contact] = [
    .init(objectID: "myID1", firstname: "Jimmie", lastname: "Barninger"),
    .init(objectID: "myID2", firstname: "Warren", lastname: "Speach"),
  ]

  index.saveObjects(contacts) { result in
    if case .success(let response) = result {
      print("Response: \(response)")
    }
  }
  ```
</CodeGroup>

### Replace all attributes in a single record

<CodeGroup>
  ```cs C# theme={"system"}
  index.SaveObject(new Contact { ObjectID = "myID", Firstname = "Jimmie", Lastname = "Barninger", City = "New York" });

  // Asynchronous
  await index.SaveObjectAsync(new Contact { ObjectID = "myID", Firstname = "Jimmie", Lastname = "Barninger", City = "New York" });
  ```

  ```go Go theme={"system"}
  type Contact struct {
    ObjectID  string `json:"objectID"`
    Firstname string `json:"firstname"`
    Lastname  string `json:"lastname"`
    City      string `json:"city"`
  }

  contact := Contact{
    ObjectID:  "myID",
    Firstname: "Jimmie",
    Lastname:  "Barninger",
    City:      "New York",
  }

  res, err := index.SaveObject(contact)
  ```

  ```java Java theme={"system"}
  // Sync version
  index.saveObject(
    new Contact()
      .setFirstname("Jimmie")
      .setLastname("Barninger")
      .setCity("New York")
      .setObjectID("myID")
  );

  // Async version
  index.saveObjectAsync(
    new Contact()
      .setFirstname("Jimmie")
      .setLastname("Barninger")
      .setCity("New York")
      .setObjectID("myID")
  );
  ```

  ```js JavaScript theme={"system"}
  index.saveObject({
    firstname: 'Jimmie',
    lastname: 'Barninger',
    city: 'New York',
    objectID: 'myID'
  }).then(() => {
    // done
  });
  ```

  ```kotlin Kotlin theme={"system"}
  // With JsonObject
  val json = buildJsonObject {
      put("firstname", "Jimmie")
      put("lastname", "Barninger")
      put("objectID", "myID")
  }

  index.saveObject(json)

  // / With serializable class
  val contact = Contact("Jimmie", "Barninger", ObjectID("myID"))

  index.saveObject(Contact.serializer(), contact)
  ```

  ```php PHP theme={"system"}
  $index->saveObject(
    [
      'firstname' => 'Jimmie',
      'lastname'  => 'Barninger',
      'city'      => 'New York',
      'objectID'  => 'myID'
    ]
  );
  ```

  ```python Python theme={"system"}
  index.save_object({
      'firstname': 'Jimmie',
      'lastname': 'Barninger',
      'city': 'New York',
      'objectID': 'myID'}
  )
  ```

  ```ruby Ruby theme={"system"}
  index.save_object({
    firstname: 'Jimmie',
    lastname:  'Barninger',
    city:      'New York',
    objectID:  'myID'
  })
  ```

  ```scala Scala theme={"system"}
  client.execute {
    index into "index1" `object` Contact("myID", "Jimmie", "Barninger")
  }
  ```

  ```swift Swift theme={"system"}
  struct Contact: Encodable {
    let objectID: ObjectID
    let firstname: String
    let lastname: String
    let city: String
  }

  let contact: Contact = .init(objectID: "myID1", firstname: "Jimmie", lastname: "Barninger", city: "New York")

  index.saveObject(contact) { result in
    if case .success(let response) = result {
      print("Response: \(response)")
    }
  }
  ```
</CodeGroup>

### Replace all attributes in existing records and send extra HTTP headers

<CodeGroup>
  ```cs C# theme={"system"}
  List<Contact> contacts = new List<Contact>
  {
      new Contact { ObjectID = "myID1", Firstname = "Jimmie", Lastname = "Barninger" },
      new Contact { ObjectID = "myID2", Firstname = "Warren", Lastname = "Speach" }
  };

  RequestOptions requestOptions = new RequestOptions
  {
      Headers = new Dictionary<string,string>{ { "X-Algolia-User-ID", "user123" } }
  };

  index.SaveObjects(contacts, requestOptions);

  // Asynchronous
  await index.SaveObjectsAsync(contacts, requestOptions);
  ```

  ```go Go theme={"system"}
  type Contact struct {
    ObjectID  string `json:"objectID"`
    Firstname string `json:"firstname"`
    Lastname  string `json:"lastname"`
  }

  contacts := []Contact{
    {ObjectID: "myID1", Firstname: "Jimmie", Lastname: "Barninger"},
    {ObjectID: "myID2", Firstname: "Ray", Lastname: "Charles"},
  }

  extraHeaders := opt.ExtraHeaders(map[string]string{
    "X-Algolia-User-ID": "userID2",
  })

  res, err := index.SaveObjects(contacts, extraHeaders)
  ```

  ```java Java theme={"system"}
  List<Contact> contacts = Arrays.asList(
      new Contact()
      .setObjectID("MyID1")
      .setFirstName("Jimmie")
      .setLastName("Barninger"),

      new Contact()
      .setObjectID("MyID2")
      .setFirstName("Warren")
      .setLastName("Speach"));

  // Sync version
  index.saveObjects(
    contacts,
    new RequestOptions().addExtraHeader("X-Algolia-User-ID", "user123")
  );

  // Async version
  index.saveObjectsAsync(
    contacts,
    new RequestOptions().addExtraHeader("X-Algolia-User-ID", "user123")
  );
  ```

  ```js JavaScript theme={"system"}
  const objects = [/* objects */];

  index.saveObjects(objects, {
    headers: {
      'X-Forwarded-For': '94.228.178.246'
    }
  }).then(({ objectIDs }) => {
    console.log(objectIDs);
  });
  ```

  ```kotlin Kotlin theme={"system"}
  val json = listOf(
      buildJsonObject {
          put("objectID", "myID1")
          put("firstname", "Jimmie")
          put("lastname", "Barninger")
      },
      buildJsonObject {
          put("objectID", "myID2")
          put("firstname", "Warren")
          put("lastname", "Speach")
      }
  )
  val requestOptions = requestOptions {
      headerForwardedFor("94.228.178.246")
  }

  index.saveObjects(json, requestOptions)
  ```

  ```php PHP theme={"system"}
  $objects = [/* objects */];
  $index->saveObjects($objects, [
    'X-Forwarded-For' => '94.228.178.246'
  ]);
  ```

  ```python Python theme={"system"}
  objects = [
      # Objects
  ]
  res = index.save_objects(objects, {
      'X-Forwarded-For': '94.228.178.246'
  })
  ```

  ```ruby Ruby theme={"system"}
  res = index.save_objects(objects, {
    headers: {
      'X-Forwarded-For': '94.228.178.246'
    }
  })
  ```

  ```scala Scala theme={"system"}
  client.execute {
    index into "index1" objects Seq(
      Contact("myID", "Jimmie", "Barninger"),
      Contact("myID", "Speach")
    ) options RequestOptions(
      extraHeaders = Some(Map("X-Algolia-User-ID" => "user123"))
    )
  }
  ```

  ```swift Swift theme={"system"}
  struct Contact: Encodable {
    let objectID: ObjectID
    let firstname: String
    let lastname: String
  }

  var requestOptions = RequestOptions()
  requestOptions.headers["X-Forwarded-For"] = "94.228.178.246"

  let contacts: [Contact] = [
    .init(objectID: "myID1", firstname: "Jimmie", lastname: "Barninger"),
    .init(objectID: "myID2", firstname: "Warren", lastname: "Speach"),
  ]

  index.saveObjects(contacts, requestOptions: requestOptions) { result in
    if case .success(let response) = result {
      print("Response: \(response)")
    }
  }
  ```
</CodeGroup>

### Increase the default batch size

<CodeGroup>
  ```cs C# theme={"system"}
  var config = new SearchConfig("YourApplicationID", "YourWriteAPIKey")
  {
      BatchSize = 999999
  };

  var client = new SearchClient(config);
  ```

  ```go Go theme={"system"}
  config := search.Configuration{
      AppID:        "YourApplicationID",
      APIKey:       "YourWriteAPIKey",
      MaxBatchSize: 999999,
  }

  client := search.NewClientWithConfig(config)
  ```

  ```java Java theme={"system"}
    SearchConfig config =
    new SearchConfig.Builder("YourApplicationID", "YourWriteAPIKey")
        .setBatchSize(999999)
        .build();

  SearchClient client = DefaultSearchClient.create(config);
  ```

  ```php PHP theme={"system"}
  $config = new SearchConfig([
      'appId' => 'YourApplicationID',
      'apiKey' => 'YourWriteAPIKey',
      'batchSize' => 999999,
  ]);

  $client = SearchClient::createWithConfig($config);
  ```

  ```python Python theme={"system"}
  from algoliasearch.configs import SearchConfig
  from algoliasearch.search_client import SearchClient

  config = SearchConfig('YourApplicationID', 'YourWriteAPIKey')
  config.batch_size = 999999

  client = SearchClient.create_with_config(config)
  ```

  ```ruby Ruby theme={"system"}
  config = Algolia::Search::Config.new({
    application_id: 'YourApplicationID',
    api_key: 'YourWriteAPIKey',
    batch_size: 999999
  })

  client = Algolia::Search::Client.create_with_config(config)
  ```

  ```swift Swift theme={"system"}
  let configuration = SearchConfiguration(applicationID: "YourApplicationID", apiKey: "YourWriteAPIKey")
    .set(\.batchSize, to: 999999)
  let client = SearchClient(configuration: configuration)
  ```
</CodeGroup>

## Parameters

<ParamField body="objects" type="object[]" required>
  A list of [records](/doc/libraries/sdk/v1/methods/save-objects#param-objects) to save.
</ParamField>

<ParamField body="autoGenerateObjectIDIfNotExist" type="boolean" default={false}>
  `saveObjects` requires an `objectID` unless you set `autoGenerateObjectIDIfNotExist` to `true`.

  * If the `objectID` exists, Algolia replaces the record
  * If the `objectID` is present but doesn't exist, Algolia creates the record
  * If the `objectID` isn't specified and `autoGenerateObjectID` is `false` (the default), the engine returns an error.
  * If the `objectID` isn't specified and `autoGenerateObjectID` is `true`, the engine generates an `objectID` and returns it in the response.

  **Ruby only:** the parameter name is: `auto_generate_object_id_if_not_exist`.
</ParamField>

<ParamField body="objectIDKey" type="string">
  **PHP only:** The `objectID` is set from the value of the specified key.
</ParamField>

<ParamField body="requestOptions" type="object">
  A mapping of request options.
</ParamField>

## Response

<ResponseField name="objectID" type="string">
  The objectID of the saved record. This property is only returned when using **save object**.
</ResponseField>

<ResponseField name="objectIDs" type="list">
  List of objectIDs of the saved records in order. This property is only returned when using **save objects**.
</ResponseField>

<ResponseField name="taskID" type="integer">
  The task ID used with the [`waitTask`](/doc/libraries/sdk/v1/methods/wait-task) method.
</ResponseField>

### Response as JSON

This section shows the JSON response returned by the API.
Each API client wraps this response in language-specific objects, so the structure may vary.
To view the response, use the `getLogs` method.
Don't rely on the order of properties—JSON objects don't preserve key order.

#### Save records

```jsonc JSON icon=braces theme={"system"}
{
  "objectIDs": [
    "myObjectID1",
    "myObjectID2"
  ],
  "taskID": 678,
}
```

#### Save record

```jsonc JSON icon=braces theme={"system"}
{
  "objectID": "myObjectID1",
  "taskID": 678,
}
```
