# PIM Export Profile Copy Tool

By
The Quable Team

A Python script to copy export profiles and their associated schedules from one Quable PIM instance to another.

# Overview

This tool facilitates the migration of export profiles and their scheduling configurations between Quable PIM instances. It handles intelligent profile updates (create new or update existing based on name matching), cleans mapping data, and securely handles SFTP credentials.

# Features

  • Smart Profile Management: Automatically detects existing profiles by name and updates them (PUT) or creates new ones (POST)
  • Schedule Migration: Copies export schedules with proper profile ID mapping
  • Data Cleaning: Removes unwanted metadata fields (@id, @type, empty options arrays) from mappings
  • Security: Masks passwords in SFTP URLs before transmission
  • Error Handling: Comprehensive error handling with detailed logging
  • Idempotent: Can be run multiple times without creating duplicates

# Prerequisites

  • Python 3.6+
  • requests library
  • Valid Bearer tokens for both source and target PIM instances

# Installation

  1. Install required dependencies:
pip install requests
  1. Download the script:
wget https://github.com/quable/developers.quable.io_public/blob/main/code-snippets/data-flow-profiles/dataflow-copy.py
chmod +x dataflow-copy.py

# Usage

# Basic Syntax

python dataflow-copy.py --source SOURCE_URL --target TARGET_URL \
                           --source-bearer SOURCE_TOKEN --target-bearer TARGET_TOKEN

# Arguments

Argument Short Required Description
--source -s Yes Source PIM instance URL (e.g., https://source.quable.com)
--target -t Yes Target PIM instance URL (e.g., https://target.quable.com)
--source-bearer -sb Yes Bearer token for source instance
--target-bearer -tb Yes Bearer token for target instance

# Examples

Full syntax:

python dataflow-copy.py --source SOURCE --target TARGET \
                           --source-bearer "eyJ0eXAiOiJKV1QiLCJhbGc..." --target-bearer "eyJ0eXAiOiJKV1QiLCJhbGc..."

Short syntax:

python dataflow-copy.py -s SOURCE -t TARGET \
                           -sb "eyJ0eXAiOiJKV1QiLCJhbGc..." -tb "eyJ0eXAiOiJKV1QiLCJhbGc..."

# How It Works

# 1. Profile Processing

The script retrieves export profiles from the source instance via:

GET https://SOURCE.quable.com/api/export-profiles

For each profile, it:

  • Checks if a profile with the same name exists on target
  • If exists: Updates via PUT /api/export-profiles/{id}
  • If not exists: Creates via POST /api/export-profiles
  • Cleans mapping data by removing @id, @type, and empty options arrays

# 2. Schedule Processing

Export schedules are retrieved via:

GET https://SOURCE.quable.com/api/plannings/exports

For each schedule, it:

  • Maps old profile IDs to new profile IDs
  • Masks passwords in SFTP URLs (e.g., sftp://user:***@host/path)
  • Creates schedules via POST /api/plannings/exports

# 3. Data Transformation

Profile Data Cleaning:

  • Removes: id, @type, @id, dateCreated, dateModified, createdBy, updatedBy
  • Recursively cleans mappings to remove @id, @type, empty options arrays

SFTP URL Security:

Before: sftp://user:password@ftp.example.com/path
After:  sftp://user:***@ftp.example.com/path

# API Endpoints Used

Operation Method Endpoint
Get source profiles GET /api/export-profiles
Get target profiles GET /api/export-profiles
Create profile POST /api/export-profiles
Update profile PUT /api/export-profiles/{id}
Get source schedules GET /api/plannings/exports
Create schedule POST /api/plannings/exports

# Output Example

🔧 Configuration:
   Source: https://prod.quable.com
   Target: https://staging.quable.com
   Source Bearer: ******************abc123
   Target Bearer: ******************def456

🚀 Starting export data copy
==================================================
🔄 Retrieving existing export profiles from target...
✅ 3 existing export profiles found on target
🔄 Retrieving export profiles from source...
✅ 5 export profiles retrieved

📝 Creating/updating export profiles on target...
🔄 Updating existing profile 'Product Export' (ID: abc-123)...
✅ Profile updated with ID: abc-123
🔄 Creating new profile 'New Export Config'...
✅ Profile created with ID: def-456

✅ 5/5 export profiles processed

📅 Creating export schedules on target...
🔄 Creating schedule 'Daily Product Export'...
   Old profile ID: old-123 → New profile ID: abc-123
   Upload Location: sftp://user:***@ftp.example.com/exports
✅ Schedule created with ID: schedule-789

✅ 2/2 export schedules created

==================================================
🎉 Copy completed successfully!
   • Export profiles processed: 5
   • Schedules copied: 2

📋 Profile ID mapping:
   old-123 → abc-123
   old-456 → def-456

# Error Handling

The script includes comprehensive error handling:

  • Network errors: Retries and detailed error messages
  • Authentication errors: Clear token validation feedback
  • Missing profiles: Graceful handling when referenced profiles don't exist
  • Invalid data: Validation and cleaning of malformed data

# Security Considerations

  • Token masking: Bearer tokens are partially masked in logs
  • Password sanitization: SFTP passwords are automatically masked
  • HTTPS only: All API calls use HTTPS
  • No local storage: No sensitive data is stored locally

# Troubleshooting

# Common Issues

Authentication Error (401)

Error during GET request to https://source.quable.com/api/export-profiles: 401 Client Error

Solution: Verify your Bearer token is valid and has appropriate permissions.

Profile Not Found

⚠️  Profile ID old-123 not found in mapping, schedule ignored

Solution: This indicates a schedule references a profile that wasn't successfully copied. Check profile creation logs.

Network Timeout

Error during POST request: Connection timeout

Solution: Check network connectivity and instance availability.

# Limitations

  • Only copies export profiles and schedules (not import profiles)
  • Requires manual Bearer token management
  • No incremental sync (full copy each time)
  • SFTP credentials are masked but not validated

# Contributing

This script is part of the Quable developer cookbook. For improvements or bug reports, please contact your Quable support team.

# License

This script is provided as-is for Quable customers. Please refer to your Quable license agreement for usage terms.