HomeGuidesAPI Reference
ChangelogHelp CenterCommunityContact Us
API Reference

Custom Objects API overview

Before you begin

Check out our general API overview to make sure you’re ready to get started with specific endpoints.

Custom objects enable you to map diverse data concepts into Klaviyo with a many-to-one relationship, like multiple pets, product subscriptions, or active reservations. Use custom object data to:

  • Personalize templates for your flow and campaign sends (i.e., use object personalization tags to pull custom object data into your templates).
  • Create granular customer segments (e.g., a segment of profiles that have more than 3 pets, to target with rewards for bulk pet supplies).
  • Configure date-triggered flows based on an object's date properties (e.g., a pet's birthday).
  • Set conditional splits in flows (e.g., add a text block to an email with a sign-up form for birthday rewards if the data has not been provided).

When the status of an object changes and you want to trigger a message, use the Custom Object API to update the object with the new information. You must include the complete object and an event to trigger a flow in each payload. Events are intended to trigger flows quickly, allowing you to send timely and relevant messaging.

Set up custom objects in your Klaviyo account

To get started with custom objects, you can use either the UI-based approach or the programmatic API approach (Beta).

Option 1: UI-based setup

  1. Navigate to the Object Manager to create a new data source and object.

  2. Give your object a unique name and either select an existing data source or create a new one.

  3. Define the object's schema and relationships using the Object Manager. For more information about defining an object, check out Getting started with custom objects.

  4. Use the provided sample payload to begin ingesting records from your source of data with the Bulk Create Data Source Records endpoint.

Option 2: Programmatic setup (Beta)

🚧

The Custom Objects Definition APIs are currently in Beta, releasing 2026-01-15. These APIs allow you to programmatically manage object types, schemas, and source mappings.

Instead of using the Object Manager UI, you can programmatically define and manage custom objects using the Beta Custom Objects Definition APIs. For a complete list of available endpoints, see the changelog.

With the programmatic approach, you still need to:

  1. Create a data source with the Create Data Source endpoint.

  2. Ingest some records from your source of data with the Bulk Create Data Source Records endpoint.

  3. Use the Beta Custom Objects Definition APIs to programmatically create object types, define schemas, and configure source mappings instead of using the Object Manager UI.

The following examples show how to programmatically create a Reservation custom object:

Step 1: Create an Object Type

Create an object type using the Create Object Type endpoint. This automatically creates a draft schema and source mapping:

{
    "data": {
        "type": "object-type",
        "attributes": {
            "title": "Reservation",
            "description": "Customer reservation information"
        }
    }
}

Step 2: Update the Object Schema

Update the draft schema with the properties you want to store using the Update Object Schema endpoint:

{
    "data": {
        "id": "<DRAFT_SCHEMA_ID_INCLUDED_IN_ABOVE_RESPONSE>",
        "type": "object-schema",
        "attributes": {
            "title": "Reservation",
            "properties": [
                {
                    "id": "1",
                    "name": "reservation_id",
                    "type": "STRING",
                    "description": "Unique reservation identifier"
                },
                {
                    "id": "2",
                    "name": "created_at",
                    "type": "TIMESTAMP",
                    "description": "Reservation creation date"
                },
                {
                    "id": "3",
                    "name": "guest_count",
                    "type": "INT",
                    "description": "Number of guests"
                },
                {
                    "id": "4",
                    "name": "late_cancellation_fee",
                    "type": "FLOAT",
                    "description": "Fee for late cancellation"
                },
                {
                    "id": "5",
                    "name": "is_active",
                    "type": "BOOLEAN",
                    "description": "Whether the reservation is active"
                }
            ],
            "required": ["reservation_id"]
        }
    }
}

Step 3: Update the Source Mapping

Configure how data source fields map to schema properties using the Update Source Mapping endpoint:

{
    "data": {
        "type": "source-mapping",
        "id": "<SOURCE_MAPPING_ID>",
        "attributes": {
            "property_mappings": [
                {
                    "id": "1",
                    "type": "simple",
                    "source": {
                        "source_id": "<DATA_SOURCE_ID>",
                        "id_path": "$['reservation_id']",
                        "data_path": "$['reservation_id']"
                    }
                },
                {
                    "id": "2",
                    "type": "simple",
                    "source": {
                        "source_id": "<DATA_SOURCE_ID>",
                        "id_path": "$['reservation_id']",
                        "data_path": "$['created_at']"
                    }
                },
                {
                    "id": "3",
                    "type": "simple",
                    "source": {
                        "source_id": "<DATA_SOURCE_ID>",
                        "id_path": "$['reservation_id']",
                        "data_path": "$['guest_count']"
                    }
                },
                {
                    "id": "4",
                    "type": "simple",
                    "source": {
                        "source_id": "<DATA_SOURCE_ID>",
                        "id_path": "$['reservation_id']",
                        "data_path": "$['late_cancellation_fee']"
                    }
                },
                {
                    "id": "5",
                    "type": "simple",
                    "source": {
                        "source_id": "<DATA_SOURCE_ID>",
                        "id_path": "$['reservation_id']",
                        "data_path": "$['is_active']"
                    }
                }
            ],
            "relationship_mappings": [
                {
                    "id": "profile-relationship",
                    "type": "simple",
                    "source": {
                        "source_id": "<DATA_SOURCE_ID>",
                        "id_path": "$['reservation_id']",
                        "update_strategy": "replace",
                        "type": "profile",
                        "related_id_paths": {
                            "email": "$['email']"
                        }
                    }
                }
            ]
        }
    }
}

Step 4: Activate the Schema

Once your schema and source mapping are configured, activate the schema by updating its status to active:

{
    "data": {
        "type": "object-schema",
        "id": "<DRAFT_SCHEMA_ID>",
        "attributes": {
            "status": "active"
        }
    }
}

🚧

Custom objects is a paid feature in Klaviyo, only available to customers with a paid email plan. To request access to custom objects, submit this form.

Use cases

The Custom Objects API supports a number of use cases, including:

  • Create data sources to ingest data records that will be used to create custom objects.
  • Create a data source record job to ingest data records from your data source.
  • Return all available data sources for an account.
  • Delete data sources in your account.
  • Programmatically manage object types, schemas, and source mappings using the Beta Custom Objects Definition APIs (releasing 2026-01-15).

For a quick start, download this Postman collection.

📘

If you have feedback or encounter issues using this API, please let us know using this form.

🚧

This API requires the following scopes:

  • custom-objects:read
  • custom-objects:write

Data model

Records sent from your data source using the Bulk Create Data Source Records are stored in Klaviyo. Once a custom object is defined using either the Object Manager UI or the Beta Custom Objects Definition APIs, we map your source data into custom object records and link them to profiles. While custom object records are available for use in Klaviyo workflows and segmentation, the raw JSON file is not directly accessible in the Klaviyo UI.

All custom object records have a unique identifier, properties, and a profile relationship as defined by the Object Manager or programmatically via the Beta APIs.

All object types can have at most one active schema and one draft schema at a time. Setting a draft schema to active will overwrite the current active schema. Flows, segments, and templates can behave unexpectedly if they relied on a property that is no longer in the new schema, or if an existing property's name or data type was changed.

Unique identifier

Every object must have a unique ID. The unique ID can be any ID you choose - you must provide this ID when syncing each object record from your system’s source of truth to Klaviyo.

Object properties

Every object can have up to 15 properties (or 30 properties depending on your billing plan) and must not exceed 8 KB.

Every property on an object must be one of the following acceptable data types:

  • text : The maximum size is 2 KB.
  • integer
  • decimal
  • boolean
  • timestamp : Must follow Klaviyo's acceptable timestamp formats. All datetimes are converted to UTC. Defaults to midnight if no timestamp is provided.

Relationships

All custom object records must have a relationship to a profile. When syncing each custom object record, you must provide one or more acceptable profile identifiers, like email or phone number, to identify which profile the custom object record belongs to.

Updating object records

You must provide the entire object record when you request an update to one or more properties.

🚧

If you exclude any properties, including profile identifiers, those properties are set to null.

Create Data Source(s)

Use the Custom Objects API to create a data source. Returns a unique ID to use when sending data from that source of data.

Below is an example request payload to Create a Data Source:

{
    "data": {
        "type": "data-source",
        "attributes": {
            "visibility": "private",
            "title": "Reservation Database",
            "description": "The source of truth for reservations"
        }
    }
}

Create Data Source Record

Use the Create Data Source Record endpoint to ingest data source records one at a time. This endpoint is ideal for real-time or event-driven ingestion workloads.

🚧

This endpoint is available in the 2026-01-15 revision.

Rate limits and throughput:

  • Rate limit tier: LARGE (75 requests/second burst, 700 requests/minute steady)
  • Throughput: Up to 75 records/second and 700 records/minute

Below is an example request payload where the record represents a reservation:

{
    "data": {
        "type": "data-source-record",
        "attributes": {
            "record": {
                "reservation_id": "4d5j4dH",
                "created_at": "2019-07-29T09:18:52.005234+14:00",
                "guest_count": 6,
                "late_cancellation_fee": 32.40,
                "is_active": true,
                "email": "[email protected]"
            }
        },
        "relationships": {
            "data-source": {
                "data": {
                    "type": "data-source",
                    "id": "01JKV3YV229CP2NVMXHM5SD9N5"
                }
            }
        }
    }
}

Bulk Create Data Source Records

Use the Bulk Create Data Source Records endpoint to ingest multiple data source records in a single request. This endpoint is the preferred option for high-throughput batch imports.

Rate limits and throughput:

  • Rate limit tier: SMALL (3 requests/second burst, 60 requests/minute steady)
  • Throughput: Up to ~1,500 records/second and 30,000 records/minute (with 500 records per request)
  • Records per request: Up to 500 records

📘

Choosing between single and bulk endpoints:

  • Use the single record endpoint for real-time, event-driven ingestion where you need to process records individually as they arrive.
  • Use the bulk endpoint for batch imports where you can group multiple records together. While it has a lower rate limit, it supports much higher overall throughput when batching up to 500 records per request.

Below is an example request payload where each record represents a reservation:

{
    "data": {
        "type": "data-source-record-bulk-create-job",
        "attributes": {
            "data-source-records": {
                "data": [
                    {
                        "type": "data-source-record",
                        "attributes": {
                            "record": {
                                "reservation_id": "4d5j4dH",
                                "created_at": "2019-07-29T09:18:52.005234+14:00",
                                "guest_count": 6,
                                "late_cancellation_fee": 32.40,
                                "is_active": true,
                                "email": "[email protected]"
                            }
                        }
                    },
                    {
                        "type": "data-source-record",
                        "attributes": {
                            "record": {
                                "reservation_id": "AfjS8dN",
                                "created_at": "2019-08-12T09:18:52.005234+14:00",
                                "guest_count": 4,
                                "late_cancellation_fee": 21.23,
                                "is_active": false,
                                "email": "[email protected]"
                            }
                        }
                    }
                ]
            }
        },
        "relationships": {
            "data-source": {
                "data": {
                    "type": "data-source",
                    "id": "01JKV3YV229CP2NVMXHM5SD9N5"
                }
            }
        }
    }
}

🚧

This endpoint creates data source records asynchronously, so it may be a while (~15 minutes) before you notice data source records in your account.

Get Data Sources

When making a request to Get Data Sources, here's an example of how a data source should look in your response:

{
   "data": [
       {
           "type": "data-source",
           "id": "01JKV3YV229CP2NVMXHM5SD9N5",
           "attributes": {
               "title": "My Reservation Data Source",
               "visibility": "shared",
               "description": "Data source for reservation data"
           },
           "links": {
               "self": "https://a.klaviyo.com/api/data-sources/01JKV3YV229CP2NVMXHM5SD9N5/"
           }
       }
   ],
   "links": {
       "self": "https://a.klaviyo.com/api/data-sources",
       "next": null,
       "prev": null
   }
}

Limitations

Payload limits

Bulk Create Data Source Records endpoint:

  • Max payload size - 4 MB
  • Max records per request - 500 records

All custom object records:

  • Max object record size - 8 KB
  • Max object property size - 2 KB

📘

Rate limits are specified for each endpoint in their respective sections above. Learn more about rate limits.

Troubleshooting

Common errors

Status codeReasons
400
  • Number of records has exceeded the limit (>500), see "Limitations" above.
  • A data source identifier was not provided in the request attributes.
413
  • Request payload size is too large (>4MB), see "Limitations" above.
429

Additional resources