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
Hard Limits (Enforced):
Maximum: 100 requests per minute (RPM)
Maximum payload size: 1MB per request
Recommended: Stay below 20 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",
"createdAt": 1768913221,
"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:
{
"type": "REVIEW",
"createdAt": 1716460800,
"text": "This product works exactly as described. Very happy with my purchase!",
"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
questionfieldThe
answerandselectedOptionsfields are optional
Example:
{
"records": [
{
"id": "survey-456",
"fileID": "nps-survey",
"type": "SURVEY",
"createdAt": 1768913221,
"surveyResponse": {
"responses": [
{
"question": "How likely are you to recommend our product to a colleague?",
"answer": [
"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
textandactorfieldsActor must be one of: "user", "agent", or "bot"
Example:
{
"records": [
{
"id": "01JY05BQ6EV1RPSXJ61K0BV0YA",
"type": "CONVERSATION",
"fileID": "proto_chat",
"createdAt": 1768913221,
"conversation": {
"msgs": [
{
"actor": "bot",
"text": "Hello boom504!"
},
{
"actor": "bot",
"text": "Hello boom504!"
}
]
},
"metadata": {
"metadata": {
"src_account_id": {
"array": {
"s": [
"TybFPBMTLnY96T5nQ"
]
}
},
"website": {
"array": {
"s": [
"SportsBet"
]
}
},
"primary_product": {
"array": {
"s": [
"Cross Sell"
]
}
},
"tech": {
"array": {
"s": [
"Web"
]
}
},
"channel": {
"array": {
"s": [
"Desktop"
]
}
},
"value_segment": {
"array": {
"s": [
"High Value 1"
]
}
},
"active_segment": {
"array": {
"s": [
"Active High"
]
}
},
"sportsbook_ccf": {
"array": {
"s": [
"CCF 0.1"
]
}
},
"vip": {
"array": {
"s": [
"1"
]
}
},
"scrubbed": {
"array": {
"s": [
"0"
]
}
},
"first_deposit_date": {
"array": {
"s": [
"2022-11-13T00:00:00.000Z"
]
}
},
"last_active_date": {
"array": {
"s": [
"2025-06-18T00:00:00.000Z"
]
}
},
"bot_id": {
"array": {
"s": [
"01J0685Q1AYVRTHSKRSA289MKC"
]
}
},
"bot_name": {
"array": {
"s": [
"Sportsbet.io"
]
}
},
"language": {
"array": {
"s": [
"English"
]
}
}
}
}
}
]
}AUDIO_RECORDING Type
Use for voice recordings from call centers, sales calls, or other audio feedback.
Required fields:
audioRecording: Contains theaudioURLfieldaudioURLshould 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": 1768913221,
"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": 1768913221,
"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": [
"value1",
"value2"
]
}
}
}
}
}
Supported Metadata TypesStrings: Use "s" as the type indicator for strings
"user_tier": { "array": { "s": ["Premium"] } }Numbers: Use "n" as the type indicator for number [int, float]
"rating": { "array": { "n": [4.5] } }Booleans: Use "b" as the type indicator for bool
"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. If you send a single values we will treat it as a single value like a key-value pair.
Data Mutability & Updating Records
What is Data Mutability?
Data mutability defines how Enterpret handles incoming records that share the same id.
When enabled
Sending a record with an existing id will update the original record instead of creating a duplicate. This is useful when you need to:
Update feedback content (for example, when a user edits a review in the source system)
Add or enrich metadata over time
Correct mistakes in previously ingested records
When disabled (default)
Records with duplicate ids are automatically skipped to prevent duplication. This is ideal for one-time or historical data imports where records should remain immutable.
How to Check if Data Mutability Is Enabled
Data mutability is configured per integration and must be enabled by Enterpret support.
To check whether it’s enabled for your integration:
Contact your Customer Success Manager (CSM) or Enterpret Support
Share your integration name or API key
The team will confirm your current data mutability setting
Note: Data mutability is disabled by default for new webhook integrations and must be explicitly enabled.
How to Update Existing Records
Once data mutability is enabled, you can update a record by sending the same id with the updated fields.
Example: Updating a Review
{
"records": [
{
"id": "review-123",
"fileID": "appstore-reviews",
"type": "REVIEW",
"createdAt": 1768913221,
"text": "Updated review text after customer edited their review",
"metadata": {
"metadata": {
"rating": { "array": { "n": [5] } },
"updated_at": { "array": { "n": [1716500000] } }
}
}
}
]
}
Example: Adding Metadata to an Existing Record
{
"records": [
{
"id": "review-123",
"fileID": "appstore-reviews",
"type": "REVIEW",
"createdAt": 1716460800,
"text": "Original review text",
"metadata": {
"metadata": {
"rating": { "array": { "n": [5] } },
"user_tier": { "array": { "s": ["Premium"] } },
"lifetime_value": { "array": { "n": [50000] } }
}
}
}
]
}
Important Considerations
ID Consistency: Always use the same `id` format when updating records. The ID must match exactly (case-sensitive) because it's used to generate a deterministic UUID for record identification.
Metadata Updates: When updating metadata, the entire metadata attribute is replaced, not merged. If you want to add a new metadata field while keeping existing ones, you must include all existing metadata fields in your update request along with the new field.
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 20) |
| 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: creating 3 sample reviews
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)
]
# 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.text)
Example: Extracting Data from Your Database
Example: Extracting Data From our 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.text)
# 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:
Enterpret Custom Webhook Example_curl.ipynb
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:
Python Implementation Script
Best for: Production integrations and Python development teams
This script 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
Error handling and retry logic
Download Python Implementation Script and Sample Payload:
Script - Script_for_sending_records_to_enterpret.py
Sample Payload - sample_payload.json
python3 Script_for_sending_records_to_enterpret.py --payload sample_payload.json
Best Practices
Data Placement Guide: Feedback Content vs Metadata
Place data in the correct fields so Enterpret can analyze feedback and use metadata for filtering and context.
Feedback content fields (what customers said)
Use these for the actual customer feedback text:
text (REVIEW type) — the review text
conversation.msgs[].text (CONVERSATION type) — message content
surveyResponse.responses[].answer (SURVEY type) — open-ended answers
surveyResponse.responses[].selectedOptions (SURVEY type) — selected options
Metadata fields (context about the feedback)
Use metadata for structured, contextual information:
Ratings, scores (NPS, CSAT, star ratings)
Demographics (country, region, language)
Customer attributes (tier, segment, account ID)
Transactional data (order ID, product ID, ticket ID)
Timestamps and statuses
Platform/device information
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
Right position for feedback vs metadta: Please keep the information like customer rating, nps score, country etc in the metadta and customer text feedback in the actual Conversati like text in review, survery wquestion ans.
Performance
Batch requests: Send multiple records per request instead of one at a time (up to 20 records per batch).
Retry on transient failures: Implement retry logic for 5xx errors using exponential backoff.
Use compression: Enable request compression for larger payloads when possible.
Schedule regular syncs: Run periodic syncs to keep your data up to date in Enterpret.
Delay between two request: To avoid failure please keep 1-2 sec gap between the consecutive requests.
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


