Introduction
Enterpret's Custom Webhook integration lets you programmatically send customer feedback to Enterpret for analysis. This method is ideal for connecting feedback sources not supported by native integrations—making it easy to consolidate all your feedback in Enterpret.
When to Use a Custom Webhook
Use this integration when you're working with:
Review platforms that are not natively supported by Enterpret
Forum feedback that requires custom collection
Chatbot conversations from platforms without direct integrations
Survey tools specific to your industry
Internal feedback systems built for your organization
Feedback extracted from data warehouses (e.g., Redshift, BigQuery)
Note: Before proceeding, visit our native integrations page to see if your feedback source is already supported.
Prerequisites
API access to your feedback source
Engineering resources to implement the webhook connection
Enterpret account with administrator access
Not an engineer? This guide is designed for developers and contains technical instructions. Please share it with your engineering team for implementation.
Getting Started
Create an API Key
Go to the Integrations page in your Enterpret instance
Click +New Integration, and search for "Webhook"
Choose the type of webhook integration based on your needs:
Provide a descriptive Display Name for your integration
This name will appear as the source for records throughout Enterpret
Add a detailed description to improve summary and prediction quality
Once configured, you'll find your API key at the top of the integration page
This key should be included in all API requests to authenticate
Webhook Endpoint & Authentication
Endpoint URL: https://api.enterpret.com/webhook/custom/all
Authentication: Include your API key in every request header
api-key: your-api-key-here
Rate Limits:
Maximum: 20 requests per minute (RPM)
Maximum payload size: 1MB per request
Recommended: Stay below 100 records per batch
Data Structure Overview
Webhook payloads must follow a structured JSON format. Enterpret accepts data in JSON format with a specific structure based on the feedback type.
Supported Feedback Types
We support four primary types of feedback:
REVIEW - Simple product/service reviews
CONVERSATION - Multi-message interactions between users and agents
SURVEY - Question-and-answer format feedback (NPS, CSAT, product feedback forms)
AUDIO_RECORDING - Voice recordings with optional transcripts
Core Fields
All records require these essential fields:
{ "records": [ { "id": "unique-identifier", "fileID": "source-identifier", "type": "REVIEW|CONVERSATION|SURVEY|AUDIO_RECORDING", "createdAt": 1716460800, // Type-specific fields go here "metadata": { "metadata": { "custom_field": { "array": { "s": ["value1", "value2"] } } } } } ] }
Detailed Guides by Feedback Type
REVIEW Type
The simplest feedback format, ideal for app store reviews, product reviews, etc.
Required fields:
text
: The content of the review
Example:
{ "records": [ { "id": "review-123", "fileID": "appstore-reviews", "type": "REVIEW", "createdAt": 1716460800, "text": "This product works exactly as described. Very happy with my purchase!", "metadata": { "metadata": { "rating": { "array": { "n": [5] } }, "platform": { "array": { "s": ["iOS App Store"] } } } } } ] }
SURVEY Type
Use for structured question-and-answer feedback like NPS, CSAT, and product feedback surveys.
Required fields:
surveyResponse
: Contains an array of responsesEach response needs a
question
fieldThe
answer
andselectedOptions
fields are optional
Example:
{ "records": [ { "id": "survey-456", "fileID": "nps-survey", "type": "SURVEY", "createdAt": 1716460800, "surveyResponse": { "responses": [ { "question": "How likely are you to recommend our product to a colleague?", "selectedOptions": ["9"] }, { "question": "What is the primary reason for your score?", "answer": "The product is intuitive and saves me time on daily tasks." }, { "question": "Which features do you use most often?", "selectedOptions": ["Dashboard", "Reports", "API"] } ] }, "metadata": { "metadata": { "nps_score": { "array": { "n": [9] } }, "user_segment": { "array": { "s": ["Enterprise"] } } } } } ] }
CONVERSATION Type
Ideal for support tickets, chat transcripts, or any back-and-forth communication.
Required fields:
conversation
: Contains an array of messagesEach message needs
text
andactor
fieldsActor must be one of: "user", "agent", or "bot"
Example:
{ "records": [ { "id": "convo-789", "fileID": "support-chats", "type": "CONVERSATION", "createdAt": 1716460800, "conversation": { "msgs": [ { "actor": "user", "text": "I'm having trouble exporting my data to CSV format." }, { "actor": "agent", "text": "I'm sorry to hear that. Let me help you troubleshoot this issue." }, { "actor": "agent", "text": "Could you please tell me what happens when you try to export?" }, { "actor": "user", "text": "I click on Export, select CSV, but nothing downloads." }, { "actor": "agent", "text": "Thanks for that information. Let's try clearing your browser cache first." } ] }, "metadata": { "metadata": { "ticket_id": { "array": { "s": ["SUPPORT-1234"] } }, "resolution_time_minutes": { "array": { "n": [18] } } } } } ] }
AUDIO_RECORDING Type
Use for voice recordings from call centers, sales calls, or other audio feedback.
Required fields:
audioRecording
: Contains theaudioURL
fieldaudioURL
should be publicly accessible or have a long-lived signed URL
Supported formats: mp3, mp4, wav, flac, ogg, amr, webm, m4a
Optional: Include a transcript to improve analysis or use your own transcription
With Automatic Transcription:
{ "records": [ { "id": "call-abc123", "fileID": "sales-calls", "type": "AUDIO_RECORDING", "createdAt": 1716460800, "audioRecording": { "audioURL": "https://storage.example.com/calls/customer-feedback-call.mp3" }, "metadata": { "metadata": { "call_duration_seconds": { "array": { "n": [352] } }, "call_type": { "array": { "s": ["Sales Demo"] } } } } } ] }
With Provided Transcript:
{ "records": [ { "id": "call-xyz789", "fileID": "support-calls", "type": "AUDIO_RECORDING", "createdAt": 1716460800, "audioRecording": { "audioURL": "https://storage.example.com/calls/support-call.mp3", "transcript": { "conversation": { "units": [ { "actor": "agent", "actorID": "support-rep-42", "text": "Thank you for calling customer support. How can I help you today?", "metadata": { "startTime": 1000, "endTime": 5000 } }, { "actor": "user", "actorID": "caller", "text": "Hi, I'm having an issue with logging into my account.", "metadata": { "startTime": 5500, "endTime": 9000 } } ] } } }, "metadata": { "metadata": { "issue_category": { "array": { "s": ["Authentication"] } } } } } ] }
Working with Metadata
Metadata provides crucial context about your feedback. Enterpret uses this data for filtering, analysis, and visualization.
Metadata Structure
All metadata follows this format:
"metadata": { "metadata": { "field_name": { "array": { "type_indicator": [values] } } } }
Supported Metadata Types
Strings: Use "s" as the type indicator
"user_tier": { "array": { "s": ["Premium"] } }
Numbers: Use "n" as the type indicator
"rating": { "array": { "n": [4.5] } }
Booleans: Use "b" as the type indicator
"is_paying_customer": { "array": { "b": [true] } }
Multiple Values: Arrays can contain multiple values
"tags": { "array": { "s": ["bug", "ui", "mobile"] } }
Important: Each metadata field can only use one type. Mixing types (e.g., strings and numbers) in the same field is not supported.
Error Handling
Our API provides detailed error messages to help you troubleshoot issues with your webhook implementation.
Error Response Structure
When you encounter an error, you'll receive a JSON response with:
Field | Type | Description |
| String | A detailed error message explaining the issue |
| String | An error code identifier |
| String | A unique ID to reference when contacting support |
Common Error Responses
Error Code | HTTP Status | Is Retriable? | Description |
| 500 | Yes | Server-side issue - retry with exponential backoff |
| 400 | No | Issue with request format or data |
| 400 | No | Required field is missing from the payload |
| 400 | No | Field format doesn't match expected schema |
| 400 | No | Too many records in single request (max 100) |
| 413 | No | Request payload exceeds 1MB limit |
| 429 | Yes | Too many requests - implement backoff |
| 401 | No | API key is invalid or missing |
Example Error Response
{ "msg": "Missing required field: 'id'. Each record must have a unique identifier.", "code": "ErrCodeMissingRequiredField", "referenceID": "8B5OQA" }
Troubleshooting Tips
Authentication Issues: Verify your API key is correct and the integration is enabled
Format Problems: Ensure your JSON is valid and follows the required schema
Missing Fields: Check that all required fields are present for your feedback type
Invalid Values: Verify field values meet the requirements (e.g., actor types)
Large Payloads: Consider breaking very large requests into smaller batches
Implementation Examples
Example: Sending a Batch of Reviews
import requests import json import time # Configuration api_key = "your-api-key" endpoint = "https://api.enterpret.com/webhook/custom/all" # Sample data reviews = [ { "id": f"review-{i}", "fileID": "product-reviews", "type": "REVIEW", "createdAt": int(time.time()), "text": f"Sample review text {i}", "metadata": { "metadata": { "rating": { "array": { "n": [4] } } } } } for i in range(1, 4) # Creating 3 sample reviews ] # Prepare payload payload = { "records": reviews } # Send request headers = { "api-key": api_key, "Content-Type": "application/json" } response = requests.post(endpoint, headers=headers, data=json.dumps(payload)) # Handle response if response.status_code == 200: print("Successfully sent reviews to Enterpret") else: print(f"Error: {response.status_code}") print(response.json())
Example: Extracting Data from Your Database
import requests import json import psycopg2 import time # Database connection conn = psycopg2.connect("dbname=feedback user=user password=pass host=localhost") cur = conn.cursor() # Fetch data cur.execute("SELECT id, created_at, feedback_text, rating FROM customer_feedback LIMIT 100") rows = cur.fetchall() # Prepare records records = [] for row in rows: db_id, created_at, feedback_text, rating = row # Convert datetime to Unix timestamp timestamp = int(created_at.timestamp()) record = { "id": f"db-{db_id}", "fileID": "database-extract", "type": "REVIEW", "createdAt": timestamp, "text": feedback_text, "metadata": { "metadata": { "rating": { "array": { "n": [rating] } }, "source": { "array": { "s": ["internal_database"] } } } } } records.append(record) # Send to Enterpret headers = { "api-key": "your-api-key", "Content-Type": "application/json" } payload = { "records": records } response = requests.post( "https://api.enterpret.com/webhook/custom/all", headers=headers, data=json.dumps(payload) ) print(f"Status: {response.status_code}") print(response.json()) # Close database connection cur.close() conn.close()
Interactive Code Examples
We provide downloadable notebooks with executable code examples to accelerate your integration development:
cURL Examples Notebook
Best for: Initial testing, debugging, and non-Python environments
This notebook contains command-line examples that work in any environment. Use it when you need to:
Test the API immediately without writing code
Debug integration issues quickly
Work in non-Python development environments
Validate your API key and endpoint connectivity
What's included:
Working cURL commands for all feedback types
Error handling examples
Authentication testing
Quick validation scripts
Download cURL Examples Notebook: Enterpret Custom Webhook Example_curl.ipynb
Python Implementation Notebook
Best for: Production integrations and Python development teams
This notebook provides production-ready Python classes with type hints for building robust webhook integrations. Use it when you need:
Structured, maintainable code for your integration
Type safety and IDE support
Reusable classes for different feedback types
A foundation for scaling your webhook implementation
What's included:
Complete Python class definitions
Type-safe implementations
Working examples for all feedback types
Error handling and retry logic
Download Python Implementation Notebook: Enterpret Custom Webhook Example.ipynb
When to Use Each Notebook
ScenarioRecommended NotebookWhyFirst-time API testingcURLQuick validation without codingDebugging integration issuescURLMinimal dependencies, easy troubleshootingBuilding production integrationPythonType safety, maintainable code structureNon-Python tech stackcURLLanguage-agnostic, copy-paste friendlyPython development teamPythonLeverages language features, better tooling
Both notebooks complement the examples in this guide and provide hands-on, executable code you can customize for your specific integration needs.
Best Practices
Data Quality
Include rich metadata - The more context you provide, the better Enterpret can analyze your feedback
Maintain consistent IDs - Use stable, unique identifiers for your records
Provide accurate timestamps - This helps with trend analysis over time
Handle special characters properly in your JSON strings
Set appropriate fileType values to organize your feedback sources
Performance
Batch your requests - Send multiple records in each request rather than one at a time
Implement retry logic for transient errors (5xx responses) with exponential backoff
Maximum payload size: 1MB per request
Rate limit: 20 requests per minute
Use compression for large payloads when possible
Schedule regular syncs to keep your data fresh in Enterpret
Security
Protect your API key - Treat it like a password
Use HTTPS for all requests to ensure encryption
Audit data before sending to ensure no sensitive information is included
Consider IP restrictions for your API access if available
Getting Help
If you encounter any issues implementing your webhook integration:
Check error messages for specific guidance on what needs to be fixed
Review this documentation to ensure your implementation follows the requirements
Contact Enterpret Support with your referenceID if you need additional assistance
Support Channels:
Help Center: helpcenter.enterpret.com
Email: [email protected]
Dashboard: Use the chat widget in your dashboard