Skip to main content

Report Creation Pipeline

This guide provides a detailed explanation of each step in the report creation process, including all available options and edge cases.

Pipeline Overview​

Step 1: Create Report​

Search by Username​

The most common method - search for a specific social media account:

POST /create
{
"source": "ig",
"username": "username_to_search"
}

Available sources:

SourcePlatformNotes
igInstagramMost comprehensive data
twTwitterGood for public figures
fbFacebookLimited to public profiles
ttTikTokGrowing coverage
liLinkedInProfessional profiles

Search by Name (US Only)​

Search by person's name and state:

POST /create
{
"name": "John Smith",
"state": "CA"
}

This searches across all social networks to find matching profiles.

Response​

{
"id": "68af01be012b843fd7bc2bf4"
}

The report ID is a 24-character string. Save it for all subsequent calls.

Step 2: Get Search Results​

Get All Sources​

GET /create/{reportId}

Returns profiles from all social networks at once.

Get Specific Source​

GET /create/{reportId}/{source}?limit=20&offset=0

Paginated results for a specific source.

Search Within Source​

If the profile wasn't found, search directly:

POST /create/{reportId}/{source}/search
{
"username": "exact_username"
}

Profile Status​

Each profile can have a badReason indicating why it can't be analyzed:

ReasonDescription
privateProfile is private
notFoundProfile doesn't exist
zeroFollowsProfile follows no one
optOutUser requested data removal
unloadedData not yet loaded
unmappedProfile could not be mapped
unexpectedUnexpected failure

Step 3: Add Profiles​

Add profiles one by one to your report:

POST /create/{reportId}/{source}/add
{
"id": "profile_id"
}

Response​

{
"added": true,
"unloaded": false,
"status": {
"type": "follows",
"status": "inited",
"id": "profile_id",
"source": "ig"
}
}

Status Values​

  • inited - Profile queued for loading
  • inprogress - Loading in progress
  • done - Data loaded successfully
  • error - Loading failed

Adding Multiple Sources​

You can add profiles from multiple sources to a single report:

# Add Instagram profile
POST /create/{reportId}/ig/add
{"id": "ig_profile_id"}

# Add Twitter profile
POST /create/{reportId}/tw/add
{"id": "tw_profile_id"}

Step 4: Confirm Selection​

Lock in your profile selection and start data loading:

POST /create/{reportId}/confirm
[
{"source": "ig", "id": "ig_profile_id"},
{"source": "tw", "id": "tw_profile_id"}
]

Response​

{
"estimatedTime": 30000,
"loadTimeout": 60000
}
  • estimatedTime - Milliseconds until data ready (0 = already loaded)
  • loadTimeout - Maximum wait time

Important Notes​

  • You cannot modify the report after confirmation
  • Confirming does not itself consume a report credit — the credit gate is checked when you first create the report (POST /create returns 402 if you have none, see below); the credit is actually deducted the first time you view the finished report (GET /report/{reportId}), transparently, with no separate confirmation step
  • Repeating POST /create/{reportId}/confirm on a report you already confirmed returns 409 with "report profiles were already confirmed" — the earlier profile selection was already locked in and is left untouched
  • If estimatedTime > 0, wait before fetching the report
  • Confirm requires a signed-in account: it returns 401 for a guest session with no user ID, even though the earlier steps work for guests too

Step 5: Monitor Progress​

Check Status​

GET /check/{reportId}
{
"generated": true,
"ready": true,
"inProgress": false
}

GET /check/{reportId} returns 404 (not 403) when the caller does not own the report — this avoids confirming that a given report ID exists to someone who isn't allowed to see it.

Real-time Updates (SSE)​

Connect to SSE for live updates:

GET /sse/{reportId}

See Real-time Updates Guide for details.

Step 6: Get Report​

Report page (slim — default)​

GET /report/{reportId}

Returns ReportPage: per-source rows, previews, merged highlights rollup. Not the full monolithic per-profile payload (see /full below).

Full interest categories (lazy-loaded detail)​

GET /report/{reportId}/interests
# Optional: one network only
GET /report/{reportId}/interests?source=ig

Full report shape (monolithic JSON)​

GET /report/{reportId}/full

Returns the full ReportItem list per profile (and optional embedded summary). Prefer GET /report/{reportId} for the slim page and GET /report/{reportId}/summary for summary-only.

Report for Specific Source​

GET /report/{reportId}/{source}

Sorting Options​

GET /report/{reportId}?sortByRedFlags=true&limit=50

Additional Data Endpoints​

Friends List (unified)​

GET /report/{reportId}/friends?limit=20&offset=0

Friends List (per source)​

GET /report/{reportId}/friends/{source}?limit=20&offset=0

Common Interests with Friend​

GET /report/{reportId}/{source}/common/{friendId}

Interest Details​

GET /report/{reportId}/{source}/{interestId}

Profiles by Interest​

GET /report/{reportId}/{source}/{interestId}/profiles

Interest Changes Over Time​

GET /report/{reportId}/{source}/diffs?date=2024-01&type=new

AI Summary​

GET /report/{reportId}/summary

Error Handling​

Repeat Confirm​

{
"code": 409,
"message": "report profiles were already confirmed"
}

POST /create/{reportId}/confirm on a report you already confirmed returns 409. A separate 403 "report was already generated" can come from other endpoints in this flow (e.g. GET /create/{reportId} once the report has moved past the search-and-select stage) — it means the report can no longer be edited, distinct from the 409 above.

Report Limit Exceeded​

{
"code": 402,
"message": "to continue please upgrade your subscription"
}

POST /create (not confirm) returns 402 when you have no remaining report credits. An unauthenticated caller instead gets "You have reached search limit. Please Sign up to continue.".

Profile Not Found​

{
"code": 404,
"message": "Profile not found"
}

The specified profile ID doesn't exist in the search results.

Best Practices​

  1. Cache the token - Don't authenticate on every request
  2. Use SSE for real-time updates - More efficient than polling
  3. Handle partial results - Some profiles may fail to load
  4. Store report IDs - Reports can be retrieved later without re-creation