# sib_custom_objects.upsertrecords: Sendinblue Package for Custom Objects operations that could not be mapped to a table.
sib_custom_objects.upsertrecords: Sendinblue Package for Custom Objects operations that could not be mapped to a table.
<Note title="Enterprise access only">Custom objects are only available to Enterprise plans.
This feature is in beta. These are subject to change.</Note>
Performs bulk create or update (upsert) operations for object records in a single asynchronous request. This endpoint is optimized for high-volume data imports and synchronization scenarios.
**How Upsert Works:**
- **Create**: Omit `identifiers`, or provide only `ext_id` (if it doesn't already exist). A new record is created with a Brevo-generated `id`.
- **Update**: Provide `id` (Brevo internal ID) or an `ext_id` that already exists. The matching record is updated with the new attribute values.
- **Important:** `id` is for **updates only**. Providing an `id` that does not belong to an existing record will fail during async processing (the HTTP response will still be 202, but the record will be rejected in the background). To create a new record with a stable external reference, use `ext_id` instead.
**Request Structure:**
Each object record in the `records` array can include:
- `identifiers`: Either `id` (internal Brevo ID) or `ext_id` (your external system ID) — required for updates. **Note:** use `id` (singular), not `ids`.
- `attributes`: Key-value pairs where each key is the attribute **key** (e.g., `company_name`), not the attribute label (e.g., "Company Name").
- `associations`: Controls linking and unlinking of associated records (optional). Each entry specifies:
- `object_type`: The type of the associated object
- `action`: `link` (default) to create the association, or `unlink` to remove it
- `records`: The associated records to link or unlink (each identified by `ext_id` or `id`)
- **Unlink is idempotent** — unlinking a non-existing association is a no-op (no error returned)
- `link` and `unlink` actions can be submitted for the same `object_type` in a single record entry
- Both associated records must already exist before a link can be created
> **Common mistake:** Passing the attribute **label** (the display name you see in the UI) instead of the attribute **key** will cause the attribute to be silently ignored and the record may not be created as expected.
**Asynchronous Processing:**
- Returns immediately with a `processId` (HTTP 202 Accepted)
- Use the processId to track status via the Get process API
**API and Schema Limitations:**
- Max 1000 object records per request
- Max request body size: 1 MB
- Max 500 attributes per object record (matches the schema limit of 500 attributes per object)
- Unknown attribute keys are silently ignored (no error, no attribute creation)
- Max 10 association records per associated object-type in each record of the request. If you need more, send multiple requests.
**Important Behaviors:**
- The object schema must be created before upserting records
- Unknown attribute keys are silently ignored (no error, no creation)
- Both associated object records must already exist before creating a link association
- Unlink operations are idempotent: attempting to unlink a non-existing association returns success
- `link` and `unlink` actions can be submitted for the same `object_type` in a single record entry
- Contact objects cannot be created via this endpoint
- For `category` and `multiple_category` attributes, pass the option **key** as the value (not the option label or option ID).
- The `id` identifier (internal Brevo ID) can only be used for **updating** existing records. To create new records, either omit identifiers (Brevo auto-generates an ID) or provide an `ext_id`.
**Errors:**
- Make sure both object records exist before associating them, else the API will return an error.
- This route does not create objects. The object where the object records are upserted by this API must be created already else the API will return an error "invalid object type".Parameters of Procedure
The following parameters can be used to control the behaviour of the procedure `sib_custom_objects.upsertrecords`. A value must be provided at all times for required parameters, but optional parameters in general do not need to have a value and the execution will default to a pre-defined behaviour. Values can be specified by position and by name. In both cases, all parameters not specified will be evaluated using their default values.
Value specification by position is done by listing all values from the first to the last needed value. For example: a `begin package.procedure(value1, value2, value3); end` on a procedure with four parameters will use the default value for the fourth parameter and the specified values for the first three.
Value specification by name is done by listing all values that require a value. For example with `begin package.procedure(name1 => value1, name3 => value3); end` on the same procedure will use the default values for the second and fourth parameters and the specified values for the first and third.
| Name | Data Type | Required | Default Value | Documentation |
|---|:---:|:---:|:---:|---|
| `p_object_type` | `string` | ☑ | | Object type for the records to upsert. Must be a previously created custom object type. Only lowercase alphanumeric characters and underscores are allowed (max 32 characters). |