Guide to doing research with Federdeck

This guide is for researchers who want to study Federdeck data on the AT Protocol. It focuses on practical retrieval workflows (not on explaining psychometrics).

Platform overview

Federdeck supports pathways (ordered courses of decks), four study modes (sequential, random, spaced repetition SM-2, algorithmic IRT), and four question types (open-ended, closed/multiple choice, order puzzle, Anki-style show-answer). Study mode is a user preference, not stored per deck.

Quick summary

  • Per-user / per-DID research: use AT Protocol directly (query the participant’s PDS).
  • Per-item / per-deck research across many users: you need an index (this instance provides read-only XRPC-style endpoints that query its local index).
  • Prompt media (blobs): optional; usually not the research target.

Platform overview

Federdeck supports four study modes (sequential, random, spaced repetition SM-2, algorithmic IRT) and four question types (open-ended, multiple choice, spaced repetition show-answer, order puzzle). Decks can be grouped into pathways (ordered courses). The whitepaper describes planned research infrastructure (consent, registry, Query API); the current release provides XRPC endpoints and guides below.

Lexicons and collections

Federdeck records are stored as ATProto repo records using these collections (NSIDs):

  • com.federdeck.pathway (pathways)
  • com.federdeck.deck (decks)
  • com.federdeck.item (items)
  • com.federdeck.response (responses)

If Federdeck later migrates to a domain-backed namespace, treat the new namespace as a schema-identical alias of com.federdeck.*.

Lexicons (JSON)

Method 1: research per DID (direct AT Protocol)

Use this when you have a consented cohort (a list of DIDs) or you’re doing qualitative / case-based work. You pull records from each person’s PDS and analyze locally.

Step 1 — resolve handle → DID (optional)

curl -sS "https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=alice.bsky.social"

Step 2 — resolve DID → PDS endpoint

For did:plc, fetch the DID document from the PLC directory and extract the PDS serviceEndpoint.

curl -sS "https://plc.directory/did:plc:YOUR_DID_HERE"

Step 3 — list records from the user repo

Once you have PDS_BASE and DID, list records from the Federdeck collections.

PDS_BASE="https://federdeck.com"
DID="did:plc:..."

# decks
curl -sS "${PDS_BASE}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=com.federdeck.deck&limit=100"

# items
curl -sS "${PDS_BASE}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=com.federdeck.item&limit=100"

# responses
curl -sS "${PDS_BASE}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=com.federdeck.response&limit=100"

Use the returned cursor to paginate until it’s absent. Store uri, cid, and the full record value for reproducibility.

Deck → item join

A deck record contains itemIds (ordered AT-URIs). You can reconstruct the deck by joining those URIs to item records (either by listing all items once and mapping in-memory, or calling com.atproto.repo.getRecord for specific item rkeys).

Responses are the main research artifact

Responses are the typical primary object of analysis. Each response record includes itemId, userDid, correctness, response time (optional), and an answeredAt timestamp.

Method 2: research per item/deck (indexed XRPC endpoints)

AT Protocol does not offer a global “where itemId == X” query across all repos. If you want “all responses for item X” or “all responses for deck X across users”, you need an indexer. This Federdeck instance maintains a local index (Jetstream + backfill) and exposes query endpoints.

Important: results are limited to what this instance has indexed (its discovery scope + uptime). For full-network coverage you’d run your own indexer/AppView-like service.

Get responses by item

Endpoint: /xrpc/com.federdeck.getResponsesByItem?item=AT_URI&limit=50&cursor=...

ITEM="at://did:plc:.../com.federdeck.item/3k...."
curl -sS "https://federdeck.com/xrpc/com.federdeck.getResponsesByItem?item=${ITEM}&limit=50"

The response contains responses[] and an optional cursor for pagination.

Get responses by deck

Deck-scoped queries return all responses whose itemId is in the deck’s itemIds.

Endpoint: /xrpc/com.federdeck.getResponsesByDeck?deck=AT_URI&limit=50&cursor=...

DECK="at://did:plc:.../com.federdeck.deck/3k...."
curl -sS "https://federdeck.com/xrpc/com.federdeck.getResponsesByDeck?deck=${DECK}&limit=50"

CSV export

Append format=csv to get CSV instead of JSON: ?item=AT_URI&limit=50&format=csv

Pagination model

These endpoints use keyset pagination ordered by answeredAt (descending) and then uri. Always pass the returned cursor back to fetch the next page.

Optional: prompt media (blobs)

Blobs are just media embedded in prompts (images, etc). If your study needs stimulus media, fetch blobs via com.atproto.sync.getBlob from the same PDS that hosts the repo.

Suggestions to make Federdeck more suitable for open research

  • Consent mode: explicitly choose whether responses are published to the repo (public) or kept local-only.
  • Research session IDs: add a sessionId field to responses so researchers can group a sitting.
  • Deck/deckUri on responses: denormalize deck membership so “responses for deck X” doesn’t require joining via itemIds.
  • Stable export: add a “download CSV/JSON” export for consented users (or admin-only) to simplify replication.
  • Anonymization helpers: optional hashed participant IDs for sharing datasets without raw DIDs.
  • Provenance: store and return CIDs for indexed response records when available (Jetstream provides CIDs).