Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 335 lines 8.4 kB view raw view rendered
1# User Pages - API Examples 2 3Real examples of ATProto API responses used by the user pages. 4 5## 1. Resolve Handle to DID 6 7### Request 8``` 9GET https://at.aesthetic.computer/xrpc/com.atproto.identity.resolveHandle?handle=fifi.at.aesthetic.computer 10``` 11 12### Response 13```json 14{ 15 "did": "did:plc:xyz123abc456def789ghi012jkl345" 16} 17``` 18 19## 2. List Painting Records 20 21### Request 22``` 23GET https://at.aesthetic.computer/xrpc/com.atproto.repo.listRecords?repo=did:plc:xyz123...&collection=computer.aesthetic.painting&limit=100 24``` 25 26### Response 27```json 28{ 29 "records": [ 30 { 31 "uri": "at://did:plc:xyz123.../computer.aesthetic.painting/3jzx7k2m4n5", 32 "cid": "bafyreib...", 33 "value": { 34 "$type": "computer.aesthetic.painting", 35 "slug": "2023.10.20.15.30.45", 36 "code": "abc123", 37 "createdAt": "2023-10-20T15:30:45.123Z", 38 "image": { 39 "$type": "blob", 40 "ref": { 41 "$link": "bafkreiabcd..." 42 }, 43 "mimeType": "image/png", 44 "size": 45678 45 }, 46 "ref": "65f3d2c1a8b9e4f5a6b7c8d9" 47 } 48 }, 49 { 50 "uri": "at://did:plc:xyz123.../computer.aesthetic.painting/2hwy6j1l3m4", 51 "cid": "bafyreic...", 52 "value": { 53 "$type": "computer.aesthetic.painting", 54 "slug": "2023.10.19.12.15.30", 55 "code": "def456", 56 "createdAt": "2023-10-19T12:15:30.456Z", 57 "image": { 58 "$type": "blob", 59 "ref": { 60 "$link": "bafkreixyz..." 61 }, 62 "mimeType": "image/png", 63 "size": 38901 64 }, 65 "ref": "65f3d2c1a8b9e4f5a6b7c8d8" 66 } 67 } 68 ], 69 "cursor": "3jzx7k2m4n5" 70} 71``` 72 73## 3. List Mood Records 74 75### Request 76``` 77GET https://at.aesthetic.computer/xrpc/com.atproto.repo.listRecords?repo=did:plc:xyz123...&collection=computer.aesthetic.mood&limit=100 78``` 79 80### Response 81```json 82{ 83 "records": [ 84 { 85 "uri": "at://did:plc:xyz123.../computer.aesthetic.mood/5pzn8r3q4t6", 86 "cid": "bafyreid...", 87 "value": { 88 "$type": "computer.aesthetic.mood", 89 "mood": "Feeling creative today! Just finished a new piece.", 90 "when": "2023-10-20T14:25:15.789Z", 91 "ref": "65f3d2c1a8b9e4f5a6b7c8d7" 92 } 93 }, 94 { 95 "uri": "at://did:plc:xyz123.../computer.aesthetic.mood/4nyi7q2p3s5", 96 "cid": "bafyreie...", 97 "value": { 98 "$type": "computer.aesthetic.mood", 99 "mood": "Working on something experimental...", 100 "when": "2023-10-19T09:45:30.123Z", 101 "ref": "65f3d2c1a8b9e4f5a6b7c8d6" 102 } 103 } 104 ], 105 "cursor": null 106} 107``` 108 109## 4. Get Blob (Image) 110 111### Request 112``` 113GET https://at.aesthetic.computer/xrpc/com.atproto.sync.getBlob?did=did:plc:xyz123...&cid=bafkreiabcd... 114``` 115 116### Response 117Binary image data (PNG) 118 119## Record URI Structure 120 121ATProto URIs follow this pattern: 122``` 123at://[DID]/[COLLECTION]/[RKEY] 124``` 125 126Examples: 127- `at://did:plc:xyz123.../computer.aesthetic.painting/3jzx7k2m4n5` 128- `at://did:plc:xyz123.../computer.aesthetic.mood/5pzn8r3q4t6` 129 130Components: 131- **DID**: Decentralized identifier for the user 132- **Collection**: Lexicon name (e.g., `computer.aesthetic.painting`) 133- **RKEY**: Record key (unique ID within collection) 134 135## Field Descriptions 136 137### Painting Record Fields 138 139| Field | Type | Description | 140|-------|------|-------------| 141| `$type` | string | Always `computer.aesthetic.painting` | 142| `slug` | string | Timestamp-based painting ID | 143| `code` | string | Short alphanumeric code (e.g., `abc123`) | 144| `createdAt` | string | ISO 8601 timestamp | 145| `image` | blob | Reference to image data | 146| `ref` | string | MongoDB ObjectId reference | 147 148### Mood Record Fields 149 150| Field | Type | Description | 151|-------|------|-------------| 152| `$type` | string | Always `computer.aesthetic.mood` | 153| `mood` | string | The mood text content | 154| `when` | string | ISO 8601 timestamp | 155| `ref` | string | MongoDB ObjectId reference | 156 157### Blob Fields 158 159| Field | Type | Description | 160|-------|------|-------------| 161| `$type` | string | Always `blob` | 162| `ref.$link` | string | CID (Content Identifier) | 163| `mimeType` | string | MIME type (e.g., `image/png`) | 164| `size` | number | Size in bytes | 165 166## Error Responses 167 168### Handle Not Found 169```json 170{ 171 "error": "InvalidRequest", 172 "message": "Unable to resolve handle: fifi.at.aesthetic.computer" 173} 174``` 175Status: 400 176 177### Collection Not Found 178```json 179{ 180 "error": "InvalidRequest", 181 "message": "Collection not found: computer.aesthetic.painting" 182} 183``` 184Status: 400 185 186### DID Not Found 187```json 188{ 189 "error": "InvalidRequest", 190 "message": "Could not find repo: did:plc:xyz123..." 191} 192``` 193Status: 400 194 195## Pagination 196 197When there are more than 100 records, use the `cursor`: 198 199### Request with Cursor 200``` 201GET https://at.aesthetic.computer/xrpc/com.atproto.repo.listRecords?repo=did:plc:xyz123...&collection=computer.aesthetic.painting&limit=100&cursor=3jzx7k2m4n5 202``` 203 204### Response 205```json 206{ 207 "records": [ 208 // Next 100 records... 209 ], 210 "cursor": "2gwx6i1k2m3" // Or null if no more records 211} 212``` 213 214## JavaScript Examples 215 216### Fetch Handle DID 217```javascript 218const PDS_URL = 'https://at.aesthetic.computer'; 219 220async function resolveDID(handle) { 221 const url = `${PDS_URL}/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`; 222 const response = await fetch(url); 223 const data = await response.json(); 224 return data.did; 225} 226 227// Usage 228const did = await resolveDID('fifi.at.aesthetic.computer'); 229console.log(did); // did:plc:xyz123... 230``` 231 232### List All Records (with Pagination) 233```javascript 234async function listRecords(did, collection) { 235 const records = []; 236 let cursor = undefined; 237 238 do { 239 const url = new URL(`${PDS_URL}/xrpc/com.atproto.repo.listRecords`); 240 url.searchParams.append('repo', did); 241 url.searchParams.append('collection', collection); 242 url.searchParams.append('limit', 100); 243 if (cursor) url.searchParams.append('cursor', cursor); 244 245 const response = await fetch(url); 246 const data = await response.json(); 247 248 records.push(...data.records); 249 cursor = data.cursor; 250 } while (cursor); 251 252 return records; 253} 254 255// Usage 256const paintings = await listRecords(did, 'computer.aesthetic.painting'); 257console.log(`Found ${paintings.length} paintings`); 258``` 259 260### Get Image URL 261```javascript 262function getImageUrl(did, blobCid) { 263 return `${PDS_URL}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${blobCid}`; 264} 265 266// Usage 267const painting = records[0]; 268const did = painting.uri.split('/')[2]; 269const cid = painting.value.image.ref.$link; 270const imageUrl = getImageUrl(did, cid); 271 272// Use in img tag 273document.querySelector('img').src = imageUrl; 274``` 275 276### Extract Record Key (RKEY) 277```javascript 278function getRkey(uri) { 279 return uri.split('/').pop(); 280} 281 282// Usage 283const uri = 'at://did:plc:xyz123.../computer.aesthetic.painting/3jzx7k2m4n5'; 284const rkey = getRkey(uri); // '3jzx7k2m4n5' 285``` 286 287## Testing with cURL 288 289```bash 290# 1. Resolve handle 291curl "https://at.aesthetic.computer/xrpc/com.atproto.identity.resolveHandle?handle=fifi.at.aesthetic.computer" 292 293# 2. List paintings (replace DID) 294curl "https://at.aesthetic.computer/xrpc/com.atproto.repo.listRecords?repo=did:plc:xyz123...&collection=computer.aesthetic.painting&limit=5" 295 296# 3. Get image (replace DID and CID) 297curl "https://at.aesthetic.computer/xrpc/com.atproto.sync.getBlob?did=did:plc:xyz123...&cid=bafkreiabcd..." --output image.png 298 299# 4. List moods 300curl "https://at.aesthetic.computer/xrpc/com.atproto.repo.listRecords?repo=did:plc:xyz123...&collection=computer.aesthetic.mood&limit=5" 301``` 302 303## Rate Limiting 304 305The PDS does not currently enforce strict rate limits, but: 306- Recommended: Max 100 requests per minute per client 307- Pagination: Use reasonable limits (100-500) 308- Caching: Cache resolved DIDs client-side 309 310## CORS 311 312The PDS allows CORS requests from any origin: 313``` 314Access-Control-Allow-Origin: * 315``` 316 317This enables the user pages to work purely client-side. 318 319## Security Notes 320 3211. **No Authentication Required** - All data is public 3222. **Read-Only** - XRPC endpoints used are read-only 3233. **No Personal Data** - Only public ATProto records 3244. **Client-Side Only** - No server-side secrets exposed 325 326## Related Documentation 327 328- [ATProto Lexicon Reference](https://atproto.com/specs/lexicon) 329- [XRPC Specification](https://atproto.com/specs/xrpc) 330- [User Pages Architecture](USER-PAGES-ARCHITECTURE.md) 331- [User Pages Documentation](USER-PAGES.md) 332 333--- 334 335**Last Updated:** 2025-10-20