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 curl  commands 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 , Twitter  or 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=true  to 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. inmail and follow can only run before the profile is connected; after connect, use message, endorse, visit, and likepost.
  • salesnav - Sales Navigator; same action ordering as regular.
  • recruiter - Recruiter; inmail is allowed both before and after the profile is connected.