Skip to content

Export Data from ODP

⏱ 25 minutes intermediate
📜CoreODP

ODP collects rich customer data — events, profiles, segments, computed metrics — but that data is most valuable when it flows into your broader data infrastructure. Your BI team needs it in the data warehouse for cross-system reporting. Your data science team needs it for predictive models. Your CRM needs segment membership updates to trigger workflows.

Without export, ODP becomes a data silo. With export, it becomes a hub that enriches every downstream system with unified customer intelligence.

  1. Choose the right export method for your use case
  2. Query customer profiles and events via the API
  3. Set up webhooks for real-time segment change notifications
  4. Configure batch exports for data warehouse ingestion
  5. Handle privacy and consent requirements in exported data
MethodBest forLatencyVolume
REST APIOn-demand lookups, application integrationsReal-timeIndividual records
WebhooksReacting to segment entry/exit, event triggersNear real-time (seconds)Event-driven
Batch exportData warehouse loads, BI reporting, bulk analysisScheduled (hourly/daily)High volume
  • REST API — Your application needs to look up a customer profile at runtime (e.g., personalization engine checking segment membership before rendering a page).
  • Webhooks — You need to trigger an action when something happens (e.g., send a Slack alert when a high-value customer enters the “at-risk churn” segment).
  • Batch export — You need to load all customer data into a warehouse on a regular schedule for reporting and analysis.

Look up a customer profile by any known identifier:

Get a customer profile
javascript
const fetch = require('node-fetch');

async function getCustomerProfile(identifier, value) {
  const response = await fetch(
    `https://api.zaius.com/v3/profiles?id_field=${identifier}&id_value=${value}`,
    {
      headers: {
        'x-api-key': process.env.ODP_PRIVATE_API_KEY
      }
    }
  );

  return response.json();
}

// Look up by email
const profile = await getCustomerProfile('email', 'customer@example.com');
console.log('Segments:', profile.segments);
console.log('Lifetime value:', profile.attributes.lifetime_value);

// Look up by customer ID
const profileById = await getCustomerProfile(
  'customer_id', 'CUST-9876'
);
python
import requests
import os

def get_customer_profile(
    identifier: str, value: str
) -> dict:
    response = requests.get(
        'https://api.zaius.com/v3/profiles',
        params={
            'id_field': identifier,
            'id_value': value
        },
        headers={
            'x-api-key': os.environ['ODP_PRIVATE_API_KEY']
        }
    )
    response.raise_for_status()
    return response.json()

# Look up by email
profile = get_customer_profile(
    'email', 'customer@example.com'
)
print(f'Segments: {profile["segments"]}')
print(f'LTV: {profile["attributes"]["lifetime_value"]}')
bash
curl -G https://api.zaius.com/v3/profiles \
  -H 'x-api-key: YOUR_PRIVATE_API_KEY' \
  -d 'id_field=email' \
  -d 'id_value=customer@example.com'

Retrieve the event history for a specific customer:

Get customer events
javascript
async function getCustomerEvents(
  identifier, value, eventType
) {
  const params = new URLSearchParams({
    id_field: identifier,
    id_value: value,
    ...(eventType && { event_type: eventType }),
    limit: '50'
  });

  const response = await fetch(
    `https://api.zaius.com/v3/events?${params}`,
    {
      headers: {
        'x-api-key': process.env.ODP_PRIVATE_API_KEY
      }
    }
  );

  return response.json();
}

// Get all events for a customer
const allEvents = await getCustomerEvents(
  'email', 'customer@example.com'
);

// Get only purchase events
const purchases = await getCustomerEvents(
  'email', 'customer@example.com', 'order'
);
python
def get_customer_events(
    identifier: str,
    value: str,
    event_type: str = None
) -> dict:
    params = {
        'id_field': identifier,
        'id_value': value,
        'limit': 50
    }
    if event_type:
        params['event_type'] = event_type

    response = requests.get(
        'https://api.zaius.com/v3/events',
        params=params,
        headers={
            'x-api-key': os.environ['ODP_PRIVATE_API_KEY']
        }
    )
    response.raise_for_status()
    return response.json()

# Get purchase events
purchases = get_customer_events(
    'email', 'customer@example.com',
    event_type='order'
)
bash
curl -G https://api.zaius.com/v3/events \
  -H 'x-api-key: YOUR_PRIVATE_API_KEY' \
  -d 'id_field=email' \
  -d 'id_value=customer@example.com' \
  -d 'event_type=order' \
  -d 'limit=50'

List all customers in a specific segment:

Export segment members
javascript
async function exportSegmentMembers(
  segmentId, cursor = null
) {
  const params = new URLSearchParams({
    segment_id: segmentId,
    limit: '1000'
  });
  if (cursor) params.set('cursor', cursor);

  const response = await fetch(
    `https://api.zaius.com/v3/profiles/export?${params}`,
    {
      headers: {
        'x-api-key': process.env.ODP_PRIVATE_API_KEY
      }
    }
  );

  return response.json();
}

// Paginate through all segment members
let cursor = null;
let allMembers = [];

do {
  const batch = await exportSegmentMembers(
    'seg_abc123', cursor
  );
  allMembers = allMembers.concat(batch.profiles);
  cursor = batch.next_cursor;
} while (cursor);

console.log(`Total members: ${allMembers.length}`);
python
def export_segment_members(
    segment_id: str
) -> list:
    all_members = []
    cursor = None

    while True:
        params = {
            'segment_id': segment_id,
            'limit': 1000
        }
        if cursor:
            params['cursor'] = cursor

        response = requests.get(
            'https://api.zaius.com/v3/profiles/export',
            params=params,
            headers={
                'x-api-key': os.environ['ODP_PRIVATE_API_KEY']
            }
        )
        response.raise_for_status()
        data = response.json()

        all_members.extend(data['profiles'])
        cursor = data.get('next_cursor')

        if not cursor:
            break

    return all_members

members = export_segment_members('seg_abc123')
print(f'Total members: {len(members)}')
bash
curl -G https://api.zaius.com/v3/profiles/export \
  -H 'x-api-key: YOUR_PRIVATE_API_KEY' \
  -d 'segment_id=seg_abc123' \
  -d 'limit=1000'

Webhooks push data to your systems in real time when events occur. Configure them in ODP Settings > Webhooks.

Segment webhooks fire when customers enter or exit a segment:

  1. Navigate to Settings > Webhooks in ODP
  2. Click Create Webhook
  3. Set the Trigger to Segment Entry or Segment Exit
  4. Select the target segment
  5. Enter your endpoint URL (must accept POST requests over HTTPS)
  6. Optionally add authentication headers
  7. Save and test with a sample payload

Your endpoint receives a POST request with a JSON body:

Webhook handler example
javascript
const express = require('express');
const app = express();

app.post('/webhooks/odp', express.json(), (req, res) => {
  const { event_type, customer, segment } = req.body;

  console.log(`Customer ${customer.email}`);
  console.log(`${event_type} segment: ${segment.name}`);

  switch (event_type) {
    case 'segment_entry':
      // Customer entered a segment
      triggerWelcomeEmail(customer.email, segment.name);
      break;
    case 'segment_exit':
      // Customer left a segment
      removeFromCampaign(customer.email, segment.name);
      break;
  }

  // Respond quickly to acknowledge receipt
  res.status(200).json({ received: true });
});

app.listen(3000);
python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhooks/odp', methods=['POST'])
def handle_odp_webhook():
    payload = request.get_json()

    event_type = payload['event_type']
    customer = payload['customer']
    segment = payload['segment']

    print(f'Customer {customer["email"]}')
    print(f'{event_type} segment: {segment["name"]}')

    if event_type == 'segment_entry':
        trigger_welcome_email(
            customer['email'], segment['name']
        )
    elif event_type == 'segment_exit':
        remove_from_campaign(
            customer['email'], segment['name']
        )

    return jsonify({'received': True}), 200

Webhook reliability tips:

  • Respond with a 2xx status within 5 seconds. Do heavy processing asynchronously.
  • ODP retries failed deliveries (non-2xx or timeout) with exponential backoff.
  • Implement idempotency — the same event may be delivered more than once.

For high-volume data warehouse loads, use the ODP batch export feature.

DestinationConnection method
Amazon S3IAM role or access key credentials
Google BigQueryService account with BigQuery write access
SnowflakeSnowflake connector with warehouse and schema details
Azure Blob StorageStorage account key or SAS token
SFTPSSH key or username/password
  1. Navigate to Settings > Data Export in ODP
  2. Click Create Export
  3. Select the data type: Customer Profiles, Events, or Segment Membership
  4. Choose your destination and provide connection credentials
  5. Set the schedule: hourly, daily, or weekly
  6. Select which fields to include (or export all)
  7. Choose the file format: CSV, JSON, or Parquet
  8. Save and run a test export
Use caseData to exportScheduleDestination
BI dashboardsCustomer profiles + eventsDailyBigQuery or Snowflake
Data science modelsFull event historyWeeklyS3 as Parquet
CRM syncSegment membership changesHourlySFTP to CRM import
Compliance auditAll customer data with consent statusMonthlySecure S3 bucket
Marketing reportingCampaign events + conversionsDailyBigQuery

Exported data contains customer information. Handle it responsibly.

Include consent fields in exports so downstream systems can respect customer preferences:

  • marketing_consent — Whether the customer opted in to marketing communications
  • tracking_consent — Whether the customer consented to behavioral tracking
  • data_processing_consent — Whether the customer consented to data processing (GDPR)

Export only the fields you need. If your BI dashboard does not require email addresses, exclude PII from the export. This reduces risk if the destination system is compromised.

Ensure exported data follows the same retention policies as ODP. If ODP deletes customer data after 24 months, configure your warehouse to apply the same retention.

When a customer exercises their right to deletion (GDPR Article 17, CCPA), you must delete their data from all systems — including exported copies. Plan for this:

  1. Track which systems received exported data
  2. Implement a deletion workflow that propagates ODP deletion requests to all downstream systems
  3. Use the ODP Deletion API to trigger the process
Handle a deletion request
javascript
async function deleteCustomerData(email) {
  // Delete from ODP
  const response = await fetch(
    'https://api.zaius.com/v3/profiles/delete',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.ODP_PRIVATE_API_KEY
      },
      body: JSON.stringify({
        id_field: 'email',
        id_value: email
      })
    }
  );

  if (response.ok) {
    // Propagate deletion to downstream systems
    await deleteFromWarehouse(email);
    await deleteFromCRM(email);
    console.log(`Deletion complete for ${email}`);
  }
}
python
def delete_customer_data(email: str) -> None:
    # Delete from ODP
    response = requests.post(
        'https://api.zaius.com/v3/profiles/delete',
        headers={
            'Content-Type': 'application/json',
            'x-api-key': os.environ['ODP_PRIVATE_API_KEY']
        },
        json={
            'id_field': 'email',
            'id_value': email
        }
    )
    response.raise_for_status()

    # Propagate deletion to downstream systems
    delete_from_warehouse(email)
    delete_from_crm(email)
    print(f'Deletion complete for {email}')
bash
curl -X POST https://api.zaius.com/v3/profiles/delete \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: YOUR_PRIVATE_API_KEY' \
  -d '{
    "id_field": "email",
    "id_value": "customer@example.com"
  }'
IssueCauseFix
API returns 401 UnauthorizedInvalid or expired API keyRegenerate the private API key in ODP Settings > API Keys
API returns 429 Too Many RequestsRate limit exceededImplement exponential backoff; default limit is 100 requests/second
Webhook not firingEndpoint unreachable or returning non-2xxCheck endpoint URL is publicly accessible over HTTPS; verify in webhook logs
Webhook payload missing fieldsFields not tracked or customer not identifiedVerify event tracking includes expected properties; check identity resolution
Batch export produces empty filesNo data matches the export criteriaVerify date range, segment filter, and field selection; check that data exists in ODP
Batch export credentials failDestination permissions incorrectVerify IAM role, service account, or access key has write permission to the destination
Exported PII after deletion requestDeletion not propagated to export destinationImplement deletion propagation workflow; re-run deletion in downstream systems