API reference

Sourced profiles

Candidates your customer went out and found, rather than ones who applied. Same shape of person, very different consent footing — and the payload says so on every row.

GET/sourced-profilessourced_profiles:read

ParameterTypeNotes
originstringWhere the profile came from: coresignal, xray, import or github.
has_contact_infobooleanOnly profiles that do (or do not) have contact data held against them. Cheap way to avoid hydrating rows that have nothing to hydrate.
qstringSearch by name, title or company.
updated_afterRFC 3339For incremental sync.
limitintegerDefault 25, max 100.
cursorstringFrom the previous page.
Response
{
  "object": "list",
  "data": [
    {
      "object": "sourced_profile",
      "id": "cnd_8Fj3kLm2Qd7s",
      "workspace_id": "wsp_4Kd8sPm2Qx7L",
      "full_name": "Minjae Park",
      "headline": "Staff Engineer, Payments",
      "job_title": "Staff Software Engineer",
      "company_name": "Toss",
      "company_industry": "Financial Services",
      "company_website": "https://toss.im",
      "company_linkedin_url": "https://www.linkedin.com/company/viva-republica",
      "department": "Engineering",
      "management_level": "individual_contributor",
      "location_full": "Seoul, South Korea",
      "location_country": "KR",
      "linkedin_url": "https://www.linkedin.com/in/minjae-park-9x8y7z",
      "photo_url": null,
      "summary": "Twelve years building payment infrastructure ...",
      "total_experience_months": 148,
      "connections_count": 1840,
      "follower_count": 2210,
      "match_score": 91,
      "match_tier": "strong",
      "created_at": "2026-08-19T07:41:02.115Z",
      "updated_at": "2026-09-06T12:08:55.400Z",
      "has_contact_info": true,
      "has_resume": false,
      "has_business_card": false,
      "has_profile_photo": true,
      "has_linkedin_capture": true,
      "provenance": {
        "origin": "sourced",
        "acquisition": "provider_search",
        "provider": "coresignal",
        "owner_workspace_id": "wsp_4Kd8sPm2Qx7L",
        "first_seen_at": "2026-08-19T07:41:02.115Z",
        "last_seen_at": "2026-09-06T12:08:55.400Z",
        "consent": {
          "basis": "legitimate_interest_sourcing",
          "candidate_facing_notice": false,
          "unsubscribed": false,
          "suppressed": false
        },
        "licence": {
          "redistributable": false,
          "note": "Provider-derived. Not licensed for onward redistribution."
        }
      },
      "links": {
        "self": "/api/partner/v1/sourced-profiles/cnd_8Fj3kLm2Qd7s",
        "contact_info": "/api/partner/v1/sourced-profiles/cnd_8Fj3kLm2Qd7s/contact-info",
        "attachments": "/api/partner/v1/sourced-profiles/cnd_8Fj3kLm2Qd7s/attachments",
        "list_memberships": "/api/partner/v1/sourced-profiles/cnd_8Fj3kLm2Qd7s/list-memberships"
      }
    }
  ],
  "has_more": true,
  "next_cursor": "cur_eyJrIjoiMjAyNi0wOC0xOVQwNzo0MTowMloi..."
}

match_score and match_tier are Tahoe’s assessment against the search that found this person, not a general quality rating. They are meaningless outside that context, so do not display one as a standalone score.

GET/sourced-profiles/{profile_handle}sourced_profiles:read

One profile, same shape as a list row.

GET/sourced-profiles/{profile_handle}/contact-infocontact:read

Only values this workspace has already revealed. This endpoint does not reveal anything new, does not call a provider, and does not spend your customer’s credits. If a field was never unlocked, it is reported as such rather than fetched on demand.

Response
{
  "object": "contact_info",
  "subject": { "object": "sourced_profile", "id": "cnd_8Fj3kLm2Qd7s" },
  "emails": [
    { "value": "[email protected]", "kind": "work", "status": "found" }
  ],
  "phones": [],
  "unsubscribed": false,
  "field_states": {
    "work_email": "found",
    "personal_email": "not_found",
    "phone": "not_found"
  }
}

Here phones is empty and phone is not_found with nothing in restricted — that means Tahoe genuinely does not hold a phone number, not that one is being withheld. Had the scope been missing, phones would have been named in restricted instead. The difference is the whole reason both fields exist.

Each disclosed value consumes one unit of the daily personal-data budget and writes an audit row naming your key, the record and the field. Hydrate contact details when someone is about to use them, not for every profile at sync time.

GET/sourced-profiles/{profile_handle}/attachmentsattachments:read

The index of files held against this profile — resume, business_card and profile_photo. Files whose own scope you lack are still listed, with readable: false and the scope named.

Response
{
  "object": "list",
  "data": [
    {
      "object": "attachment",
      "type": "profile_photo",
      "filename": "minjae.jpg",
      "mime": "image/jpeg",
      "bytes": 48120,
      "uploaded_at": "2026-08-19T07:41:04.882Z",
      "required_scope": "attachments:read",
      "readable": true,
      "links": {
        "content": "/api/partner/v1/sourced-profiles/cnd_8Fj3kLm2Qd7s/attachments/profile_photo/content"
      }
    },
    {
      "object": "attachment",
      "type": "resume",
      "filename": "minjae-park.pdf",
      "mime": "application/pdf",
      "bytes": 210444,
      "uploaded_at": "2026-08-21T10:02:19.301Z",
      "required_scope": "resume:download",
      "readable": false
    }
  ],
  "has_more": false,
  "next_cursor": null
}

The links.content key is present only when readable is true, so a client that follows links will never construct a request it is not allowed to make. Listing the unreadable entry anyway is deliberate: knowing a resume exists but needs another scope is more useful than the row silently vanishing.

GET/sourced-profiles/{profile_handle}/attachments/{kind}/contentattachments:read

Download one attachment. In the download rate-limit tier (30/minute). A resume needs resume:download as well — the attachment index tells you which scope each file wants in required_scope.

Request
curl -s "https://tahoe.workonward.com/api/partner/v1/sourced-profiles/cnd_8Fj3kLm2Qd7s/attachments/profile_photo/content" \
  -H "Authorization: Bearer $TAHOE_API_KEY"

GET/sourced-profiles/{profile_handle}/list-membershipslists:read

Which of the workspace’s candidate lists this profile is in, and what stage it sits at in each. This is the sourcing-side equivalent of an application’s pipeline stage — see projects and lists.

Related events

sourced_profile.created, sourced_profile.updated and sourced_profile.deleted need sourced_profiles:read. sourced_profile.contact_info_revealed needs contact:read and sourced_profile.attachment_added needs attachments:read.