Importing custom objects via SFTP and data warehouse syncing
You will learn
You can import custom object records in bulk using 2 methods: SFTP and data warehouse import. Both methods load raw records into a data source. You can use the imported records with a new custom object or an existing object configured with that data source.
This article covers how each method works, how to format your files, and what to expect during and after import.
Before you begin
Before importing, review Getting started with custom objects and Custom Objects API overview.
Keep these concepts in mind when configuring an import:
- A custom objects Data Source stores the raw data you import. A Data Source Record is an individual record in that data source. These records persist in Klaviyo, so you can use previously imported data to configure additional custom objects.
- A custom object itself consists of an object schema and a mapping schema between a Data Source and the object.
- Different custom objects can be mapped to a single Data Source, using either the same or different field mappings.
For SFTP, you need the ID of an existing data source in your account. You can create a data source through the API or while configuring a new custom object in Klaviyo. For data warehouse import, you can create a data source or select an existing one during sync setup.
Method 1: SFTP import
Before uploading, add an SSH public key to Klaviyo and connect your SFTP client using the credentials Klaviyo provides. See Import data via SFTP.
Data source
Identify the custom objects data source ID you wish to target with the import, and create a config.json file with the ID, like this:
{
"data_source_id": "01KTMWCZ8ZMNZS0HG5HQNX0H6E"
}Directory structure
- From the SFTP root, create a new folder in
/imports/custom_objects/. The name of the folder does not affect how the data is processed. - Copy your
config.jsonfile, which containsdata_source_id, into the new folder. - Upload your data files to the same folder after uploading the configuration file.
*.csvand*.jsonlfiles will be processed.
{company_id}/imports/custom_objects/pets/
config.json ← Configuration file with data_source_id
pet_records.csv ← CSV file to process
pet_records.jsonl ← JSONL file to processFiles placed directly under custom_objects/ without a subdirectory will be rejected. Every custom object import must be inside a named subfolder.
Supported file formats
Format | Extension | Notes |
|---|---|---|
CSV |
| Include a header row. Use column names referenced by your custom object mappings. Cell values are imported as strings. |
JSONL |
| One JSON object per line. Use property names referenced by your custom object mappings. Nested objects and arrays retain their structure. |
JSONL is strongly recommended when your records contain nested data or arrays.
CSV formatting
- The first row must be a header row. Use column names referenced by your custom object mappings.
- If a CSV cell contains JSON text, enclose the cell in double quotes and double each internal quote (e.g.,
""). The value is imported as a string. Use JSONL to preserve nested objects or arrays. - Empty CSV cells are imported as empty strings.
Example CSV:
subscription_id,product_name,status,start_date
sub_001,Premium Plan,active,2025-01-15
sub_002,Basic Plan,inactive,2024-06-01JSONL formatting
- Each line must be a valid JSON object (
{...}). - Lines that are not objects (e.g., arrays or primitives) are skipped and counted as skipped rows.
- Empty lines are silently ignored.
- Nested objects and arrays are passed through and stored in full.
Example JSONL:
{"subscription_id": "sub_001", "product_name": "Premium Plan", "status": "active", "start_date": "2025-01-15"}
{"subscription_id": "sub_002", "product_name": "Basic Plan", "status": "inactive", "start_date": "2024-06-01", "metadata": {"source": "shopify", "tags": ["vip", "annual"]}}What happens during import
- Klaviyo detects the subdirectory path and determines the resource type is
custom_objects. - Klaviyo checks if a custom objects data source with the
data_source_idinconfig.jsonexists in the account. - Klaviyo extracts records from the file, then writes them to the data source in batches of up to 500.
- Records are added to the data source through the same custom object ingestion process used for records sent via API.
- You receive a completion notification (email or in-product) when the job finishes.
Error handling
- Klaviyo skips CSV rows with an incorrect number of columns and invalid JSONL lines, then continues processing. If part of a CSV file cannot be parsed, all rows in that part are skipped.
- Check the completion notification for the processed and skipped row counts. Invalid JSONL lines are counted as skipped rows; no downloadable row-level error file is created for JSONL files.
- If the folder has no
config.jsonor the data source ID in the config is invalid, the file will not be processed. To re-attempt, you must upload the file again with a different name. Old files will be removed after 30 days.
Method 2: Data warehouse import
Overview
If you use Snowflake, Databricks, or BigQuery, you can configure a data warehouse sync to import custom object records directly. Connect your warehouse, select a table or view, and choose Custom Objects as the data object type. Then choose the Klaviyo data source that will receive the records.
Before starting, connect your warehouse to Klaviyo and make sure the table or view you want to sync is accessible. For plan requirements and connection guides, see Understanding data warehouse import in Klaviyo.
Configuring the sync
- Go to Data management > Syncing and open your warehouse connection.
- Click Add source to create a new sync. To edit a sync, open its row menu and select Edit.
- Enter a sync Name and select the warehouse table or view in Data source. Under Data object types, select Custom Objects.
- Choose the Cadence. For automatic imports, select Schedule run and configure the schedule. For imports you start yourself, select Manual. If creating a new sync, click Next.
- Under Change detection, select a column in New Row Detection that indicates when each row was added or modified. The column must contain a datetime value or a value that can be converted to a datetime.
- Under Custom object data source, choose the Data source mode:
- Sync to existing data source: select the destination under Select a data source. Make sure the warehouse column names match the source property names used in your custom object mappings. Changing the data source redirects future synced records to that source.
- Create new data source: enter a unique Data source name. Klaviyo suggests
Data Sync: {table_name}, which you can change. The data source is created when you save the sync.
- Click Done to create the sync, or Save if editing an existing sync. A new sync is active when saved. To start an import yourself, open the sync and click Run sync.
Sync behavior
- Records are processed in batches of up to 500 per call.
- Data warehouse imports for custom objects do not produce a downloadable row-level error file.
- Open the sync’s Runs tab to check run status and processing progress. Open Logs for details about sync errors.
After importing
If one or more custom objects are already active with that data source, the imported records are processed using those objects’ mappings, just as they would be if you added data source records via API.
If no custom object uses the data source yet, you can create one using the imported records. Importing at least 1 record first lets you preview its fields while mapping. When creating the object, select the data source used for this import. Follow Getting started with custom objects to finish configuring and publishing the object.