Skip to main content

Quickstart

This walks one happy path end to end: find a space, open it, list its posts, and read one. Every endpoint is a GET, and none of them needs an Authorization header today. The examples use a sample space and post; replace them with values the API returns. JSON below is trimmed to the fields in play.

1. List public spaces

curl 'https://api.dfos.com/v1/spaces?limit=20'
{
"items": [
{
"id": "space_7gx4k2m9",
"did": "did:dfos:93n4d6936c3ct6r3k7477dn4z89c39h",
"domain": "field-notes",
"displayName": "Field Notes",
"avatarUrl": "https://media.dfos.com/field-notes-avatar.jpg",
"memberCountSummary": "a few dozen members"
}
],
"nextCursor": null,
"totalCount": 42
}

Each item is a compact card. Store the id or did — the domain (subdomain) is a mutable alias. You can filter with ?joinMode=open and page with nextCursor. Full field and filter semantics are in Spaces, and the pagination contract is in Conventions.

2. Get a space

Address it by subdomain, entity id (space_…), or protocol DID:

curl https://api.dfos.com/v1/spaces/field-notes

The single fetch adds the space's full public profile — joinMode, siteMode, subscribeEnabled, profile links, and (for application-mode spaces) applicationQuestions. See Spaces for what each field means.

3. List the space's posts

Posts come back newest first.

curl 'https://api.dfos.com/v1/spaces/field-notes/posts?limit=20'
{
"items": [
{
"id": "post_4k8m2q7v",
"title": "Notes from the wetlands",
"displayTitle": "Notes from the wetlands",
"excerpt": "What changed after the first week of rain...",
"isPinned": false,
"publishedAt": "2026-07-19T18:00:00.000Z"
}
],
"nextCursor": null
}

displayTitle is a ready-to-render heading (it fills in for untitled posts), and isPinned marks pinned posts — but the feed is ordered purely by recency and won't reorder them for you. The listing carries no post body; fetch a post to read it. See Posts.

4. Read a single post

Use the post's id, not its slug:

curl https://api.dfos.com/v1/spaces/field-notes/posts/post_4k8m2q7v

The response is a union on state. When the post is anonymously readable, state is "eligible" and the content is under post:

{
"state": "eligible",
"post": {
"id": "post_4k8m2q7v",
"displayTitle": "Notes from the wetlands",
"body": "The waterline rose overnight. Here is what we found...",
"canonicalUri": "https://field-notes.dfos.com/post/notes-from-the-wetlands-post_4k8m2q7v",
"publishedAt": "2026-07-19T18:00:00.000Z"
}
}

When an anonymous caller can't read the post, state is "gated" instead: no content, just a slim space call-to-action and a reason. The full union — including folded posts and the reason enum — is documented in Posts.

Next