possum
PDS (Personal Data Server)
A PDS, or Personal Data Server, is a server that hosts a user, it will always store the user’s data repo and signing keys. It may also assign the user a handle and a DID. Many PDSes will host multiple users.
A PDS doesn’t typically run any applications itself, though it will have general account management interfaces such as the OAuth login screen. PDSes actively sync their data repos with Relays.
Lexicon
Lexicon is a schema language. It’s used in the Atmosphere to describe data records and HTTP APIs. Functionally it’s very similar to JSON-Schema and OpenAPI. Lexicon’s sole purpose is to help developers build compatible software.
Record Keys
A record key (sometimes shortened to “rkey”) is used to name and reference an individual record within the same collection of an atproto repository. It ends up as a segment in AT URIs, and in the repo MST path.
CID (Content ID)
CIDs, or Content Identifiers, are cryptographic hashes of records. They are used to track specific versions of records.
Values
pub fn authorized(
request: request.Request(a),
access_token token: String,
) -> request.Request(a)
Include a access token in the request’s headers.
Tokens can be acquired with create_session.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.authorized("my-access-token")
pub fn create_record(
request: request.Request(a),
did: did.Did,
rkey rkey: option.Option(String),
collection collection: String,
record record: List(#(String, json.Json)),
swap_commit swap_commit: option.Option(String),
validate validate: option.Option(Bool),
) -> request.Request(String)
Create a single new repository record. Requires auth, implemented by PDS.
Body
- collection: The NSID of the record collection.
- repo: The handle or DID of the repo (aka, current account).
- rkey: The Record Key.
- swapCommit: Compare and swap with the previous commit by CID.
- validate: Can be set to ‘false’ to skip Lexicon schema validation of record data, ‘true’ to require it, or leave unset to validate only for known Lexicons.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.authorized("access-token")
|> possum.create_record(
did: did,
rkey: "wibble",
collection: "wibble.wobble.woo",
record: [],
swap_commit: option.None,
validate: option.None,
)
Response
{
"cid": "string",
"uri": "string",
"commit": {
"cid": "string",
"rev": "string"
},
"validationStatus": "valid"
}
Endpoint Docs: /xrpc/com.atproto.repo.createRecord
pub fn create_session(
request: request.Request(a),
did: did.Did,
app_password app_password: String,
allow_takendown allow_takendown: option.Option(Bool),
auth_factor_token auth_factor_token: option.Option(String),
) -> request.Request(String)
Create an authentication session. An App Password can be generated in your Bluesky settings.
Body
- password: App password
- allowTakendown: When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned
- authFactorToken: Used during the authentication process to handle Two-Factor Authentication
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.create_session(
did,
"bsky-app-password",
option.None,
option.None
)
Response
{
"did": "string",
"email": "string",
"active": true,
"didDoc": null,
"handle": "string",
"status": "takendown",
"accessJwt": "string",
"refreshJwt": "string",
"emailConfirmed": true,
"emailAuthFactor": true
}
Endpoint Docs: /xrpc/com.atproto.server.createSession
pub fn describe_repository(
request: request.Request(a),
did: did.Did,
) -> request.Request(a)
Get information about an account and repository, including the list of collections.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.describe_repository(did)
Response
{
"did": "string",
"didDoc": null,
"handle": "string",
"collections": [
"string"
],
"handleIsCorrect": true
}
Endpoint Docs: /xrpc/com.atproto.repo.describeRepo
pub fn get_plc_data(
request: request.Request(a),
did: did.Did,
) -> request.Request(a)
Get current PLC Data for the indicated DID, this returns information about a Decentralized Identifier (DID), including their handle and service endpoint.
PLC is a persistent global identifier system, stands for “Public Ledger of Credentials”.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> possum.get_plc_data("did:plc:z72i7hdynmk6r22z27h6tvur")
Response
{
"did": "string",
"verificationMethods": {
"atproto": "string"
},
"rotationKeys": [
"string",
"string"
],
"alsoKnownAs": [
"string"
],
"services": {
"atproto_pds": {
"type": "string",
"endpoint": "string"
}
}
Documentation: DID PLC Directory
pub fn get_record(
request: request.Request(a),
did: did.Did,
rkey rkey: String,
collection collection: String,
cid cid: option.Option(String),
) -> request.Request(a)
Get a single record from a repository. Does not require auth.
A record key (rkey) is used to name and reference an individual record withing the same collection of an repository.
CIDs include a metadata code which indicates whether it links to a node
or arbitrary binary data. In atproto, object nodes often include a string
field $type that specifies their Lexicon schema.
You can use projects like Slingshot for easy access to cached data.
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.get_record(
repository: did,
rkey: "3mn6n3lvibc2b",
collection: "site.standard.document",
cursor: option.None,
cid: option.None,
)
Response
{
"cid": "string",
"uri": "string",
"value": null
}
Endpoint Docs: /xrpc/com.atproto.repo.getRecord Documentation: atproto.com
pub fn get_session_info(
request: request.Request(a),
) -> request.Request(a)
Get information about the current auth session. Requires auth.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.authorized("access-token")
|> possum.get_session_info
Response
{
"did": "string",
"email": "string",
"active": true,
"didDoc": null,
"handle": "string",
"status": "takendown",
"emailConfirmed": true,
"emailAuthFactor": true
}
Endpoint Docs: /xrpc/com.atproto.server.getSession
pub fn list_records(
request: request.Request(a),
did: did.Did,
collection collection: String,
limit limit: option.Option(Int),
cursor cursor: option.Option(String),
reverse reverse: option.Option(Bool),
) -> request.Request(a)
List a range of records in a repository, matching a specific collection.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.list_records(
did: did,
collection: "site.standard.document",
limit: option.Some(3),
cursor: option.None,
reverse: option.None,
)
Response
{
"cursor": "string",
"records": [
{
"cid": "string",
"uri": "string",
"value": null
}
]
}
Endpoint Docs: /xrpc/com.atproto.repo.listRecords
pub fn list_standard_documents(
request: request.Request(a),
did: did.Did,
limit limit: option.Option(Int),
) -> request.Request(a)
List published articles, blog posts and other content.
The site.standard.document lexicon provides metadata for individual documents. Including the document’s relation to a publication if applicable, a path to the document, and more information like a document’s complete contents.
This function os a wrapper around list_records.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.list_standard_documents(did, limit: option.None)
Documentation: standard.site
pub fn refresh_session(
request: request.Request(a),
refresh token: String,
) -> request.Request(a)
Refresh an authentication session. Requires auth using the ‘refreshJwt’ (not the ‘accessJwt’).
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.refresh_session("refresh-token")
Response
{
"did": "string",
"email": "string",
"active": true,
"didDoc": null,
"handle": "string",
"status": "takendown",
"accessJwt": "string",
"refreshJwt": "string",
"emailConfirmed": true,
"emailAuthFactor": true
}
Endpoint Docs: /xrpc/com.atproto.server.refreshSession
pub fn resolve_handle(
request: request.Request(a),
handle handle: String,
) -> request.Request(a)
Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.
You can use projects like Slingshot for easy access to cached data.
Examples
import gleam/http/request
import possum
let request =
request.new()
|> request.set_host("personal.data-server.pds")
|> possum.resolve_handle("gleam.run")
Response
{
"did": "string"
}
Endpoint Docs: /xrpc/com.atproto.identity.resolveHandle
pub fn resolve_well_known_did(
request: request.Request(a),
host host: String,
) -> request.Request(a)
Resolves a handle to a DID using a HTTPS /.well-known/ URL path,
it looks for a file called “atproto-did” that contains the user DID.
Examples
import gleam/http/request
import possum
request.new()
|> possum.resolve_well_known_did("gleam.run")
Response
did:plc:k5vecqzf4d5mdvkcu3mx6l5g
Documentation: HTTPS well-known Method