Reporting & Discovery API
Overview
With the Reporting & Discovery API, you can list and search the profiles that Dux-Soup- or STACKED-powered by Dux-Soup has visited and recorded. You can also determine which profiles are active in a Campaign, track how far they have progressed, and identify which actions and parameters are valid when building a Campaign.
For instance, you can pull every profile visited within the last 10 days into your CRM, or feed a Campaign’s progress into a weekly dashboard.
The Reporting & Discovery API endpoints are GET requests.
All Reporting & Discovery API calls are made against your Remote Control endpoint:
https://app.dux-soup.com/xapi/remote/control/{{USERID}}/...
Required fields
All Dux-Soup API requests must include a signed X-Dux-Signature header. Because every call on this page is a GET request, no HTTP body is sent; options are passed as query parameters in the URL instead. For comprehensive guidance on obtaining the Authentication Key and calculating the signature, please refer to Connecting to and Authenticating API calls.
| Field | Description |
|---|---|
X-Dux-Signature (header) |
HMAC signature calculated from your Authentication Key |
targeturl |
The target URL of the command (should start with https://app.dux-soup.com ) |
userid |
The userid the command is sent to; should match the userid in the target URL |
timestamp |
Current Unix time in milliseconds; must be within 5 minutes of the current time |
You can generate
curlcommands or execute calls directly at https://app.dux-soup.com/web/rc/test - the easiest way to try any endpoint on this page.
List / Search Contacts
Returns the profile data Dux-Soup has viewed and recorded on the account. Use it to list recently visited profiles, look up a single profile by its Dux-Soup ID, or narrow the results to one Campaign.
URL: https://app.dux-soup.com/xapi/remote/control/{{USERID}}/contacts
HTTP method: GET
Query parameters
| Parameter | Description |
|---|---|
campaignid |
Campaign ID to return contacts for (optional, String). If omitted, the default Campaign is used. |
search |
Search term, e.g. a Dux-Soup internal profile ID such as id.548182024 (optional, String) |
daysback |
Only return profiles recorded within this many days (optional, Number) |
Example requests
List all contacts recorded in the last 10 days in the default Campaign:
curl -v -XGET -H 'X-Dux-Signature: {{SIGNATURE}}' -H 'Content-type: application/json' 'https://app.dux-soup.com/xapi/remote/control/{{USERID}}/contacts?campaignid=default&daysback=10'
Search for a single profile in the default Campaign:
curl -v -XGET -H 'X-Dux-Signature: {{SIGNATURE}}' -H 'Content-type: application/json' 'https://app.dux-soup.com/xapi/remote/control/{{USERID}}/contacts?campaignid=default&search=id.548182024&daysback=10'
Search for the same profile in another Campaign:
curl -v -XGET -H 'X-Dux-Signature: {{SIGNATURE}}' -H 'Content-type: application/json' 'https://app.dux-soup.com/xapi/remote/control/{{USERID}}/contacts?campaignid=new-july&search=id.548182024&daysback=10'
Example response (shortened to a single item)
{
"success": true,
"data": {
"total": 733,
"items": [
{
"id": "id.548182024",
"userid": "{{USERID}}",
"when": "2026-07-08T08:46:57.899Z",
"Profile": "https://www.linkedin.com/in/gin-kuz/",
"SalesProfile": "https://www.linkedin.com/sales/people/ACoAACCsmAgBQqkYHSceXPeYMXRFjF6fN-b1z8w",
"RecruiterProfile": "https://www.linkedin.com/talent/profile/ACoAACCsmAgBQqkYHSceXPeYMXRFjF6fN-b1z8w",
"Degree": "1",
"First_Name": "Gintarė",
"Last_Name": "Kuzminskaitė",
"Connections": "2432",
"Summary": "Business Consultant with a demonstrated history of working in the IT and Services industries...",
"Title": "Client Manager",
"From": "2023",
"Company": "Dux-Soup",
"CompanyProfile": "https://www.linkedin.com/company/71973555/",
"CompanyWebsite": "https://www.dux-soup.com",
"Email": null,
"Phone": null,
"Twitter": "LGLondon",
"Location": "Christchurch, Canterbury, New Zealand",
"Industry": "Financial Services",
"My_Tags": [
"🦆-1st-degree-june-enrolled",
"🦆-1st-degree-june-accepted",
"🦆-1st-degree-june-responded",
"🦆-default-enrolled"
],
"My_Notes": "",
"campaignid": "default",
"Picture": "https://media.licdn.com/dms/image/v2/..."
}
]
}
}
data.total is the number of matching contacts, and data.items holds one object per profile.
Contact object attributes
| Field | Description |
|---|---|
id |
Dux-Soup internal profile ID - use it with search, or when enrolling a profile via the Campaign Management API |
when |
Date and time the profile was last recorded (ISO 8601) |
Profile, SalesProfile, RecruiterProfile |
Profile URLs on regular LinkedIn, Sales Navigator, and Recruiter |
Degree |
Connection degree relative to the account, e.g., "1" , "2" , "3" |
First_Name , Middle_Name , Last_Name |
Name fields as shown on LinkedIn |
Connections |
Number of LinkedIn connections |
Summary |
Profile "About" text |
Title, From, Company |
Current position, start year, and employer |
CompanyProfile, CompanyWebsite |
Company LinkedIn page and website |
Email , Phone , Twitter |
Contact details, where available (null if not) |
Location, Industry |
Location and industry as shown on LinkedIn |
My_Tags |
All tags on the profile, including Dux-Soup system tags (see Get Campaign Stats below) |
My_Notes |
Your notes on the profile |
campaignid |
The Campaign the result was returned for |
Picture |
Profile picture URL |
Fields that LinkedIn doesn't provide for a profile are left out of its object entirely (for example
Summary,Picture), so don't assume every attribute is always present.
Get Campaign Stats
Returns the profiles taking part in a Drip Campaign within a date range, together with the system tags that show how far each one has progressed. This is the starting point for Campaign analysis - for example, counting how many profiles were invited, accepted, or responded since a given date.
URL: https://app.dux-soup.com/xapi/remote/control/{{USERID}}/campaign/{{CAMPAIGNID}}/stats
HTTP method: GET
Query parameters:
| Parameter | Description |
|---|---|
rangetype |
Type of date range, e.g. custom (String) |
fromdate |
Start of the range as an ISO 8601 date-time, URL-encoded, e.g. 2026-04-09T09%3A01%3A28.973Z (String). Used with rangetype=custom . |
idonly |
Set to true to return only profile IDs instead of full profile details (optional, Boolean) |
Example request
curl -v -XGET -H 'X-Dux-Signature: {{SIGNATURE}}' -H 'Content-type: application/json' 'https://app.dux-soup.com/xapi/remote/control/{{USERID}}/campaign/default/stats?rangetype=custom&fromdate=2026-04-09T09%3A01%3A28.973Z'
Example response (shortened)
{
"success": true,
"data": {
"success": true,
"data": {
"fromtimestamp": "2026-06-26T12:42:13.116Z",
"totimestamp": "2026-07-06T12:42:13.233Z",
"timestamp": "2026-07-06T12:42:13.268Z",
"campaignid": "default",
"range": "custom",
"profiles": [
{
"tags": ["🦆-default-enrolled", "🦆-default-invited", "🦆-default-accepted"],
"userid": "{{USERID}}",
"id": "id.548182024",
"First_Name": "Gintarė",
"Last_Name": "Kuzminskaitė",
"Profile": "https://www.linkedin.com/in/gin-kuz/",
"SalesProfile": "https://www.linkedin.com/sales/people/ACoAACCsmAgBQqkYHSceXPeYMXRFjF6fN-b1z8w",
"Company": "Dux-Soup",
"Title": "Client Manager",
"Location": "Christchurch, Canterbury, New Zealand",
"Industry": "Financial Services",
"url": "https://www.linkedin.com/in/gin-kuz/",
"name": "Gintarė Kuzminskaitė"
}
]
}
}
}
fromtimestamp and totimestamp show the range the stats cover, and profiles holds one entry per profile active in the Campaign during that range. Note that the result is wrapped in two success/data levels.
Reading the tags
Each profile's tags array holds the system tags that are applied as a profile moves through the Campaign, in the form 🦆-{{CAMPAIGNID}}-{{STAGE}}. Counting profiles per tag gives you the Campaign funnel.
| Tag | Meaning |
|---|---|
🦆-{{CAMPAIGNID}}-enrolled |
Profile was enrolled in the Campaign |
🦆-{{CAMPAIGNID}}-invited |
Connection request was sent |
🦆-{{CAMPAIGNID}}-accepted |
Connection request was accepted |
🦆-{{CAMPAIGNID}}-responded |
Profile replied on LinkedIn; the Campaign sequence is paused for them |
🦆-{{CAMPAIGNID}}-qualified-in |
Profile was qualified in (Funnel's Qualified section) |
🦆-{{CAMPAIGNID}}-qualified-out |
Profile was qualified out (Funnel's Bin section) |
Add
idonly=trueto the URL when you only need to know which profiles are in a Campaign - for example, to match them against records in your CRM. The response then returns profile IDs only, which is much lighter for large Campaigns.
Get Campaign Schema
Returns the building blocks of a Campaign: which action types exist, which LinkedIn targets they can run on, which parameters each action takes, and the character limits for each. It's mainly used by AI assistants connected through MCP, so they can build valid Campaigns on their own - but it's just as useful when you're developing sequences yourself and want to check a campaign object.
URL: https://app.dux-soup.com/xapi/remote/control/{{USERID}}/campaignschema
HTTP method: GET
Example request
curl -v -XGET -H 'X-Dux-Signature: {{SIGNATURE}}' -H 'Content-type: application/json' 'https://app.dux-soup.com/xapi/remote/control/{{USERID}}/campaignschema'
Example response
{
"success": true,
"data": {
"actionTypes": ["visit", "inmail", "follow", "connect", "message", "endorse", "likepost", "disconnect"],
"targets": ["regular", "salesnav", "recruiter"],
"actionMeta": {
"visit": { "params": [] },
"inmail": { "params": ["subject", "text"], "maxSubject": 200, "maxText": 1900 },
"follow": { "params": [] },
"connect": { "params": ["text"], "maxText": 300 },
"message": { "params": ["text"], "maxText": 7900 },
"endorse": { "params": ["skills"], "skillRange": [-3, 3] },
"likepost": { "params": [] },
"disconnect": { "params": [] }
},
"targetSummaries": {
"regular": "Standard LinkedIn. inmail/follow are pre-connect only; after connect: message/endorse/visit/likepost.",
"salesnav": "Sales Navigator. Same ordering as regular.",
"recruiter": "Recruiter. inmail allowed pre- and post-connect."
}
}
}
Action types at a glance
| Action type | Parameters | Limits |
|---|---|---|
visit |
none | - |
inmail |
subject , text |
Subject up to 200 characters, text up to 1,900 characters |
follow |
none | - |
connect |
text (connection note) |
Up to 300 characters |
message |
text |
Up to 7,900 characters |
endorse |
skills |
Value between -3 and 3 (skillRange ) |
likepost |
none | - |
disconnect |
none | - |
Targets
- regular - standard LinkedIn.
inmailandfollowcan only run before the profile is connected; afterconnect, usemessage,endorse,visit, andlikepost. - salesnav - Sales Navigator; same action ordering as
regular. - recruiter - Recruiter;
inmailis allowed both before and after the profile is connected.