Getting Started
The Enttor API lets you programmatically list team members, upload leads, and create DM campaigns across X (Twitter), Instagram, and LinkedIn.
All requests must include a valid API key via the Authorization header. Responses are JSON and follow a consistent envelope format.
Authentication
API keys are managed from the Settings → API Keys section of your Enttor dashboard. Each key is prefixed with ent_ and is shown only once at creation time.
Include the key in every request as a Bearer token:
curl -X GET https://www.enttor.ai/api/v1/users \
-H "Authorization: Bearer ent_your_api_key_here" \
-H "Content-Type: application/json"Key Scopes
Each key can be granted specific scopes that restrict what it can access:
| Field | Type | Required | Description |
|---|---|---|---|
| leads:write | scope | No | Upload leads to prospect groups |
| campaigns:write | scope | No | Create DM campaigns |
| users:read | scope | No | List team members |
By default, newly created keys include all three scopes. You can restrict scopes when creating a key via the dashboard or the key creation endpoint.
List Users
/api/v1/users
Retrieve all team members in your company. Use this to get valid user_ids for campaign distribution.
Example Response 200
{
"success": true,
"data": {
"company_id": "1c5028af-0825-4fcc-97d5-991243aa38ff",
"users": [
{
"id": 1037,
"name": "Kevin Gamez",
"email": "kgamez@enttor.ai"
},
{
"id": 1001,
"name": "Zinnie Zhang",
"email": "zzhang@enttor.ai"
},
{
"id": 1036,
"name": "Sameer",
"email": "ssomani@enttor.ai"
}
]
}
}Upload Leads
/api/v1/leads
Upload a batch of leads into a new prospect group. Leads are processed in batches internally so there is no per-request cap.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| group_name | string | Yes | Name for the prospect group |
| platform | string | Yes | "x", "instagram", or "linkedin" |
| leads | array | Yes | Array of lead objects |
| user_id | number | No | Account ID to assign leads to (from List Users). If omitted, leads are unassigned. |
Lead Object Fields
Common (all platforms)
| Field | Type | Required | Description |
|---|---|---|---|
| username | string | Yes | Platform username / handle |
| profile_url | string | No | Full URL to the profile |
| followers | number | No | Follower count |
X (Twitter) additional fields
| Field | Type | Required | Description |
|---|---|---|---|
| company | string | No | Company name |
| company_description | string | No | Company description |
| job_title | string | No | Job title |
| location | string | No | Geographic location |
Instagram additional fields
| Field | Type | Required | Description |
|---|---|---|---|
| contact_info | string | No | Contact info from bio |
| content_pillars | array | No | Content categories |
| user_info | object | No | Additional user metadata |
LinkedIn additional fields
| Field | Type | Required | Description |
|---|---|---|---|
| full_name | string | No | Full display name |
| headline | string | No | LinkedIn headline |
| job_title | string | No | Job title |
| company | string | No | Company name |
| location | string | No | Geographic location |
Example Request
{
"group_name": "Video editors",
"platform": "instagram",
"leads": [
{
"username": "garyvee",
"profile_url": "https://instagram.com/garyvee",
"followers": 10200000,
"contact_info": "team@vaynermedia.com",
"content_pillars": ["entrepreneurship", "marketing"]
},
{
"username": "hormozi",
"profile_url": "https://instagram.com/hormozi",
"followers": 3100000
}
]
}Example Response 201
{
"success": true,
"data": {
"dataset_id": "316",
"group_name": "Video editors",
"platform": "instagram",
"leads_inserted": 2,
"leads_skipped": 0
}
}List Datasets
/api/v1/datasets
Retrieve all prospect datasets (groups) belonging to your company. Use the returned id as dataset_id when creating campaigns.
Example Response 200
{
"success": true,
"data": {
"company_id": "1c5028af-0825-4fcc-97d5-991243aa38ff",
"datasets": [
{
"id": "317",
"user_id": 1001,
"name": "robinhoodapp",
"platform": "Instagram",
"source": "platform",
"status": "completed",
"lead_count": "350",
"created_at": "2026-02-06T12:50:12.205Z"
},
{
"id": "313",
"user_id": 1037,
"name": "SaaS Founders",
"platform": "X (Twitter)",
"source": "api",
"status": "completed",
"lead_count": "2500",
"created_at": "2026-02-04T09:15:22.100Z"
}
]
}
}Create Campaign
/api/v1/campaigns
Create one or more DM campaigns targeting a previously uploaded prospect group. Pass user_ids to distribute leads across multiple team members. The start_date must be at least 10 minutes in the future.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| dataset_id | string | Yes | ID of the prospect group (from Upload Leads response) |
| campaign_name | string | Yes | Name for the campaign |
| platform | string | Yes | "x", "instagram", or "linkedin" |
| message_sequence | string | Yes | Message template to send to each prospect |
| start_date | string (ISO 8601) | Yes | Campaign start date (min 10 min from now) |
| end_date | string (ISO 8601) | Yes | Campaign end date |
| user_ids | array | Yes | Array of account IDs to distribute leads across (from List Users) |
| daily_message_limit | number | No | Max messages per day per campaign. Defaults: instagram=50, x=200, linkedin=20 |
Example Request
{
"dataset_id": "317",
"campaign_name": "Robinhood Followers Outreach",
"platform": "instagram",
"message_sequence": "Hey {{username}}, love your content! We help creators automate their outreach — would love to show you how Enttor works.",
"start_date": "2026-03-01T00:00:00Z",
"end_date": "2026-03-31T23:59:59Z",
"user_ids": [1037, 1001],
"daily_message_limit": 40
}Example Response 201
{
"success": true,
"data": {
"campaigns": [
{ "campaign_id": 187, "user_id": 1037, "audience_size": 175 },
{ "campaign_id": 188, "user_id": 1001, "audience_size": 175 }
],
"campaign_name": "Robinhood Followers Outreach",
"status": "scheduled",
"dataset_id": "317",
"total_audience": 350
}
}Leads are distributed evenly across the provided user_ids. If the total is not perfectly divisible, the first user(s) receive one extra lead each.
Error Handling
All error responses follow a consistent format. The success field will be false and the error object contains a machine-readable code and a human-readable message.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "group_name is required"
}
}Error Codes
| Code | HTTP Status | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid API key |
| FORBIDDEN | 403 | API key lacks the required scope |
| VALIDATION_ERROR | 400 | Request body failed validation |
| NOT_FOUND | 404 | Resource does not exist or is not owned by your account |
| RATE_LIMITED | 429 | Too many requests — try again later |
| INTERNAL_ERROR | 500 | Unexpected server error |
Enttor API v1 — Questions? Contact us at kgamez@enttor.ai
