# Catalog API Endpoints for Tracking Plans


This guide provides a reference for the [Data Catalog API]({{< ref "api/data-catalog-api/" >}}) endpoints to:

- [Manage Tracking Plans](#manage-tracking-plans)
- [Manage Tracking Plan events](#manage-tracking-plan-events)
- [Manage Tracking Plan-source connections](#manage-tracking-plan-connections)

## Prerequisites

{{< customreadfile "/includes/catalog-api/prerequisites.md" >}}

## Manage Tracking Plans

This section covers the API endpoints for creating and managing your [Tracking Plans]({{< ref "data-governance/tracking-plans/" >}}).

### Create Tracking Plan

{{% api-method method="post" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans" %}}

**Request body**

{{< query-paramsList >}}
  {{< query-params keyname="name" valuename="Tracking Plan name.<br/><br/>Note that:<ul><li>The name must be between 3 and 65 characters and should start with a letter.</li><li>It must contain only letters, numbers, underscores, commas, spaces, dashes, and dots.</li></ul>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="description" valuename="Tracking Plan description. <br/><br/>Note that the description must be between 3 and 2000 characters and should start with a letter." keytype="Optional" datatype="String" >}}
{{< /query-paramsList >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
POST /v2/catalog/tracking-plans HTTP/1.1
Host: api.rudderstack.com
Content-Type: application/json
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 83

{
    "name": "Product Ordered Plan",
    "description": "Tracking Plan for users placing an order for the product."
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
    "name": "Product Ordered Plan",
    "description": "Tracking Plan for users placing an order for the product."
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "id": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
  "name": "Product Ordered Plan",
  "description": "Tracking Plan for users placing an order for the product.",
  "version": 1,
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "creationType": "Data catalog API",
  "createdAt": "2024-05-22T10:34:03.016Z",
  "updatedAt": "2024-05-22T10:34:03.016Z"
}
```

**Response codes**

| Code | Description |
| :----| :---|
| 200 | Tracking Plan is successfully created. RudderStack also returns an ID for the newly created Tracking Plan. | 
| 400 | Bad or invalid request. | 

### List all Tracking Plans

{{% api-method method="get" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans" %}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
GET /v2/catalog/tracking-plans HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "trackingPlans": [{
      "id": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
      "name": "Product Ordered Plan",
      "description": "Tracking Plan for users placing an order for the product.",
      "version": 1,
      "createdAt": "2024-05-22T13:07:18.617Z",
      "updatedAt": "2024-05-22T13:07:18.617Z",
      "creationType": "Data catalog API",
      "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e"
    },
    {
      "id": "tp_2rKxjFu6R1qot19aWhTW7W7Ojew",
      "name": "Order Completed Plan",
      "description": "Tracking Plan for users completing an order for the product.",
      "version": 4,
      "createdAt": "2024-01-30T15:41:14.446Z",
      "updatedAt": "2024-02-01T08:59:15.095Z",
      "creationType": "Event Audit API",
      "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e"
    }
  ]
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | List of all Tracking Plans in the associated workspace. | 

### Get Tracking Plan by ID

{{% api-method method="get" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Query parameters**

{{< query-params keyname="version" valuename="Tracking Plan version. Note that it must be a number." keytype="Optional" datatype="String" >}}
{{< query-params keyname="rebuildSchemas" valuename="When set to `true`, RudderStack returns the latest Tracking Plan data by rebuilding all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan will be rejected.<br /><br />When set to `false`, RudderStack returns cached data immediately, which may be slightly out of date. The data will eventually be refreshed in the background. This option provides faster response times and is recommended for read-heavy operations.<br /><br /><b>Default value</b>: `true`." keytype="Optional" datatype="Boolean" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
GET /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T?rebuildSchemas=false HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T?rebuildSchemas=false' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "id": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
  "name": "Product Ordered Plan",
  "description": "Tracking Plan for users placing an order for the product.",
  "version": 1,
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "creationType": "Data catalog API",
  "createdAt": "2024-05-22T13:07:18.617Z",
  "updatedAt": "2024-05-22T13:07:18.617Z"
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Tracking Plan retrieved successfully. |
| 404 | Tracking Plan not found for the specified ID. |

### Update Tracking Plan

{{% api-method method="put" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Request body**

To update the Tracking Plan, **at least one** of the following parameters is required:

{{< query-paramsList >}}
  {{< query-params keyname="name" valuename="Tracking Plan name.<br/><br/>Note that:<ul><li>The name must be between 3 and 65 characters and should start with a letter.</li><li>It must contain only letters, numbers, underscores, commas, spaces, dashes, and dots.</li></ul>" datatype="String" >}}
  {{< query-params keyname="description" valuename="Tracking Plan description. <br/><br/>Note that the description must be between 3 and 2000 characters and should start with a letter." datatype="String" >}}
{{< /query-paramsList >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
PUT /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 87

{
    "name": "New Product Ordered Plan",
    "description": "Updated Tracking Plan for users placing an order for the product."
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request PUT 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
    "name": "New Product Ordered Plan",
    "description": "Updated Tracking Plan for users placing an order for the product."
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "id": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
  "name": "New Product Ordered Plan",
  "description": "Updated Tracking Plan for users placing an order for the product.",
  "version": 2,
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "creationType": "Data catalog API",
  "createdAt": "2024-05-22T10:34:03.016Z",
  "updatedAt": "2024-05-22T10:36:49.252Z"
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Tracking Plan is updated successfully. |
| 400 | Bad or invalid request. |

### Delete Tracking Plan

{{< danger >}}
Deleted Tracking Plans cannot be recovered or restored.
{{< /danger >}}

{{% api-method method="delete" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
DELETE /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request DELETE 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "name": "New Product Ordered Plan",
  "version": 1,
  "description": "Updated Tracking Plan for users placing an order for the product.",
  "creationType": "Data catalog API",
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "createdBy": "2KDKycoVHAOLttVvzBiqw12O3Hr",
  "updatedBy": null,
  "createdAt": "2024-05-22T13:41:33.057Z",
  "updatedAt": "2024-05-22T13:41:33.057Z",
  "events": []
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Tracking Plan is deleted successfully. |
| 400 | Bad or invalid request. |

## Manage Tracking Plan events

This section covers the API endpoints for upserting and managing events in your Tracking Plans.

{{< info >}}
The Data Catalog API creates the events and properties in the data catalog only if they do not exist already.
{{< /info >}}

### Upsert event to Tracking Plan

{{< warning >}}
While upserting an event to a Tracking Plan, make sure the schema of the properties adheres to the [advanced rules]({{< ref "data-governance/data-catalog/properties.md#advanced-rules" >}}) set for those properties in the data catalog. Otherwise, RudderStack will **drop** the schema and give the below error:

"Property with name [${prop.name}] and type [${prop.type}] already exists with different advanced keywords."

If you get this error, you can update the existing catalog property by adding required advanced rules and try again.
{{< /warning >}}

#### Upsert event with rules

{{< danger >}}
This endpoint will be deprecated soon.
{{< /danger >}}

{{% api-method method="patch" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/events" %}}

{{< info >}}
The changes are queued for processing and typically reflect within a few minutes.
{{< /info >}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Query parameters**

{{< query-params keyname="rebuildSchemas" valuename="When set to `true`, RudderStack returns the latest Tracking Plan data by rebuilding all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan will be rejected.<br /><br />When set to `false`, RudderStack returns cached data immediately, which may be slightly out of date. The data will eventually be refreshed in the background. This option provides faster response times and is recommended for read-heavy operations.<br /><br /><b>Default value</b>: `true`." keytype="Optional" datatype="Boolean" >}}

**Request body**

{{< query-paramsList >}}
  {{< query-params keyname="name" valuename="Name of the event to be upserted.<br/><br/>Note that:<ul><li>The name must be between 3 and 65 characters and should start with a letter.</li><li>It must contain only letters, numbers, underscores, commas, spaces, dashes, and dots.</li><li>For non-`track` events, the name should be an empty string.</li></ul>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="description" valuename="Event description. <br/><br/>Note that the description must be between 3 and 2000 characters and should start with a letter." keytype="Optional" datatype="String" >}}
  {{< query-params keyname="eventType" valuename="Type of event to be upserted. <br /><br />Note that:<ul><li>Once set, the event type **cannot** be updated later.</li><li>Allowed event types are `track`, `identify`, `group`, `page`, and `screen`.</li></ul>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="categoryId" valuename="Category ID of the event. It should be a valid, non-empty string." keytype="Optional" datatype="String" >}}
  {{< query-params keyname="rules" valuename="[JSON schema](https://rudderstack.com/docs/api/data-catalog-api/json-schema/) against which RudderStack validates the event. The event rules **cannot** be empty. <br /><br />**Note**: The keywords defined for a property in the `rules` parameter are the same as the [advanced rules](https://www.rudderstack.com/docs/data-governance/data-catalog/#advanced-rules) defined for a property in the dashboard. " keytype="Required" datatype="Object" >}}
  {{< query-params keyname="identitySection" valuename="Section from which RudderStack extracts the event properties. See [Event structure for Tracking Plans](https://www.rudderstack.com/docs/data-governance/tracking-plans/view-edit-tracking-plans/#event-structure-for-tracking-plan-validation) for more information." keytype="Optional" datatype="String" >}}
{{< /query-paramsList >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
PATCH /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events?rebuildSchemas=false HTTP/1.1
Host: api.rudderstack.com
Content-Type: application/json
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 955

{
  "name": "Product Viewed",
  "eventType": "track",
  "description": "User viewed a product.",
  "categoryId": null,
  "rules": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "properties": {
        "type": "object",
        "required": [
          "amount"
        ],
        "additionalProperties": false,
        "properties": {
          "amount": {
            "type": [
              "number"
            ]
          },
        }
      }
    }
  }
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request PATCH 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events?rebuildSchemas=false' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
  "name": "Product Viewed",
  "eventType": "track",
  "description": "User viewed a product.",
  "categoryId": null,
  "rules": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "properties": {
        "type": "object",
        "required": [
          "amount"
        ],
        "additionalProperties": false,
        "properties": {
          "amount": {
            "type": [
              "number"
            ]
          },
        }
      }
    }
  }
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "id": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
  "name": "Product Viewed Plan",
  "version": 3,
  "description": "User viewed a product.",
  "creationType": "Data catalog API",
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "createdAt": "2024-05-22T10:34:03.016Z",
  "updatedAt": "2024-05-22T11:01:24.706Z"
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Event is upserted to the Tracking Plan successfully. The API gives the updated Tracking Plan information as a response. |
| 400 | Bad or invalid request. |

#### Upsert event with properties

This endpoint has the same functionality as [Upsert event with rules](#upsert-event-with-rules) except that this request operates on the event properties rather than rules.

{{% api-method method="post" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/events" %}}

{{< info >}}
The changes are queued for processing and typically reflect within a few minutes.
{{< /info >}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Query parameters**

{{< query-params keyname="rebuildSchemas" valuename="When set to `true`, RudderStack returns the latest Tracking Plan data by rebuilding all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan will be rejected.<br /><br />When set to `false`, RudderStack returns cached data immediately, which may be slightly out of date. The data will eventually be refreshed in the background. This option provides faster response times and is recommended for read-heavy operations.<br /><br /><b>Default value</b>: `true`." keytype="Optional" datatype="Boolean" >}}

**Request body**

{{< query-paramsList >}}
  {{< query-params keyname="name" valuename="Name of the event to be upserted.<br/><br/>Note that:<ul><li>The name must be between 3 and 65 characters and should start with a letter.</li><li>It must contain only letters, numbers, underscores, commas, spaces, dashes, and dots.</li><li>For non-`track` events, the name should be an empty string.</li></ul>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="description" valuename="Event description. <br/><br/>Note that the description must be between 3 and 2000 characters and should start with a letter." keytype="Optional" datatype="String" >}}
  {{< query-params keyname="eventType" valuename="Type of event to be upserted. <br /><br />Note that:<ul><li>Once set, the event type **cannot** be updated later.</li><li>Allowed event types are `track`, `identify`, `group`, `page`, and `screen`.</li></ul>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="categoryId" valuename="Category ID of the event. It should be a valid, non-empty string." keytype="Optional" datatype="String" >}}
  {{< query-params keyname="properties" valuename="The event properties against which RudderStack validates the event. It **cannot** be empty.<br /><br />See **Properties structure** section below for more information on this parameter." keytype="Required" datatype="Array" >}}
  {{< query-params keyname="identitySection" valuename="Section from which RudderStack extracts the event properties. See [Event structure for Tracking Plans](https://www.rudderstack.com/docs/data-governance/tracking-plans/view-edit-tracking-plans/#event-structure-for-tracking-plan-validation) for more information." keytype="Optional" datatype="String" >}}
{{< /query-paramsList >}}

**Properties structure**

{{< query-paramsList >}}
  {{< query-params keyname="name" valuename="Property name. <br/><br/>Note that:<ul><li>The name must be of at least one character and should start with a letter.</li><li>It must contain only letters, numbers, underscores, and spaces.</li></ul>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="description" valuename="Property description. <br/><br/>Note that the description must be between 3 and 2000 characters and should start with a letter." keytype="Optional" datatype="String" >}}
  {{< query-params keyname="type" valuename="Data type of the property. <br /><br />Note that:<ul><li>The data type must be either string, integer, number, object, array, boolean, null, or multi data type.<li>If not explicitly set, RudderStack allows all the above data types for the property, by default.</li>" keytype="Required" datatype="String" >}}
  {{< query-params keyname="propConfig" valuename="Advanced rules for the property. See [JSON Schema](https://www.rudderstack.com/docs/api/data-catalog-api/json-schema/) for the complete list of supported keywords." keytype="Required" datatype="Object" >}}
  {{< query-params keyname="required" valuename="Determines whether the property must be present in the event." keytype="Optional" datatype="Boolean" >}}
  {{< query-params keyname="additionalProperties" valuename="This parameter is only applicable for arrays and objects if nested properties are present. It determines if additional properties (apart from the provided nested properties) should be allowed." keytype="Optional" datatype="Boolean" >}}
  {{< query-params keyname="metadata" valuename="Additional [metadata](https://rudderstack.com/docs/api/data-catalog-api/json-schema/#metadata) for the property containing generic keywords." keytype="Optional" datatype="Object" >}}
  {{< query-params keyname="properties" valuename="Details of the nested properties." keytype="Required only for nested properties" datatype="Array" >}}

{{< /query-paramsList >}}


**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
POST /v2/catalog/tracking-plans/tp_2u9kdo9I3y0ou8O722ZTc8SOgMk/events?rebuildSchemas=false HTTP/1.1
Host: api.rudderstack.com
Content-Type: application/json
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 955
{
    "description": "Triggered when user views a product.",
    "eventType": "track",
    "name": "Product Viewed",
    "properties": [
        {
            "name": "product_details",
            "description": "Product details",
            "type": "object",
            "propConfig": {},
            "required": false,
            "additionalProperties": true,
            "metadata": {},
            "properties": [
                {
                    "name": "id",
                    "description": "Product ID",
                    "type": "string",
                    "propConfig": {
                        "minLength": 1
                    },
                    "required": true,
                    "additionalProperties": true,
                    "metadata": {}
                }
            ]
        },
        {
            "name": "amount",
            "description": "Product amount",
            "type": "number, string",
            "propConfig": {},
            "required": true,
            "additionalProperties": true,
            "metadata": {},
            "properties": []
        }
    ]
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request POST 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_2u9kdo9I3y0ou8O722ZTc8SOgMk/events?rebuildSchemas=false' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
    "description": "Triggered when user views a product.",
    "eventType": "track",
    "name": "Product Viewed",
    "properties": [
        {
            "name": "product_details",
            "description": "Product details",
            "type": "object",
            "propConfig": {},
            "required": false,
            "additionalProperties": true,
            "metadata": {},
            "properties": [
                {
                    "name": "id",
                    "description": "Product ID",
                    "type": "string",
                    "propConfig": {
                        "minLength": 1
                    },
                    "required": true,
                    "additionalProperties": true,
                    "metadata": {}
                }
            ]
        },
        {
            "name": "amount",
            "description": "Product amount",
            "type": "number, string",
            "propConfig": {},
            "required": true,
            "additionalProperties": true,
            "metadata": {},
            "properties": []
        }
    ]
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "id": "tp_2u9kdo9I3y0ou8O722ZTc8SOgMk",
  "name": "Product Viewed Plan",
  "version": 3,
  "description": "User viewed a product.",
  "creationType": "Data catalog API",
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "createdAt": "2024-05-22T10:34:03.016Z",
  "updatedAt": "2024-05-22T11:01:24.706Z"
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Event is upserted to the Tracking Plan successfully. The API gives the updated Tracking Plan information as a response. |
| 400 | Bad or invalid request. |

#### Upsert event with identifiers

This endpoint has the same functionality as [Upsert event with properties](#upsert-event-with-properties) except that this request only requires the identifiers (Tracking Plan ID, event ID, and property IDs).

{{% api-method method="put" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/events" %}}

{{< info >}}
The changes are queued for processing and typically reflect within a few minutes.
{{< /info >}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Query parameters**

{{< query-params keyname="rebuildSchemas" valuename="When set to `true`, RudderStack returns the latest Tracking Plan data by rebuilding all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan will be rejected.<br /><br />When set to `false`, RudderStack returns cached data immediately, which may be slightly out of date. The data will eventually be refreshed in the background. This option provides faster response times and is recommended for read-heavy operations.<br /><br /><b>Default value</b>: `true`." keytype="Optional" datatype="Boolean" >}}

**Request body**

{{< query-paramsList >}}
  {{< query-params keyname="id" valuename="Event ID. <br /><br />RudderStack automatically fetches the event name, description, type, and other event details from this ID." keytype="Required" datatype="String" >}}
  {{< query-params keyname="properties" valuename="The event properties against which RudderStack validates the event. It **cannot** be empty.<br /><br />See **Properties structure** section below for more information on this parameter." keytype="Required" datatype="Array" >}}
{{< /query-paramsList >}}

**Properties structure**

{{< query-paramsList >}}
  {{< query-params keyname="id" valuename="Property ID. <br/><br/>RudderStack automatically fetches the property name, description, type, and other details from this ID." keytype="Required" datatype="String" >}}
  {{< query-params keyname="required" valuename="Determines whether the property must be present in the event." keytype="Optional" datatype="Boolean" >}}
  {{< query-params keyname="additionalProperties" valuename="This parameter is only applicable for arrays and objects if nested properties are present. It determines if additional properties (apart from the provided nested properties) should be allowed." keytype="Optional" datatype="Boolean" >}}
  {{< query-params keyname="metadata" valuename="Additional [metadata](https://rudderstack.com/docs/api/data-catalog-api/json-schema/#metadata) for the property containing generic keywords." keytype="Optional" datatype="Object" >}}
  {{< query-params keyname="properties" valuename="Details of the nested properties." keytype="Required only for nested properties" datatype="Array" >}}
{{< /query-paramsList >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
PUT /v2/catalog/tracking-plans/tp_2u9kdo9I3y0ou8O722ZTc8SOgMk/events?rebuildSchemas=false HTTP/1.1
Host: api.rudderstack.com
Content-Type: application/json
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 955

{
    "id": "ev_2govsgWGzvmkZqiHESDpdHqkbsI", 
    "properties": [
        {
            "id": "prop_2bc0rhFC4oOKa8VCfAhMCkN31rf",
            "required": true,
            "additionalProperties": true,
            "metadata": {},
            "properties": [
                {
                    "id": "prop_2rQucgLjgHWYQQIst2iu5yIjWKh",
                    "required": true,
                    "additionalProperties": true,
                    "metadata": {}
                }
            ]
        },
        {
            "id": "prop_2bdWBUck8T5kqMoWnwTyn4h5reo",
            "required": false,
            "additionalProperties": false,
            "metadata": {},
            "properties": []
        }
    ]
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request PUT 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_2u9kdo9I3y0ou8O722ZTc8SOgMk/events?rebuildSchemas=false' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
    "id": "ev_2govsgWGzvmkZqiHESDpdHqkbsI", 
    "properties": [
        {
            "id": "prop_2bc0rhFC4oOKa8VCfAhMCkN31rf",
            "required": true,
            "additionalProperties": true,
            "metadata": {},
            "properties": [
                {
                    "id": "prop_2rQucgLjgHWYQQIst2iu5yIjWKh",
                    "required": true,
                    "additionalProperties": true,
                    "metadata": {}
                }
            ]
        },
        {
            "id": "prop_2bdWBUck8T5kqMoWnwTyn4h5reo",
            "required": false,
            "additionalProperties": false,
            "metadata": {},
            "properties": []
        }
    ]
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "id": "tp_2u9kdo9I3y0ou8O722ZTc8SOgMk",
  "name": "Product Viewed Plan",
  "version": 3,
  "description": "User viewed a product.",
  "creationType": "Data catalog API",
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "createdAt": "2024-05-22T10:34:03.016Z",
  "updatedAt": "2024-05-22T11:01:24.706Z"
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Event is upserted to the Tracking Plan successfully. The API gives the updated Tracking Plan information as a response. |
| 400 | Bad or invalid request. |

#### Property keyword validations

While upserting event with properties to a Tracking Plan, the API validates the data types for the various keywords defined in the `propConfig` and [`metadata`]({{< ref "api/data-catalog-api/json-schema.md#metadata" >}}) parameters, and gives an error if you pass an invalid value.

See this [FAQ](#supported-type-specific-keywords) for more information on the type-specific keywords supported by RudderStack.

For example, if you pass the `propConfig` and `metadata` objects as follows:

```json
{
  "type": "string",
  ...

  "metadata": {
    "title": 45   // Number instead of a string
  },

  "propConfig": {
    "maxLength": "4",   // String instead of a number.
  }
}
```

Then, you will get the below errors:

```json
{
  "error": "max length must be an integer, title must be a string"
}

{
  "error": "schema is invalid: data/properties/properties/properties/<property_name>/title must be string"
}
```

### List all events in Tracking Plan

{{% api-method method="get" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/events" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Query parameters**

{{< query-params keyname="rebuildSchemas" valuename="When set to `true`, RudderStack returns the latest Tracking Plan data by rebuilding all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan will be rejected.<br /><br />When set to `false`, RudderStack returns cached data immediately, which may be slightly out of date. The data will eventually be refreshed in the background. This option provides faster response times and is recommended for read-heavy operations.<br /><br /><b>Default value</b>: `true`." keytype="Optional" datatype="Boolean" >}}
{{< query-params keyname="page" valuename="In a paginated view, all the response entries are divided into pages. Use this field to specify which page of results to return. Default value is **1**. <br /><br />**Note**: <br /><br /><ul><li>This parameter must be a positive integer.</li><li>The API returns a maximum of 50 pages.</li><ul>" keytype="Optional" datatype="Number" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
GET /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events?rebuildSchemas=false HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events?rebuildSchemas=false' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "data": [{
    "id": "ev_2gotMKGuOtdDY4XbSdKjkwk4qc2",
    "name": "Product Viewed",
    "description": "User viewed a product.",
    "eventType": "track",
    "categoryId": null,
    "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
    "createdBy": "2KDKycoVHAOLttVvzBiqw12O3Hr",
    "updatedBy": null,
    "createdAt": "2024-05-22T11:01:24.706Z",
    "updatedAt": "2024-05-22T11:01:24.706Z",
    "identitySection": "properties",
    "additionalProperties": true,
  }],
  "total": 1,
  "currentPage": 1,
  "pageSize": 50
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | All the events in the Tracking Plan are fetched successfully. |

The response body contains the below fields:

| Field | Type | Description |
| :---| :----| :----|
| `data` | Array | Contains all the events in the Tracking Plan. | 
| `total` | Number | Total number of entries in the response. |
| `currentPage` | Number | Current page number being viewed (starts from 1). |
| `pageSize` | Number | Maximum number of items displayed per page. |

### Get Tracking Plan event by ID

{{% api-method method="get" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/events/{eventId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}
{{< query-params keyname="eventId" valuename="Event ID." keytype="Required" datatype="String" >}}

**Query parameters**

{{< query-params keyname="format" valuename="Fetches the response in the specified format. Acceptable values are:<br /><br /><ul><li> `schema`: Response is shown with the `rules` object. This is the default `format` value.</li><li>`properties`: Response is shown with the `properties` object.</li></ul>" keytype="Optional" datatype="String" >}}
{{< query-params keyname="rebuildSchemas" valuename="When set to `true`, RudderStack returns the latest Tracking Plan data by rebuilding all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan will be rejected.<br /><br />When set to `false`, RudderStack returns cached data immediately, which may be slightly out of date. The data will eventually be refreshed in the background. This option provides faster response times and is recommended for read-heavy operations.<br /><br /><b>Default value</b>: `true`." keytype="Optional" datatype="Boolean" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
GET /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events/ev_2gotMKGuOtdDY4XbSdKjkwk4qc2?rebuildSchemas=false HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events/ev_2gotMKGuOtdDY4XbSdKjkwk4qc2?rebuildSchemas=false' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

{{< tabs tabTotal="2" >}}
{{% tab tabName="Schema format" %}}

The response when you add `format=schema` as the query parameter is shown:

```json
{
  "id": "ev_2gotMKGuOtdDY4XbSdKjkwk4qc2",
  "name": "Product Viewed",
  "description": "User viewed a product.",
  "eventType": "track",
  "categoryId": null,
  "workspaceId": "1hitizAoFT91DD6rfFhBjiTex3e",
  "createdBy": "2KDKycoVHAOLttVvzBiqw12O3Hr",
  "updatedBy": null,
  "createdAt": "2024-05-22T11:01:24.706Z",
  "updatedAt": "2024-05-22T11:01:24.706Z",
  "identitySection": "properties",
  "rules": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "properties": {
        "type": "object",
        "required": [
          "amount"
        ],
        "additionalProperties": false,
        "properties": {
          "amount": {
            "type": [
              "number"
            ]
          },
        }
      }
    }
  }
}
```
{{% /tab %}}
{{% tab tabName="Properties format" %}}

The response when you add `format=properties` as the query parameter is shown:

```json
{
  "id": "ev_2gotMKGuOtdDY4XbSdKjkwk4qc2",
  "name": "Product Viewed",
  "description": "User viewed a product.",
  "eventType": "track",
  "categoryId": null,
  "workspaceId": "1zitShAoFT91DD6rfFhBjiTex3e",
  "createdBy": "2KDKycoVHAOLttVvzBiqw12O3Hr",
  "updatedBy": "2KDKycoVHAOLttVvzBiqw12O3Hr",
  "createdAt": "2024-05-22T11:22:32.710Z",
  "updatedAt": "2025-03-11T04:44:43.633Z",
  "identitySection": "properties",
  "additionalProperties": false,
  "properties": [{
    "id": "prop_2bc0rhFC4oOKa8VCfAhMCkN31rf",
    "name": "amount",
    "description": "Product amount",
    "type": "number, string",
    "propConfig": {},
    "required": true,
    "additionalProperties": false,
    "metadata": {},
    "properties": []
  }]
}
```
{{% /tab %}}
{{< /tabs >}}

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Event specified by the ID is fetched successfully. |
| 404 | Tracking Plan event not found for the specified ID. |

### Delete event from Tracking Plan

{{% api-method method="delete" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/events/{eventId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}
{{< query-params keyname="eventId" valuename="Event ID." keytype="Required" datatype="String" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
DELETE /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events/ev_2gotMKGuOtdDY4XbSdKjkwk4qc2 HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request DELETE 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/events/ev_2gotMKGuOtdDY4XbSdKjkwk4qc2' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Response codes**

| Code | Description |
| :----|  :---|
| 204 | Event is deleted from Tracking Plan successfully. |
| 400 | Bad or invalid request. |

## Manage Tracking Plan connections

This section covers the API endpoints for managing the connections between your Tracking Plans and sources.

### Add new connection

{{% api-method method="post" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/sources/{sourceId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}
{{< query-params keyname="sourceId" valuename="Source ID." keytype="Required" datatype="String" >}}

**Request body**

{{< warning >}}
The request body must not be empty. Otherwise, you will encounter an error.
{{< /warning >}}

{{< query-paramsList >}}
  {{< query-params keyname="config" valuename="Tracking Plan configuration for the source. See <b>Config object structure</b> below for more information." keytype="Required" datatype="Object" >}}
{{< /query-paramsList >}}

**Config object structure**

The `config` object provided in the request body contains the source-specific Tracking Plan settings for validating the individual events. A sample object is shown below:

```json
{
  "config": {
    "page": {
      "unplannedProperties": "forward",  // or "drop"
      "anyOtherViolation": "forward",  // or "drop"
      "propagateValidationErrors": "true",  // or "false"
    },
    "group": {
      "unplannedProperties": "forward",
      "anyOtherViolation": "forward",
      "propagateValidationErrors": "true"
    },
    "track": {
      "allowUnplannedEvents": "true",
      "unplannedProperties": "forward",
      "anyOtherViolation": "forward",
      "propagateValidationErrors": "true",  // or "false"
    },
    "global": {
      "allowUnplannedEvents": "true",
      "unplannedProperties": "forward",
      "anyOtherViolation": "forward",
      "propagateValidationErrors": "true"
    },
    "screen": {
      "unplannedProperties": "forward",
      "anyOtherViolation": "forward",
      "propagateValidationErrors": "true"
    },
    "identify": {
      "unplannedProperties": "forward",
      "anyOtherViolation": "forward",
      "propagateValidationErrors": "true"
    }
  }
}
```

The event-level settings that you can define within the `config` object are described below. See [Source-specific Tracking Plan settings]({{< ref "data-governance/tracking-plans/view-edit-tracking-plans.md#source-specific-settings" >}}) for more information:

| Field | <div style="width:300px">Description</div> |
| :----| :-----|
| `allowUnplannedEvents` | **Applicable for `track` object only.** <br /><br /> Boolean that determines if RudderStack should drop all events that do not match the predefined event names in the Tracking Plan. |
| `unplannedProperties` | Acceptable values are `forward` and `drop`. <br /><br />Determines if RudderStack should forward or drop events that contain properties not matching the list of predefined properties for the specific event. |
| `anyOtherViolation` | Acceptable values are `forward` and `drop`. <br /><br />Determines if RudderStack should forward or drop events with any other violations that include **Type Mismatch**, **Required Fields Missing**, and others outlined in the [Violation types]({{< ref "data-governance/tracking-plans/violation-management.md#violation-types" >}}) section. |
| `propagateValidationErrors` | Boolean that determines if RudderStack should capture the validation errors in the event’s `context` object and send them downstream (user transformations and destinations).  |

{{< info >}}
Note that:

- You need not provide the Tracking Plan settings for all events. For example, you can include only the `track` and `global` objects within `config`. However, note that you **must not** provide a blank event object. If included, you must define at least one setting for that event.
- RudderStack uses the default settings for the events that you do not specify explicitly and validates them accordingly.
{{< /info >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
POST /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources/2nk0qVvmxE79uIwsKebgVH4iNTR HTTP/1.1
Host: api.rudderstack.com
Content-Type: application/json
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 1125

{
  "config": {
    "page": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "group": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "track": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "true",
      "propagateValidationErrors": "true"
    },
    "global": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "false",
      "propagateValidationErrors": "true"
    },
    "screen": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "identify": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    }
  }
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources/2nk0qVvmxE79uIwsKebgVH4iNTR' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
    "config": {
        "page": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        },
        "group": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        },
        "track": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "allowUnplannedEvents": "true",
            "propagateValidationErrors": "true"
        },
        "global": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "allowUnplannedEvents": "false",
            "propagateValidationErrors": "true"
        },
        "screen": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        },
        "identify": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        }
    }
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "sourceId": "2nk0qVvmxE79uIwsKebgVH4iNTR",
  "trackingPlanId": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
  "config": {
    "page": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "group": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "track": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "true",
      "propagateValidationErrors": "true"
    },
    "global": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "false",
      "propagateValidationErrors": "true"
    },
    "screen": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "identify": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    }
  }
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Connection created successfully. |
| 400 | <ul><li>Invalid Request</li><li>Empty or incorrect `config` object.</li><li>Source already connected to Tracking Plan.</li></ul> |

### Update Tracking Plan configuration

{{% api-method method="put" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/sources/{sourceId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}
{{< query-params keyname="sourceId" valuename="Source ID." keytype="Required" datatype="String" >}}

**Request body**

{{< warning >}}
The request body must not be empty. Otherwise, you will encounter an error.
{{< /warning >}}

{{< query-paramsList >}}
  {{< query-params keyname="config" valuename="Tracking Plan configuration for the source. See <b>Config object structure</b> below for more information." keytype="Required" datatype="Object" >}}
{{< /query-paramsList >}}

**Config object structure**

The `config` object provided in the request body contains the source-specific Tracking Plan settings for validating the individual events. A sample object is shown below:

```json
{
  "config": {
    "page": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "group": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "track": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "true",
      "propagateValidationErrors": "true"
    },
    "global": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "false",
      "propagateValidationErrors": "true"
    },
    "screen": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "identify": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    }
  }
}
```

The event-level settings that you can define within the `config` object are described below. See [Source-specific Tracking Plan settings]({{< ref "data-governance/tracking-plans/view-edit-tracking-plans.md#source-specific-settings" >}}) for more information:

| Field | <div style="width:300px">Description</div> |
| :----| :-----|
| `allowUnplannedEvents` | **Applicable for `track` object only.** <br /><br /> Boolean that determines if RudderStack should drop all events that do not match the predefined event names in the Tracking Plan. |
| `unplannedProperties` | Acceptable values are `forward` and `drop`. <br /><br />Determines if RudderStack should forward or drop events that contain properties not matching the list of predefined properties for the specific event. |
| `anyOtherViolation` | Acceptable values are `forward` and `drop`. <br /><br />Determines if RudderStack should forward or drop events with any other violations that include **Type Mismatch**, **Required Fields Missing**, and others outlined in the [Violation types]({{< ref "data-governance/tracking-plans/violation-management.md#violation-types" >}}) section. |
| `propagateValidationErrors` | Boolean that determines if RudderStack should capture the validation errors in the event’s `context` object and send them downstream (user transformations and destinations).  |

{{< info >}}
Note that:

- You need not provide the Tracking Plan settings for all events. For example, you can include only the `track` and `global` objects within `config`. However, note that you **must not** provide a blank event object. If included, you must define at least one setting for that event.
- RudderStack uses the default settings for the events that you do not specify explicitly and validates them accordingly.
{{< /info >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
PUT /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources/2nk0qVvmxE79uIwsKebgVH4iNTR HTTP/1.1
Host: api.rudderstack.com
Content-Type: application/json
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
Content-Length: 1125

{
  "config": {
    "page": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "group": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "track": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "true",
      "propagateValidationErrors": "true"
    },
    "global": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "false",
      "propagateValidationErrors": "true"
    },
    "screen": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "identify": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    }
  }
}
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request PUT 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources/2nk0qVvmxE79uIwsKebgVH4iNTR' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>' \
--data '{
    "config": {
        "page": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        },
        "group": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        },
        "track": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "allowUnplannedEvents": "true",
            "propagateValidationErrors": "true"
        },
        "global": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "allowUnplannedEvents": "false",
            "propagateValidationErrors": "true"
        },
        "screen": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        },
        "identify": {
            "anyOtherViolation": "forward",
            "unplannedProperties": "forward",
            "propagateValidationErrors": "true"
        }
    }
}'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "config": {
    "page": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "group": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "track": {
      "anyOtherViolation": "drop",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "true",
      "propagateValidationErrors": "true"
    },
    "global": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "allowUnplannedEvents": "false",
      "propagateValidationErrors": "true"
    },
    "screen": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    },
    "identify": {
      "anyOtherViolation": "forward",
      "unplannedProperties": "forward",
      "propagateValidationErrors": "true"
    }
  }
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | Configuration updated successfully. |
| 400 | <ul><li>Invalid Request</li><li>Empty or incorrect `config` object.</li><li>Source is not connected to Tracking Plan.</li></ul> |

### List all sources connected to Tracking Plan

{{% api-method method="get" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/sources" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
GET /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Example response**

```json
{
  "connections": [{
      "sourceId": "2nk0qVvmxE79uIwsKebgVH4iNTR",
      "trackingPlanId": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
      "config": {
        "track": {
          "anyOtherViolation": "forward",
          "unplannedProperties": "forward",
          "allowUnplannedEvents": "true",
          "propagateValidationErrors": "true"
        },
        "global": {
          "anyOtherViolation": "forward",
          "unplannedProperties": "forward",
          "allowUnplannedEvents": "false",
          "propagateValidationErrors": "true"
        },
        "identify": {
          "anyOtherViolation": "forward",
          "unplannedProperties": "forward",
          "propagateValidationErrors": "true"
        }
      }
    },
    {
      "sourceId": "2rL1XeHCG8P8OrMHnHx4WjMjuTo",
      "trackingPlanId": "tp_5gopz6tfKxAjpS4TjuqVIeTdm7T",
      "config": {
        "track": {
          "anyOtherViolation": "drop",
          "unplannedProperties": "forward",
          "allowUnplannedEvents": "true",
          "propagateValidationErrors": "true"
        },
        "global": {
          "anyOtherViolation": "forward",
          "unplannedProperties": "forward",
          "allowUnplannedEvents": "false",
          "propagateValidationErrors": "true"
        }
      }
    }
  ]
}
```

**Response codes**

| Code | Description |
| :----|  :---|
| 200 | All the sources connected to a Tracking Plan fetched successfully. |

### Delete source connection

{{% api-method method="delete" host="https://api.rudderstack.com/v2" path="/catalog/tracking-plans/{trackingPlanId}/sources/{sourceId}" %}}

**Path parameters**

{{< query-params keyname="trackingPlanId" valuename="Tracking Plan ID." keytype="Required" datatype="String" >}}
{{< query-params keyname="sourceId" valuename="Source ID." keytype="Required" datatype="String" >}}

**Example request**

{{< tabs tabTotal="2" >}}
{{% tab tabName="HTTP" %}}
```http
DELETE /v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources/2nk0qVvmxE79uIwsKebgVH4iNTR HTTP/1.1
Host: api.rudderstack.com
Authorization: Bearer <SERVICE_ACCESS_TOKEN>
```
{{% /tab %}}
{{% tab tabName="CURL" %}}
```bash
curl --location --request DELETE 'https://api.rudderstack.com/v2/catalog/tracking-plans/tp_5gopz6tfKxAjpS4TjuqVIeTdm7T/sources/2nk0qVvmxE79uIwsKebgVH4iJNR' \
--header 'Authorization: Bearer <SERVICE_ACCESS_TOKEN>'
```
{{% /tab %}}
{{< /tabs >}}

**Response codes**

| Code | Description |
| :----|  :---|
| 204 | Source disconnected from Tracking Plan successfully. |
| 400 | <ul><li>Source already disconnected from Tracking Plan.</li><li>Invalid source ID.</li></ul>|

## Supported type-specific keywords {#supported-type-specific-keywords}

{{< tabs tabTotal="3" >}}
{{% tab tabName="String" %}}

RudderStack supports the following keywords for the string data type:

- `minLength`
- `maxLength`
- `pattern`
- `format`

See the [JSON Schema]({{< ref "api/data-catalog-api/json-schema.md#strings" >}}) guide for more information on these keywords.

{{% /tab %}}
{{% tab tabName="Integer and Number" %}}
RudderStack supports the following keywords for the integer and number data type:

- `multipleOf`
- `minimum`
- `maximum`
- `exclusiveMinimum`
- `exclusiveMaximum`

See the [JSON Schema]({{< ref "api/data-catalog-api/json-schema.md#integers-and-numbers" >}}) guide for more information on these keywords.

{{% /tab %}}
{{% tab tabName="Array" %}}
RudderStack supports the following keywords for the array data type:

- `minItems`
- `maxItems`
- `uniqueItems`

See the [JSON Schema]({{< ref "api/data-catalog-api/json-schema.md#arrays" >}}) guide for more information on these keywords.

{{% /tab %}}
{{< /tabs >}}

## FAQ

#### How do I handle concurrent update failures when working with the Tracking Plan endpoints?

When you use endpoints that support the `rebuildSchemas` query parameter with its default value (`true`), RudderStack rebuilds all schema rules before responding. During this operation, any concurrent updates to the Tracking Plan are rejected, which can cause your requests to fail.

If you encounter concurrent update failures, set the `rebuildSchemas` query parameter to `false`. This option:

- Returns cached data immediately, which may be slightly out of date
- Allows concurrent updates to proceed without rejection
- Provides faster response times

`rebuildSchemas=false` is recommended for read-heavy operations — the data will eventually be refreshed in the background, so you still get updated information eventually.

<br />
