# Batch upsert catalog records

Creates or updates multiple Catalog records at once, so you can send the same records again without creating duplicates.

Each record you send is matched to an existing record by its primary attribute values, then:

- If it matches an existing record, that record is updated. Only the attributes you include change: attributes you leave out keep their values, and an attribute sent with an empty `values` array is cleared.
- If it matches nothing, a new record is created. Existing records that no sent record matches are left unchanged.

When matching, the order of the primary values doesn't matter, and a primary attribute left empty matches only records where it's also empty. If any record in the batch can't be saved, none of them are saved.

[endpoint]
base_url = "https://incidents.betterstack.com"
path = "/api/v2/catalog/relations/{relation_id}/records/batch"
method = "PATCH"

[[path_param]]
name = "relation_id"
description = "The ID of the Catalog relation you want to create or update records for."
required = true
type = "string"

[[body_param]]
name = "[]"
description = "Array of records to create or update. Each record follows the format for [creating a single Catalog record](https://betterstack.com/docs/uptime/api/create-catalog-record/)."
required = true
type = "array"

[[header]]
name = "Authorization"
description = "Bearer `$TOKEN`"
required = true
type = "string"

[[header]]
name = "Content-Type"
description = "application/json"
required = true
type = "string"
[/endpoint]

[responses]
[[response]]
status = 200
description = '''Returns the records in the order you sent them. `meta.created` lists the IDs of the new records, and `meta.updated` the IDs of the existing records the batch matched.'''
body = '''{
  "data": [
    {
      "id": "67",
      "type": "catalog_record",
      "attributes": {
        "attributes": [
          {
            "attribute": { "id": 56, "name": "Team" },
            "values": [
              { "type": "String", "value": "My Team" }
            ]
          },
          {
            "attribute": { "id": 57, "name": "Team Lead" },
            "values": [
              { "type": "User", "item_id": 123, "name": "Alice Smith", "email": "alice@example.com" }
            ]
          }
        ]
      }
    },
    {
      "id": "68",
      "type": "catalog_record",
      "attributes": {
        "attributes": [
          {
            "attribute": { "id": 56, "name": "Team" },
            "values": [
              { "type": "String", "value": "Another Team" }
            ]
          },
          {
            "attribute": { "id": 57, "name": "Team Lead" },
            "values": [
              { "type": "User", "item_id": 124, "name": "Bob Jones", "email": "bob@example.com" }
            ]
          }
        ]
      }
    }
  ],
  "meta": {
    "created": ["68"],
    "updated": ["67"]
  }
}'''

[[response]]
status = 422
description = '''A record couldn't be saved, so no records were saved. `record_index` is that record's position in the array, counting from 0. A record fails when it matches several existing records, has the same primary attribute values as another record in the batch, or doesn't pass validation. Errors in the request itself, like an unknown attribute name, come without `record_index`.'''
body = '''{
  "errors": {
    "base": ["Record 1: Another row in this batch (index 0) has the same primary values."]
  },
  "record_index": 1
}'''

[/responses]

#### Example cURL

```shell
[label Example]
curl -X "PATCH" "https://incidents.betterstack.com/api/v2/catalog/relations/37/records/batch" \
     -H "Authorization: Bearer $TOKEN" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'[
  {
    "attributes": [
      {
        "attribute": { "id": "56", "name": "Team" },
        "values": [
          { "type": "String", "value": "My Team" }
        ]
      },
      {
        "attribute": { "id": "57", "name": "Team Lead" },
        "values": [
          { "type": "User", "email": "alice@example.com" }
        ]
      }
    ]
  },
  {
    "attributes": [
      {
        "attribute": { "id": "56", "name": "Team" },
        "values": [
          { "type": "String", "value": "Another Team" }
        ]
      },
      {
        "attribute": { "id": "57", "name": "Team Lead" },
        "values": [
          { "type": "User", "email": "bob@example.com" }
        ]
      }
    ]
  }
]'
```

[info]
#### Looking for the details of a specific parameter?
Explore [the list of all Catalog record API parameters](https://betterstack.com/docs/uptime/api/catalog-record-response-params/).
[/info]
