---
title: "Upsert Rows"
method: POST
path: "/studio/v1/audiences/{audienceId}/rows/actions/upsert"
tags: ["Audiences"]
---

# Upsert Rows

`POST /studio/v1/audiences/{audienceId}/rows/actions/upsert`

## Request

- Base URL: `https://api.zoominfo.com/gtm`
- URL: `https://api.zoominfo.com/gtm/studio/v1/audiences/{audienceId}/rows/actions/upsert`
- Auth: OAuth 2
  - Authorization code: `https://login.zoominfo.com`
  - Token URL: `https://okta-login.zoominfo.com/oauth2/default/v1/token` scopes: `api:audience:manage`

Creates and/or updates up to 50 rows in an audience in a single synchronous operation.
Each entry in the request body includes cell values keyed by `columnId`. Including a `rowId` updates that existing row; omitting `rowId` creates a new row.
Both creates and updates can be combined freely in the same request.
Use this endpoint when upserting **50 rows or fewer**. For larger batches (up to 500 rows), use [Bulk Upsert Rows](ref:Rows_upsertRows) at `POST /actions/bulk/upsert` instead.
Returns `200` with `data[]` row resources — each entry includes `id`, `type`, and `attributes.values` with full cell details (`columnId`, `value`, `state`, and `errorDetails` when applicable).
Returns `400` if the request body is malformed, exceeds 50 rows, or `columnId` references are invalid.

## Path parameters

- `audienceId` string, uuid, required

## Request body

- RowUpsertListApiModel: JSON API model for synchronous upsert Row request (≤ 50 rows). Row `id` is optional — omit to create, provide to update.
  - `data` UpsertRow[], required: The primary data of the document
    - `id` string: The unique identifier for the resource
    - `type` string, required: The type of the resource
    - `attributes` RowAttributes, required: Contains all cell data for a row, organized as an array of `CellDetails` objects — one per column.
      - `values` CellDetails[], required: Array of cell details for this row. Each entry corresponds to one column identified by `columnId`.
        - `columnId` string, required: The `columnId` identifying which column this cell belongs to.
        - `value` union, required: The cell's current value. Type must match the column's `dataType`. Provide on create/update; returned on read. This could be of datatypes `string`, `number`, `boolean`, `string array`, `numeric array`, `JsonString(JsonObject, JsonArrayOfObjects)` depending on the column definition
          - string
          - number
          - boolean
          - string[]: Represents a list of string values for a field
          - number[]: Represents a list of numeric values for a field
        - `state` 'RESULT' | 'BLANK' | 'LOADING' | 'ERROR' | 'NO_RESULT', required: Processing state of a cell value within a row. Indicates whether enrichment has run and what the outcome was.
        - `errorDetails` CellErrorDetails: Describes an error that occurred during enrichment for a specific cell.
          - `summary` string, required: Short human-readable label for the error.
          - `description` string, required: Full explanation of the error — what went wrong and why.
          - `retryable` boolean, required: Whether re-running enrichment for this cell is expected to succeed. If `false`, the error is permanent until the underlying data issue is resolved.

## Response `200`

Success

- UpsertRowsJsonApiModel: JSON API response for bulk row upsert. Returns created/updated rows in `data[]`, matching the get row by ID response shape (includes `state` and `errorDetails` per cell).
  - `data` Row[], required: The primary data of the document
    - `id` string, required: The unique identifier for the resource
    - `type` string, required: The type of the resource
    - `attributes` RowAttributes, required: Contains all cell data for a row, organized as an array of `CellDetails` objects — one per column.
      - `values` CellDetails[], required: Array of cell details for this row. Each entry corresponds to one column identified by `columnId`.
        - `columnId` string, required: The `columnId` identifying which column this cell belongs to.
        - `value` union, required: The cell's current value. Type must match the column's `dataType`. Provide on create/update; returned on read. This could be of datatypes `string`, `number`, `boolean`, `string array`, `numeric array`, `JsonString(JsonObject, JsonArrayOfObjects)` depending on the column definition
          - string
          - number
          - boolean
          - string[]: Represents a list of string values for a field
          - number[]: Represents a list of numeric values for a field
        - `state` 'RESULT' | 'BLANK' | 'LOADING' | 'ERROR' | 'NO_RESULT', required: Processing state of a cell value within a row. Indicates whether enrichment has run and what the outcome was.
        - `errorDetails` CellErrorDetails: Describes an error that occurred during enrichment for a specific cell.
          - `summary` string, required: Short human-readable label for the error.
          - `description` string, required: Full explanation of the error — what went wrong and why.
          - `retryable` boolean, required: Whether re-running enrichment for this cell is expected to succeed. If `false`, the error is permanent until the underlying data issue is resolved.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `402`: Payment Required
- `403`: Forbidden
- `429`: Too Many Requests

---

[API](https://skmtc.dev/zoominfo/apis/gtm-studio-api-v1.md) - [All operations](https://skmtc.dev/zoominfo/apis/gtm-studio-api-v1/llms.txt) - [OpenAPI document](https://skmtc.dev/zoominfo/apis/gtm-studio-api-v1/revisions/93a0bebaaac8?raw)
