Skip to main content
Sifa Docs

Show Sifa profiles in your app

Read a person's professional headline, current role, employer, and skills from their Sifa profile, and render it in your own app. Public data, no Sifa account, no API key.

If you build on the Atmosphere, you can show a person's professional facts (their current role, their employer, the skills they list) right where it's useful: a maintainer on a package page, a developer on a git forge, a contributor in a byline. The data is public and portable, so you read it directly. There's no Sifa account to create, no API key to request, and nothing to ask permission for.

There are three ways in, from least to most work. Pick the one that fits your stack.

Option 1: call the profile query

Sifa's AppView exposes an XRPC query that returns the aggregated public profile. Call it from your server with a handle or a DID:

curl "https://api.sifa.id/xrpc/id.sifa.getProfileView?actor=gui.do"

The response is JSON. The fields most apps want:

{
  "did": "did:plc:45uheisi25szrjvjurfpritx",
  "handle": "gui.do",
  "displayName": "Guido Jansen",
  "headline": "Founder at Singi Labs",
  "positions": [
    {
      "title": "Founder",
      "company": "Singi Labs",
      "entityName": "Singi Labs",
      "startedAt": "2025-11"
    }
  ],
  "skills": [{ "name": "Product" }, { "name": "AT Protocol" }],
  "education": [{ "institution": "…", "degree": "…" }]
}

A position with no endedAt is a current role. When a position is linked to a company page, entityName is the resolved name; otherwise company is the free-text value the person typed. The query needs no authentication. It returns the same public projection a logged-out visitor sees, so hidden items are already omitted.

The full field list is defined by the id.sifa.getProfileView lexicon in singi-labs/sifa-lexicons.

Option 2: use the SDK

If your app is TypeScript, the @singi-labs/sifa-sdk does the fetching and typing for you, and gives you a compact summary when you only want the headline facts.

pnpm add @singi-labs/sifa-sdk
import { fetchProfileSummary } from '@singi-labs/sifa-sdk/query'

const summary = await fetchProfileSummary({ baseUrl: 'https://api.sifa.id' }, 'gui.do')
// {
//   handle: 'gui.do',
//   displayName: 'Guido Jansen',
//   headline: 'Founder at Singi Labs',
//   currentTitle: 'Founder',
//   currentCompany: 'Singi Labs',
//   topSkills: ['Product', 'AT Protocol'],
//   claimed: true,
// }

fetchProfileSummary returns null when there's no profile for that actor, so a missing profile is easy to handle. currentTitle and currentCompany come from the same "primary position" rule the profile page uses, so your summary matches what the person sees on their own profile. Call it from your server, the same as option 1.

If you want the whole profile instead of the summary, use fetchGetProfileView, which returns the full typed ProfileView.

Option 3: read straight from the PDS

The most decentralized path skips Sifa entirely. Every id.sifa.* record lives in the person's own Personal Data Server, and those records are public. Resolve their handle to a DID, resolve the DID to its PDS host, then read the collections you want:

# id.sifa.profile.self holds the headline and core fields
curl "https://<their-pds>/xrpc/com.atproto.repo.getRecord?repo=<did>&collection=id.sifa.profile.self&rkey=self"

# positions, skills, and education are one collection each
curl "https://<their-pds>/xrpc/com.atproto.repo.listRecords?repo=<did>&collection=id.sifa.profile.position"

This is the same mechanism generic record browsers like pdsls.dev use. The trade-off: you get the raw records exactly as written, so you handle company-page resolution, formatting, and the skill-to-position links yourself. Options 1 and 2 do that work for you. Reach for this one when you specifically want zero dependency on Sifa's AppView. See Apps, AppViews, and the firehose for how PDS reads fit the wider picture.

Be a good neighbour

  • Cache. A person's role doesn't change by the second. Cache reads for a minute or so rather than fetching on every page view, and read server-side rather than from every visitor's browser.
  • Expect change. Records can be edited or deleted at any time. Treat a 404 as "no data right now", not an error, and don't hard-fail a page over a missing profile.
  • Attribute. When you show Sifa data, link back to the person's Sifa profile page (their /p/{handle} page). That way a visitor has easy access to the full picture and the owner has an easy path to update anything if needed.

Tell us what you built

If your app reads id.sifa.* records, open an issue and we'll list it on Lexicons and integrations. Seeing the same profile show up across apps, owned by the person and not by any one platform, is the entire point.

On this page