Python SDK to interface with the Whistic API
Project description
Whistic SDK
A Python SDK to interface with the Whistic API for vendor management and third-party risk management operations.
Installation
From PyPI (Recommended)
pip install whistic
From Source
git clone https://github.com/massyn/whistic.git
cd whistic
pip install -e .
Requirements
- Python 3.7 or higher
- Create an API Key on the Whistic platform
Quick Start
Environment Setup
The Whistic SDK requires authentication via an API token. You must provide this token through the WHISTIC_TOKEN environment variable.
Method 1: Environment Variable (Linux/macOS)
export WHISTIC_TOKEN=your_api_token_here
Method 2: Environment Variable (Windows)
set WHISTIC_TOKEN=your_api_token_here
Method 3: .env File (Recommended for development)
Create a .env file in your project root directory:
WHISTIC_TOKEN=your_api_token_here
The SDK will automatically load this file when you call load_dotenv() in your Python code (as shown in the examples below).
Important Notes:
- Never commit your
.envfile or API tokens to version control - Add
.envto your.gitignorefile - The API token is required for all SDK operations - the client will fail to initialize without it
Basic Usage
from whistic import Whistic
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Initialize the client
client = Whistic()
# List all vendors
vendors = client.vendors.list()
print(f"Found {len(vendors)} vendors")
# Get detailed information for all vendors (parallel processing)
detailed_vendors = client.vendors.describe()
# Get a specific vendor
vendor_id = vendors[0]['identifier']
vendor_details = client.vendors.get(vendor_id)
# Update a vendor
client.vendors.update(vendor_id, {
"name": "Updated Vendor Name",
"description": "Updated description"
})
# Create a new vendor
new_vendor_data = {
"name": "New Vendor",
"description": "A new vendor",
# ... other vendor fields
}
client.vendors.new(new_vendor_data)
# Get vendor by domain
vendor_by_domain = client.vendors.domain("example.com")
if vendor_by_domain:
print(f"Found vendor: {vendor_by_domain.get('name', 'Unknown')}")
# Get vendor intake form
intake_form = client.vendor_intake_form.get()
print(f"Intake form has {len(intake_form.get('sections', []))} sections")
# Display the form structure with field names
client.vendor_intake_form.show()
Advanced Usage
Custom Configuration
from whistic import Whistic
# Configure with custom settings
client = Whistic(max_workers=10) # Increase parallel processing workers
Batch Operations
# Process all vendors in parallel
all_vendors = client.vendors.describe()
# Filter and update multiple vendors
for vendor in all_vendors:
if vendor.get('status') == 'pending':
client.vendors.update(vendor['identifier'], {
'status': 'active'
})
Vendor Intake Form
from whistic.vendorintakeform import VendorFormValidationError
# Get the vendor intake form structure
intake_form = client.vendor_intake_form.get()
if intake_form:
print(f"Form identifier: {intake_form.get('identifier', 'N/A')}")
print(f"Number of sections: {len(intake_form.get('sections', []))}")
# Display section information
for section in intake_form.get('sections', []):
print(f"Section: {section.get('title', 'Unnamed')}")
for column in section.get('columns', []):
questions = column.get('questions', [])
print(f" Questions: {len(questions)}")
# Display the form structure for easy reference
# This prints all field names in "Section:Question" format
client.vendor_intake_form.show()
# Submit a new vendor intake form
# Field names use the format "Section:Question"
vendor_data = {
"Vendor Information:Vendor URL": "example-vendor.com",
"Vendor Information:Vendor Name": "Example Vendor Inc.",
"Vendor Information:Product / Service Name": "Cloud Security Platform",
"Vendor Information:Write a description of the vendor / service": "A comprehensive security solution",
"Vendor Information:First Name": "John",
"Vendor Information:Last Name": "Smith",
"Vendor Information:Email Address": "john.smith@example-vendor.com",
"Vendor Information:Job Title": "Security Manager",
"Primary Business Owner Information:First Name": "Jane",
"Primary Business Owner Information:Last Name": "Doe",
"Primary Business Owner Information:Email Address": "jane.doe@yourcompany.com"
# ... add other required fields in "Section:Question" format
}
# Submit the vendor intake form (validates all required fields)
try:
success = client.vendor_intake_form.vendor_intake(vendor_data)
if success:
print("Vendor intake form submitted successfully!")
except VendorFormValidationError as e:
print(f"Form validation failed: {e}")
Error Handling
import logging
# Enable debug logging to see API calls
logging.basicConfig(level=logging.DEBUG)
try:
vendor = client.vendors.get('non-existent-id')
except Exception as e:
print(f"Error fetching vendor: {e}")
API Reference
Whistic Class
The main client class for interacting with the Whistic API.
Constructor
Whistic(max_workers=5): Initialize client with optional max workers for parallel processing
Properties
vendors: Access to vendor management operationsvendor_intake_form: Access to vendor intake form operations
Vendors Class
Handles all vendor-related operations.
Methods
-
list(): Get paginated list of all vendor identifiers- Returns: List of vendor objects with basic information
-
describe(): Get detailed information for all vendors using parallel processing- Returns: List of complete vendor objects with all details
-
get(vendor_id): Fetch detailed information for a specific vendor- Parameters:
vendor_id(str) - The vendor identifier - Returns: Complete vendor object or None if not found
- Parameters:
-
update(vendor_id, data): Update vendor information- Parameters:
vendor_id(str) - The vendor identifierdata(dict) - Dictionary with fields to update
- Note: Uses deep merge to preserve existing data
- Parameters:
-
new(data): Create a new vendor- Parameters:
data(dict) - Complete vendor data structure
- Parameters:
-
domain(domain): Retrieve vendor details by domain name- Parameters:
domain(str) - The domain name to search for - Returns: Vendor object if found, or None if not found
- Parameters:
VendorIntakeForm Class
Handles vendor intake form operations.
Methods
-
get(): Retrieve the vendor intake form structure- Returns: Complete intake form object with sections, columns, and questions, or None if not found
- The form contains all the questions and structure that vendors see during onboarding
- Includes metadata like identifiers, answer options, and required fields
-
show(): Display the form structure for reference- Prints all field names in "Section:Question" format to the console
- Useful for understanding the form structure and field names needed for submission
- No return value - outputs directly to console
-
vendor_intake(data): Submit a new vendor intake form- Parameters:
data(dict) - Dictionary containing form field values using "Section:Question" format as keys
- Returns: Boolean indicating success (True) or failure (False) of submission
- Raises:
VendorFormValidationErrorif required fields are missing or invalid - Validates required fields and answer options before submission
- Automatically formats data into proper API submission structure
- Creates custom attributes from fields not in the standard vendor creation payload
- Example:
client.vendor_intake_form.vendor_intake({"Vendor Information:Vendor URL": "example.com", "Vendor Information:Vendor Name": "Example Inc."})
- Parameters:
Features
- Automatic Pagination: Handles API pagination automatically
- Parallel Processing: Concurrent API calls for better performance
- Rate Limiting: Built-in retry logic with exponential backoff
- Deep Merge Updates: Safely update vendor data without losing existing fields
- Colored Logging: Enhanced console output for debugging
- Environment Variable Support: Secure token management
Error Handling
The SDK includes comprehensive error handling:
- Rate Limiting: Automatic retry with exponential backoff for 429 responses
- Request Timeouts: 30-second timeout on all API calls
- Connection Errors: Graceful handling of network issues
- API Errors: Detailed error logging with response codes and messages
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Reference
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file whistic-0.3.0.tar.gz.
File metadata
- Download URL: whistic-0.3.0.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55cb61a4c0800c28aa8e6ddb7b41c3cc4bc76e283798a834490e7078a2831b2e
|
|
| MD5 |
ae760f5d147123e57a6b8f6ecc53102c
|
|
| BLAKE2b-256 |
906e6948dfb9924bcb3101f7c9cb4fc12fac8dcfaade7cb6ff5a51ac8b96dbad
|
File details
Details for the file whistic-0.3.0-py3-none-any.whl.
File metadata
- Download URL: whistic-0.3.0-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ba47196d2991d7c380f5941599eeb9e6cf4cbf2f5fc98aad974a520357823ef
|
|
| MD5 |
0ea5ecc5652d82521bc5e68bf1060bf8
|
|
| BLAKE2b-256 |
d5f8c9b7a0c015914388cd9fb685a600da09c99afd977c65b27a51c5781df778
|