Social Graph
Preview Base URL: https://socialgraph.stackwell.tech
Overview
Social Graph keeps the connections between people who use Stackwell apps, and lets an app read a person’s connections once that person approves it.
- You register a graph app with Social Graph.
- Your app sends the person to Social Graph’s approval page. They sign in with their ChirpAuth account and approve or deny your app.
- If they approve, your app exchanges the one-time code it gets back for an access token.
- With that token your app reads the person’s profile and connections, checks whether they are connected to someone, and finds which of their connections also use your app.
Your app cannot add or remove anyone’s connections. People appear
to your app under ids that belong to your app (psd_...).
It is for developers of apps that want to start from the people a user already knows, instead of asking them to rebuild their contacts.
What preview means here: Social Graph runs in production, and Stackwell’s own services use it. It is not yet open to outside developers:
- Registering a graph app needs a ChirpAuth developer account and a sign-in from Stackwell’s developer tool. Neither is open to outside developers yet, so there is no self-serve way to register an app.
- The Social Graph web app only signs people in, shows the approval page, makes invite links for a person to send themselves, and accepts them. There is no screen yet where a person can see their connections or the apps they have approved.
Concepts and Data and privacy mark the other gaps “Not yet”.
Quickstart
This walks one person through approving your app, and reads their connections.
1. Check that Social Graph is reachable
No credentials needed:
curl -fsS https://socialgraph.stackwell.tech/health
{"ok":true}
2. Register your app
Registration takes a ChirpAuth developer token (see Authentication), which outside developers cannot get yet. With one:
curl https://socialgraph.stackwell.tech/api/graph/apps \
-H "Authorization: Bearer $DEVELOPER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"displayName": "Acme Planner",
"description": "Plans events with your friends.",
"platform": "web",
"redirectUri": "https://acme.example/social-graph/callback"
}'
The response carries your clientId (graphapp-...), your clientSecret
(graphsecret-..., shown only once) and the app’s id. A new app is a
draft; nobody can approve it until you make it active:
curl https://socialgraph.stackwell.tech/api/graph/apps/$APP_ID/status \
-H "Authorization: Bearer $DEVELOPER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "active"}'
3. Send the person to the approval page
Make a random state, and a PKCE verifier and challenge (the challenge is the
base64url SHA-256 of the verifier, without padding):
VERIFIER=$(openssl rand -base64 48 | tr '+/' '-_' | tr -d '=\n')
CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=\n')
Send the person to:
https://socialgraph.stackwell.tech/graph/authorize?client_id=graphapp-ab6bd084821c471eaab9ef7f83b09bf9&redirect_uri=https%3A%2F%2Facme.example%2Fsocial-graph%2Fcallback&state=xyz&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
They sign in with ChirpAuth and see your app’s registered name, description, owner and redirect URI, and what it will be able to read. Their browser then returns to your redirect URI:
https://acme.example/social-graph/callback?code=graphcode-nl7_h3Yz90TH_jGjWAnhTz5DFuvra8oIjPG-GCrcjyE&state=xyz
or, if they deny, with ?error=access_denied&state=xyz. Check that state
is the one you sent.
4. Exchange the code for an access token
Within 5 minutes, from your server:
curl https://socialgraph.stackwell.tech/api/graph/token \
-H "Content-Type: application/json" \
-d '{
"clientId": "graphapp-ab6bd084821c471eaab9ef7f83b09bf9",
"authorizationCode": "graphcode-nl7_h3Yz90TH_jGjWAnhTz5DFuvra8oIjPG-GCrcjyE",
"redirectUri": "https://acme.example/social-graph/callback",
"clientSecret": "'"$CLIENT_SECRET"'",
"codeVerifier": "'"$VERIFIER"'"
}'
{
"accessToken": "graph-access-LX5hpmIpEI2UphioXi7Luz1n8Y1nBCt5yj5uSJ5bPF0",
"tokenType": "Bearer",
"me": { "...": "see API examples" }
}
This app is confidential, so the exchange always needs its clientSecret,
and codeVerifier because the approval carried a code_challenge. A public
app has no secret and sends only codeVerifier.
5. Read the person’s connections
curl https://socialgraph.stackwell.tech/api/graph-access/connections \
-H "Authorization: Bearer $ACCESS_TOKEN"
[
{
"userId": "psd_4adcf14e44b5495b9e6b7e971d1e3885",
"displayName": "user-8572fe12",
"avatarUrl": null
},
{
"userId": "psd_389ff13095374ece90ce63cbd7f7e10e",
"displayName": "user-9bbce742",
"avatarUrl": null
}
]
The token works for 90 days unless it is revoked or replaced first; see Access tokens. See API examples for the other reads.
Authentication
Reads use the person’s access token (Authorization: Bearer graph-access-...), which your app gets by exchanging an approval code. The
code exchange itself takes your app’s client id plus either its client
secret or a PKCE verifier. Registering and managing an app takes a
developer token from ChirpAuth. People approve with their own Social Graph
sign-in, which your app cannot use. Authentication has a
table of what each credential may do.
API reference
The full endpoint list is in the generated API reference. It also lists the endpoints the Social Graph app uses for people, which take a person’s own sign-in and are not covered here. API examples walks through the endpoints a graph app uses, with real responses, and Concepts explains the rules behind them.
Conventions:
- Base URL
https://socialgraph.stackwell.tech. - Request and response bodies are JSON; send
Content-Type: application/json. Field names are camelCase. The approval and token fields also accept snake_case (client_id,redirect_uri,code_challenge,authorization_code,code_verifier,client_secret). - Times in responses are UTC, written
YYYY-MM-DD HH:MM:SS. - People are identified by
psd_...ids that belong to your app; see Identifiers. - Lists are not paged. Connection lists hold at most 100 people.
- There are no idempotency keys: every
POST /api/graph/appsregisters a new app.
Errors and limits
Errors are JSON, {"error": "<message>"}, except request parsing errors,
which are plain text. A missing or unusable access token is always 401 with
{"error":"unauthorized"}. Request bodies are capped at 2 MiB.
Errors and limits lists the status codes and the
messages worth handling.
Data and privacy
Social Graph learns no email address or name from ChirpAuth. An app a person approved sees their display name and their connections, under ids specific to that app. Nothing is deleted: removing something marks it, and there is no way yet for a person to delete their Social Graph data. Data and privacy says what is stored, who sees what, and what is missing.