# Standard Entity API 3.0

Standard entities are Sprinklr's pre-defined structured objects. They work like cases and messages, but they exist so you can store and manage your own external data inside the platform using a defined schema.

The Standard Entity API 3.0 gives you full CRUD across three layers: the **definition** that describes an entity type, the **fields** that make up its schema, and the **records** that hold your data.

## Overview

A standard entity has three parts, and every integration works with all three:

| Layer | What it holds | What you can do |
|  --- | --- | --- |
| **Definition** | The entity type itself, such as `_s_Consent`. Its name, description, icon, and permission settings. | Read |
| **Field** | One column on a definition. Has an API name, a data type, and optional picklist values, defaults, and constraints. | Create, read, update, delete |
| **Record** | One row of data stored against a definition. | Create, read, update, patch, upsert, delete |


Definitions are created and managed in Entity Studio. This API reads them; it does not create them. Fields and records are fully manageable through the API.

> Related Knowledge Base Article [Entity Studio - An Overview](https://www.sprinklr.com/help/articles/entity-studio-an-overview/entity-studio-an-overview/693a9c231db8130c76d78b40)


### Naming conventions

The platform uses two prefixes consistently, and recognising them makes the API much easier to read:

| Prefix | Means | Example |
|  --- | --- | --- |
| `_s_` | A standard, platform-supplied entity type or field | `_s_Consent` |
| `_c_` | A custom field you created | `_c_ConsentName` |


### Identifiers

Three identifiers appear across this API. They are not interchangeable:

| Identifier | Identifies | Notes |
|  --- | --- | --- |
| `entityDefinitionId` / `entityType` | A **definition**, such as `_s_Consent` | Also travels in a record payload as `type` |
| `entityId` | A **record** | One of the record's primary fields. You may set it yourself at create time; if you do not, the platform generates one |
| `recordId` | A **record** | An alternative record lookup key |


### Availability

The Standard Entity API 3.0 is available on **Core, Care, and Lite** editions and is enabled by default. No configuration is required.

## Base URL

```
https://api3.sprinklr.com/{env}/api/v3/standardEntity
```

Replace `{env}` with the environment your Sprinklr workspace is hosted in:

`prod`, `prod0`, `prod2`, `prod3`, `prod4`, `prod5`, `prod6`, `prod8`, `prod11`, `prod12`, `prod15`, `prod16`, `prod17`, `prod18`, `prod19`, `prod21`, `prod25`

Calling a different environment with otherwise valid credentials returns `401 Unauthorized`. If you are seeing unexplained `401` responses, check the environment first.

## Authentication

Every request must carry **both** an access token and an API key. Sending only one of them is the most common cause of a `401` for developers new to the platform.

| Header | Value | Required |
|  --- | --- | --- |
| `Authorization` | `Bearer {{accessToken}}` | Yes |
| `Key` | `{{apiKey}}` | Yes |
| `Content-Type` | `application/json` | On requests with a body |
| `Accept` | `application/json` | Recommended |


**Each API key supports one active token pair.** Generating a new access token invalidates the previous one. If two services share an API key, refreshing the token for one will break the other. Give each integration its own key.

## How the three layers fit together

A typical integration works top-down:

1. **Read the definition** to learn what entity type you are working with.
2. **Read the fields** to learn the schema — what columns exist, which are mandatory, what types they hold.
3. **Add any custom fields** your integration needs.
4. **Read and write records** against that schema.


You only need steps 1 to 3 once, at setup. Steps 4 runs continuously.

The following paths and methods are supported:

| Path | Methods |
|  --- | --- |
| `/standardEntity/definition` | `GET` |
| `/standardEntity/field` | `GET`, `POST`, `PUT`, `DELETE` |
| `/standardEntity/record` | `GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
| `/standardEntity/record/upsert` | `POST` |


## Definition operations

### Fetch a definition

Retrieve the definition of a standard platform entity by entity type.

```
GET /api/v3/standardEntity/definition
```

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `entityType` | query | string | Yes | The entity type to fetch, for example `_s_Consent`. Supported entity Ids: `_s_Consent`, `_s_PublishingQueue`, `_s_ConsentCatalogue`, `_s_PriceBook`, `_s_PublisherSettings` |


**Request**

```bash
curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/definition?entityType=_s_Consent' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Accept: application/json'
```

**Response fields**

| Field | Type | Description |
|  --- | --- | --- |
| `id` | string | Id of the definition |
| `name` | string | Name for the entity |
| `pluralName` | string | Plural name for the entity |
| `description` | string | Description for the entity |
| `baseDefinitionId` | string | Id of the base entity definition, if this is an extended entity |
| `icon` | string | Icon for the entity |
| `permissionEnabled` | boolean | Whether the entity is permission controlled |
| `script` | string | Script for external entity |
| `scriptVersion` | string | Script version. A compiled script is cached for some time; to update the script, update the version |
| `createdTime` | integer (int64) | Created time, epoch milliseconds |
| `modifiedTime` | integer (int64) | Last modified time, epoch milliseconds |


## Standard Entity-Field Operations

### Fetch fields

Fetch fields by ID or by field name, with pagination.

```
GET /api/v3/standardEntity/field
```

#### Query Parameters

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `fieldId` | query | string | Conditional | Comma-separated list of field IDs |
| `fieldName` | query | string | Conditional | Field name |
| `entityDefinitionId` | query | string | Conditional | The definition the field belongs to. Required when identifying a field by `fieldName` |
| `pageNumber` | query | integer | No | Page number, 0-based |
| `pageSize` | query | integer | No | Number of results per page. Maximum **100** |


**Supply exactly one identifier — `fieldId` or `fieldName`, never both and never neither.** Supplying both returns `400`; supplying neither also returns `400`.

Field names are unique only within a definition, so when you look a field up by `fieldName` you must also send `entityDefinitionId`.

**Request**

```bash
curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/field?fieldName=_c_ConsentName&entityDefinitionId=_s_Consent' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Accept: application/json'
```

Returns an array of field objects. See [Field reference](#field-reference).

### Create a field

```
POST /api/v3/standardEntity/field
```

#### Request Parameters

Send the field definition in the request body. There are no query parameters.

| Body field | Type | Required | Description |
|  --- | --- | --- | --- |
| `apiName` | string | Yes | The API name for the field. Prefix custom fields with `_c_` |
| `name` | string | No | A human-readable name describing the field's purpose |
| `type` | string | Yes | The field's data type. Supported values include `TEXT`, `DATE`, `BOOLEAN`, `NUMBER`, `DOUBLE`, `INTEGER` |
| `entityDefinitionId` | string | Yes | The definition to add the field to |


**Request**

```bash
curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/field' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "apiName": "_c_ConsentName",
    "name": "User Consent Name",
    "type": "TEXT",
    "entityDefinitionId": "_s_Consent"
  }'
```

Returns the created field, including its generated `id`. **Store that `id`** — it is the most reliable way to reference the field later.

### Update a field

```
PUT /api/v3/standardEntity/field
```

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `fieldId` | query | string | Conditional | The field ID |
| `fieldName` | query | string | Conditional | The field name |
| `entityDefinitionId` | query | string | Conditional | Required when using `fieldName` |


Send the updated field object in the request body. Identify the field by either `fieldId` or `fieldName`, not both.

**Request**

```bash
curl -X PUT \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/field?fieldName=_c_ConsentName&entityDefinitionId=_s_Consent' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "apiName": "_c_ConsentName",
    "name": "Consent Full Name",
    "type": "TEXT",
    "entityDefinitionId": "_s_Consent"
  }'
```

### Delete fields

```
DELETE /api/v3/standardEntity/field
```

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `id` | query | string | Conditional | Comma-separated list of field IDs |
| `fieldName` | query | string | Conditional | The field name |
| `entityDefinitionId` | query | string | Conditional | Required when using `fieldName` |


**Request**

```bash
curl -X DELETE \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/field?id=0000000000000000000000a1,0000000000000000000000a2&entityDefinitionId=_s_Consent' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}'
```

Deleting a field removes it from the definition. Data stored in that field on existing records is no longer retrievable through the API. Confirm before you delete.

## Standard Entity - Record Operations

### Fetch records

Fetch records by entity ID, record ID, primary key, or primary key prefix.

```
GET /api/v3/standardEntity/record
```

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `entityType` | query | string | Yes | The definition to search in, for example `_s_Consent` |
| `entityId` | query | string | Conditional | Comma-separated list of entity IDs |
| `recordId` | query | string | Conditional | Comma-separated list of record IDs |
| `primaryKey` | query | string | Conditional | Primary key exact lookup |
| `primaryKeyPrefix` | query | string | Conditional | Primary key prefix lookup |
| `pageNumber` | query | integer | No | Page number, 0-based |
| `pageSize` | query | integer | No | Number of results per page. Maximum **100** |


**Always send `entityType`, plus exactly one of `entityId`, `recordId`, or `primaryKey`.** `entityType` tells the platform which definition to look in; the identifier tells it which record.

Primary key lookup only works on entity types that have primary key columns defined. Types without them return `400`.

**Request**

```bash
curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/record?entityType=_s_Consent&entityId=6321e6684eed2b006dc0abdb' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Accept: application/json'
```

### Create a record

```
POST /api/v3/standardEntity/record
```

Send the record in the request body. There are no query parameters.

**Request**

```bash
curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/record' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "_s_Consent",
    "entityId": "consent-jane-doe-001",
    "identityType": "PHONE",
    "identityId": "15550100",
    "channel": "FACEBOOK"
  }'
```

The exact payload depends on the definition. `type` always carries the definition id. The remaining fields are the fields defined on that definition — read them first with [Fetch fields](#fetch-fields), and note which are marked `mandatory`.

#### Primary fields

Some fields on a definition are **primary fields**. On `_s_Consent`, these are `identityType`, `identityId`, and `channel`.

**At least one primary field must be present on every create and update, and the primary fields you send on update must match those you sent on create.** Changing a primary field does not edit the record — it fails to match the original record entirely. This is the single most common source of updates that appear to do nothing.

If you do not supply an `entityId`, the platform generates one and returns it in the response. Setting a meaningful `entityId` yourself — one derived from your own system's key — makes every later lookup, update, and upsert simpler.

### Replace a record

```
PUT /api/v3/standardEntity/record
```

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `entityType` | query | string | Yes | The definition |
| `entityId` | query | string | Conditional | The entity ID |
| `recordId` | query | string | Conditional | The record ID |


`PUT` replaces the record with the body you send. Include the primary fields, and make sure they match the values used at create time.

```bash
curl -X PUT \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/record?entityType=_s_Consent&entityId=consent-jane-doe-001' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "_s_Consent",
    "entityId": "consent-jane-doe-001",
    "identityType": "PHONE",
    "identityId": "15550100",
    "channel": "FACEBOOK"
  }'
```

### Patch a record

```
PATCH /api/v3/standardEntity/record
```

Takes the same query parameters as `PUT`, but the body names only the fields you want to change.

| Body field | Type | Required | Description |
|  --- | --- | --- | --- |
| `updateFields` | array | Yes | List of updates to apply |
| `updateFields[].fieldName` | string | Yes | The field to change |
| `updateFields[].value` | any | Yes | The new value |
| `updateFields[].op` | string | Yes | The operation to apply. One of `FIND`, `INSERT`, `PATCH`, `UPDATE`, `DELETE` |


**Request**

```bash
curl -X PATCH \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/record?entityType=_s_Consent&entityId=consent-jane-doe-001' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "updateFields": [
      { "fieldName": "_c_ConsentName", "value": "Jane Doe", "op": "UPDATE" }
    ]
  }'
```

**Prefer `PATCH` over `PUT` for routine writes.** It touches only the fields you name, it does not require you to reconstruct the whole record, and it avoids accidentally clearing a field you forgot to include.

### Upsert a record

```
POST /api/v3/standardEntity/record/upsert
```

Creates the record if it does not exist, updates it if it does. Send the record in the request body; there are no query parameters.

```bash
curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/record/upsert' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "_s_Consent",
    "entityId": "consent-jane-doe-001",
    "identityType": "PHONE",
    "identityId": "15550100",
    "channel": "FACEBOOK"
  }'
```

Upsert is the right choice for synchronisation jobs, where you do not know or do not care whether a record already exists.

### Delete records

```
DELETE /api/v3/standardEntity/record
```

| Parameter | In | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `entityType` | query | string | Yes | The definition |
| `entityId` | query | string | Conditional | Comma-separated list of entity IDs |
| `recordId` | query | string | Conditional | Comma-separated list of record IDs |


```bash
curl -X DELETE \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/record?entityType=_s_Consent&entityId=consent-jane-doe-001,consent-jane-doe-002' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}'
```

#### Deletes are reported per record

When you delete several records in one call, some may succeed while others fail. The response reports **both** outcomes:

```json
{
  "data": [
    { "id": "consent-jane-doe-001", "message": "Successfully Deleted" }
  ],
  "errors": [
    {
      "id": "0000000000000000000000a1",
      "code": 404,
      "message": "StandardEntity not found for entityId: 'consent-jane-doe-002'. Verify the standardEntity exists and you have access permissions."
    }
  ]
}
```

**Always inspect both `data` and `errors` after a multi-record delete.** The HTTP status alone does not tell you whether every record was removed.

## Field reference

### Field object

| Field | Type | Description |
|  --- | --- | --- |
| `id` | string | Id of the field |
| `apiName` | string | API name for the field |
| `name` | string | Name of the field |
| `description` | string | Description of the field |
| `type` | string | Type of the field |
| `entityDefinitionId` | string | Id of the definition this field is a part of |
| `lookupType` | string | For a `LOOKUP` field, which entity is the reference for lookup |
| `parentChild` | boolean | For a `LOOKUP` field with a parent-child relationship, whether the entity holding the referenced value is deleted when the referenced entity is deleted |
| `form` | object | For a `FORM` field, its definition |
| `multivalued` | boolean | Whether the field holds multiple values |
| `mandatory` | boolean | Whether the field is mandatory |
| `controllingField` | string | The id of the field controlling this field's values, if any |
| `picklistValues` | array | Picklist values defined for the field, if any |
| `defaultValue` | any | Default value for the field, if any |
| `additional` | object | Additional information based on the field's type |
| `langVsTranslatedFieldValues` | object | Translated field values, keyed by language code |


Check `mandatory` before writing records — a mandatory field must be present in every record write for that definition.

### Record object

| Field | Type | Description |
|  --- | --- | --- |
| `id` | string | Platform identifier for the record |
| `entityId` | string | Entity identifier. Settable at create time |
| `type` | string | The definition id |
| `baseType` | string | The base definition id, for extended entities |
| `name` | string | Record name |
| `image` | string | Image associated with the record |
| `detail` | string | Record detail |
| `values` | object | Field values held on the record |
| `processedValues` | object | Processed field values |
| `tags` | array of string | Tags applied to the record |
| `archived` | boolean | Whether the record is archived |
| `entityPriority` | integer | Record priority |
| `createdBy` | integer (int64) | User who created the record |
| `canEdit` | boolean | Whether the caller can edit this record |
| `importId` | string | Import identifier, if the record arrived through an import |
| `langVsTranslatedFieldValues` | object | Translated field values, keyed by language code then field |
| `entityMetadata` | object | Record metadata |
| `shares` | object | Sharing configuration |
| `scorecard` | object | Scorecard associated with the record |


## Response format and status codes

All responses use the standard envelope:

```json
{
  "data": {},
  "errors": [],
  "metadata": {}
}
```

Each entry in `errors` has this shape:

| Field | Type | Description |
|  --- | --- | --- |
| `id` | string | 24-character hex ObjectId for the error occurrence |
| `code` | integer | The status code |
| `message` | string | A dotted error key or a descriptive message |


### Status codes

| Code | Meaning | Common causes |
|  --- | --- | --- |
| `200` | Success |  |
| `400` | Bad request | No identifier supplied, two identifiers supplied where one is allowed, `pageSize` above 100, negative `pageNumber`, primary key lookup on a type without primary keys |
| `401` | Unauthorized | Missing, expired, or mismatched credentials; wrong `{env}` in the URL |
| `403` | Forbidden | The API key owner lacks permission on the definition |
| `404` | Not found | The field or record does not exist, or is not visible to you |


The Standard Entity API returns detailed, specific error messages that name the offending parameter and state the constraint. Log them and show them to your users rather than replacing them with a generic message.

## Migrating from API 2.0

### What changed

API 2.0 carried every identifier in the **URL path**. API 3.0 moves every identifier into a **query parameter**, leaving stable, predictable resource paths. Field and payload names are unchanged.

There is also a spelling change that is easy to overlook: the path segment was **`standard-entity`** in API 2.0 and is **`standardEntity`** in API 3.0.

### Endpoint mapping

| Operation | API 2.0 | API 3.0 |
|  --- | --- | --- |
| Fetch definition | `GET /api/v2/standard-entity/definition/{entityDefinitionId}` | `GET /api/v3/standardEntity/definition?entityType=` |
| Create field | `POST /api/v2/standard-entity/field/{entityDefinitionId}` | `POST /api/v3/standardEntity/field` |
| Fetch fields | `GET /api/v2/standard-entity/field/...` | `GET /api/v3/standardEntity/field?entityDefinitionId=` |
| Fetch field by API name | `GET /api/v2/standard-entity/field/...` | `GET /api/v3/standardEntity/field?fieldName=&entityDefinitionId=` |
| Update field | `PUT /api/v2/standard-entity/field/...` | `PUT /api/v3/standardEntity/field?fieldName=&entityDefinitionId=` |
| Create record | `POST /api/v2/standard-entity/entity/...` | `POST /api/v3/standardEntity/record` |
| Fetch record by entity id | `GET /api/v2/standard-entity/entity/...` | `GET /api/v3/standardEntity/record?entityType=&entityId=` |
| Fetch record by primary key | `GET /api/v2/standard-entity/entity/...` | `GET /api/v3/standardEntity/record?entityType=&primaryKey=` |
| Fetch record by primary key prefix | `GET /api/v2/standard-entity/entity/...` | `GET /api/v3/standardEntity/record?entityType=&primaryKeyPrefix=` |
| Update record | `PUT /api/v2/standard-entity/entity/{entityDefinitionId}/{entityId}` | `PUT /api/v3/standardEntity/record?entityType=&entityId=` |
| Partial update | `PUT /api/v2/standard-entity/entity/...` | `PATCH /api/v3/standardEntity/record?entityType=&entityId=` |
| Delete record | `DELETE /api/v2/standard-entity/entity/...` | `DELETE /api/v3/standardEntity/record?entityType=&entityId=` |
| Upsert by entity id | `POST /api/v2/standard-entity/entity/upsert/{entityDefinitionId}/{entityId}` | `POST /api/v3/standardEntity/record/upsert` |
| Upsert by primary key | `POST /api/v2/standard-entity/entity/upsert/...` | `POST /api/v3/standardEntity/record/upsert` |


**Fourteen API 2.0 endpoints become eleven API 3.0 operations.** Two consolidations do the work:

- The three record fetches — by entity id, by primary key, by primary key prefix — become **one** `GET /standardEntity/record` distinguished by which query parameter you send.
- The two upserts — by entity id and by primary key — become **one** `POST /standardEntity/record/upsert`.


## Common Use Cases

### Discover the schema before you write anything

```bash
curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/field?entityDefinitionId=_s_Consent&pageNumber=0&pageSize=100' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}'
```

Look at `mandatory` and `type` on every field returned. Those two properties tell you exactly what a valid record payload must contain.

### Add a custom field to an existing definition

```bash
curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/standardEntity/field' \
  -H 'Authorization: Bearer {{accessToken}}' \
  -H 'Key: {{apiKey}}' \
  -H 'Content-Type: application/json' \
  -d '{
    "apiName": "_c_LoyaltyTier",
    "name": "Loyalty Tier",
    "type": "TEXT",
    "entityDefinitionId": "_s_Consent"
  }'
```

### Keep an external system in sync

Use `POST /standardEntity/record/upsert` with an `entityId` derived from your own system's primary key. Every sync run then becomes idempotent — no existence check, no branch between create and update.

### Update one field without touching the rest

Use `PATCH` with a single entry in `updateFields`. This is safer than `PUT`, which replaces the whole record.

### Page through a large result set

Start at `pageNumber=0`, request `pageSize=100`, and stop when a page returns fewer than 100 results.

## Best practices

- **Set your own `entityId` at create time.** Derive it from your source system's key. Every later lookup, update, upsert, and delete becomes trivial, and your integration stops needing a local id mapping table.
- **Read the field list before you write records.** The `mandatory` flag is the authoritative list of what a payload must contain — do not hard-code it.
- **Prefer `PATCH` to `PUT`.** It avoids clearing fields you forgot to include and avoids the primary-field matching trap.
- **Prefer `upsert` for synchronisation jobs.** It removes an entire round trip and a race condition.
- **Never change a primary field on an update.** It will not update the record.
- **Give every integration its own API key.** Sharing a key across services means refreshing one token silently breaks the others.
- **Cache the definition and field list.** They change rarely. Re-reading them on every record write is wasted latency.
- **Store the field `id` returned at create time.** Referencing a field by `id` avoids having to send `entityDefinitionId` alongside `fieldName` on every call.
- **Check `data` and `errors` on every multi-id call.** Partial success is a normal outcome, not an edge case.
- **Batch conservatively.** Comma-separated id lists are supported, but keep them to a reasonable size so that a partial failure is easy to interpret and retry.


## Troubleshooting

| Message or symptom | Cause | Fix |
|  --- | --- | --- |
| `Valid query params must be provided for standardEntityField retrieval. Provide one from: 'fieldName' or 'id' along with any additional required param as per documentation.` | No field identifier was sent | Send either `fieldName` (with `entityDefinitionId`) or the field id |
| `Only one of 'fieldName' or 'id' can be provided for StandardEntityField retrieval. Provided: 'fieldName' and 'id'. Choose the appropriate identifier.` | Both identifiers were sent | Send exactly one |
| `Valid query params must be provided for standardEntity retrieval. Provide one from: 'recordId' or 'entityId' or 'primaryKey' along with any additional required param as per documentation.` | No record identifier was sent | Send one of `recordId`, `entityId`, or `primaryKey`, together with `entityType` |
| `Invalid 'pageSize' parameter. Must be a positive integer not exceeding 100.` | Page size above 100, or zero or negative | Use a value from 1 to 100 |
| `Invalid 'pageNumber' parameter. Must be a non-negative integer (page number begins with 0).` | Page number is negative, or your client starts paging at 1 | Start at 0 |
| `Entity type _s_SurveyResponseTranslation does not have primary key columns defined` | Primary key lookup attempted on a type with no primary keys | Look the record up by `entityId` or `recordId` instead |
| `StandardEntityField not found for fieldName: '...'. Verify the standardEntityField exists and you have access permissions.` | The field does not exist on that definition, or you cannot see it | Check the `apiName` spelling and the `entityDefinitionId`; confirm the key owner's permissions |
| `StandardEntity not found for entityId: '...'. Verify the standardEntity exists and you have access permissions.` | The record does not exist, or you cannot see it | Confirm the `entityId` and `entityType`; confirm permissions |
| `401 Unauthorized` on every call | Missing `Key` header, expired token, or wrong `{env}` | Send both `Authorization` and `Key`; confirm the environment; regenerate the token if older than 30 days |
| `401` appearing intermittently across services | Two services share one API key, and each token refresh invalidates the other | Issue a separate API key per integration |
| An update returns success but the record is unchanged | A primary field value differs from the one used at create time, so no record matched | Keep `identityType`, `identityId`, and `channel` identical to the create call |
| A `PUT` cleared fields you did not intend to change | `PUT` replaces the whole record | Use `PATCH` with `updateFields` |
| A multi-record delete "succeeded" but records remain | Delete reports per-record outcomes | Read the `errors` array as well as `data` |