Highly ambitious ATProtocol AppView service and sdks
1# API Reference 2 3## Base URL 4 5``` 6https://api.slices.network/xrpc/ 7``` 8 9For local development: 10``` 11http://localhost:3000/xrpc/ 12``` 13 14## Authentication 15 16Write operations require OAuth 2.0 authentication with a Bearer token: 17 18``` 19Authorization: Bearer YOUR_ACCESS_TOKEN 20``` 21 22Read operations are public by default. 23 24## Collection Endpoints 25 26For each collection in your slice (e.g., `com.recordcollector.album`), the following endpoints are automatically generated: 27 28# **{collection}.getRecords** 29 30> List records with filtering, sorting, and pagination. 31 32**Method:** `POST` 33**Endpoint:** `/xrpc/{collection}.getRecords` 34**Example:** `/xrpc/com.recordcollector.album.getRecords` 35 36**Request Body:** 37```json 38{ 39 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 40 "limit": 20, 41 "cursor": "optional-pagination-cursor", 42 "where": { 43 "genre": { "contains": "grunge" }, 44 "condition": { "in": ["Mint", "Near Mint"] } 45 }, 46 "sortBy": [ 47 { "field": "releaseDate", "direction": "desc" } 48 ] 49} 50``` 51 52**Parameters:** 53- `slice` (string, required): The slice URI to query 54- `limit` (number, optional): Maximum records to return (default: 50, max: 100) 55- `cursor` (string, optional): Pagination cursor from previous response 56- `where` (object, optional): Filter conditions. Field filters support operators: `eq`, `contains`, `in`. Special field `json` searches across all fields 57- `sortBy` (array, optional): Sort specification. Each item has `field` and `direction` ("asc" or "desc") 58 59**Response:** 60```json 61{ 62 "records": [ 63 { 64 "uri": "at://did:plc:user123/com.recordcollector.album/3l2w4x5y6z", 65 "cid": "bafyreigbtj4x7ip5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua", 66 "did": "did:plc:user123", 67 "collection": "com.recordcollector.album", 68 "value": { 69 "$type": "com.recordcollector.album", 70 "title": "Nevermind", 71 "artist": "Nirvana", 72 "releaseDate": "1991-09-24T00:00:00.000Z", 73 "genre": ["grunge", "alternative rock"], 74 "condition": "Near Mint", 75 "notes": "Original pressing, includes poster" 76 }, 77 "indexedAt": "2024-03-15T10:30:15.123Z" 78 } 79 ], 80 "cursor": "next-page-cursor-xyz789" 81} 82``` 83 84# **{collection}.getRecord** 85 86> Get a single record by URI. 87 88**Method:** `GET` 89**Endpoint:** `/xrpc/{collection}.getRecord` 90**Example:** `/xrpc/com.recordcollector.album.getRecord` 91 92**Query Parameters:** 93- `slice` (string, required): The slice URI 94- `uri` (string, required): The AT Protocol URI of the record 95 96**Example Request:** 97``` 98GET /xrpc/com.recordcollector.album.getRecord?slice=at://did:plc:abc123/network.slices.slice/xyz789&uri=at://did:plc:user123/com.recordcollector.album/3l2w4x5y6z 99``` 100 101**Response:** 102```json 103{ 104 "uri": "at://did:plc:user123/com.recordcollector.album/3l2w4x5y6z", 105 "cid": "bafyreigbtj4x7ip5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua", 106 "did": "did:plc:user123", 107 "collection": "com.recordcollector.album", 108 "value": { 109 "$type": "com.recordcollector.album", 110 "title": "Nevermind", 111 "artist": "Nirvana", 112 "releaseDate": "1991-09-24T00:00:00.000Z", 113 "genre": ["grunge", "alternative rock"], 114 "condition": "Near Mint", 115 "notes": "Original pressing, includes poster" 116 }, 117 "indexedAt": "2024-03-15T10:30:15.123Z" 118} 119``` 120 121# **{collection}.countRecords** 122 123> Count records matching filter criteria. 124 125**Method:** `POST` 126**Endpoint:** `/xrpc/{collection}.countRecords` 127**Example:** `/xrpc/com.recordcollector.album.countRecords` 128 129**Request Body:** 130```json 131{ 132 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 133 "where": { 134 "condition": { "in": ["Mint", "Near Mint"] }, 135 "genre": { "contains": "grunge" } 136 } 137} 138``` 139 140**Response:** 141```json 142{ 143 "success": true, 144 "count": 42, 145 "message": "Count retrieved successfully" 146} 147``` 148 149# **{collection}.createRecord** 150 151> Create a new record. 152 153**Method:** `POST` 154**Endpoint:** `/xrpc/{collection}.createRecord` 155**Example:** `/xrpc/com.recordcollector.album.createRecord` 156**Authentication:** Required 157 158**Request Body:** 159```json 160{ 161 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 162 "rkey": "optional-custom-key", 163 "record": { 164 "$type": "com.recordcollector.album", 165 "title": "In Utero", 166 "artist": "Nirvana", 167 "releaseDate": "1993-09-21T00:00:00.000Z", 168 "genre": ["grunge", "alternative rock"], 169 "condition": "Very Good Plus", 170 "notes": "Some light wear on sleeve" 171 } 172} 173``` 174 175**Parameters:** 176- `slice` (string, required): The slice URI 177- `rkey` (string, optional): Custom record key (auto-generated if omitted) 178- `record` (object, required): The record data matching your lexicon schema 179 180**Response:** 181```json 182{ 183 "uri": "at://did:plc:user123/com.recordcollector.album/3abc456def", 184 "cid": "bafyreihj7x5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua" 185} 186``` 187 188# **{collection}.updateRecord** 189 190> Update an existing record. 191 192**Method:** `POST` 193**Endpoint:** `/xrpc/{collection}.updateRecord` 194**Example:** `/xrpc/com.recordcollector.album.updateRecord` 195**Authentication:** Required 196 197**Request Body:** 198```json 199{ 200 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 201 "rkey": "3abc456def", 202 "record": { 203 "$type": "com.recordcollector.album", 204 "title": "In Utero", 205 "artist": "Nirvana", 206 "releaseDate": "1993-09-21T00:00:00.000Z", 207 "genre": ["grunge", "alternative rock", "noise rock"], 208 "condition": "Very Good", 209 "notes": "Updated: slight ring wear visible, plays perfectly" 210 } 211} 212``` 213 214**Parameters:** 215- `slice` (string, required): The slice URI 216- `rkey` (string, required): The record key to update 217- `record` (object, required): The complete updated record data 218 219**Response:** 220```json 221{ 222 "uri": "at://did:plc:user123/com.recordcollector.album/3abc456def", 223 "cid": "bafyreiabc123legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua" 224} 225``` 226 227# **{collection}.deleteRecord** 228 229> Delete a record. 230 231**Method:** `POST` 232**Endpoint:** `/xrpc/{collection}.deleteRecord` 233**Example:** `/xrpc/com.recordcollector.album.deleteRecord` 234**Authentication:** Required 235 236**Request Body:** 237```json 238{ 239 "rkey": "3abc456def" 240} 241``` 242 243**Response:** 244```json 245{} 246``` 247 248## Filtering 249 250The `where` parameter supports powerful filtering: 251 252### Filter Operators 253 254- **`eq`**: Exact match 255```json 256{ "condition": { "eq": "Mint" } } 257``` 258 259- **`contains`**: Partial text match (case-insensitive) 260```json 261{ "artist": { "contains": "pearl jam" } } 262``` 263 264- **`in`**: Match any value in array 265```json 266{ "condition": { "in": ["Mint", "Near Mint", "Very Good Plus"] } } 267``` 268 269### Special Fields 270 271- **`json`**: Search across all fields 272```json 273{ "json": { "contains": "nirvana" } } 274``` 275 276- **System fields**: Filter by record metadata 277```json 278{ 279 "did": { "eq": "did:plc:user123" }, 280 "collection": { "eq": "com.recordcollector.album" }, 281 "indexedAt": { "contains": "2024-03" } 282} 283``` 284 285### Complex Filtering Examples 286 287**Multiple conditions (AND logic):** 288```json 289{ 290 "where": { 291 "genre": { "contains": "grunge" }, 292 "condition": { "in": ["Mint", "Near Mint"] }, 293 "releaseDate": { "contains": "1991" } 294 } 295} 296``` 297 298**Array field filtering:** 299```json 300{ 301 "where": { 302 "genre": { "contains": "alternative" } 303 } 304} 305``` 306 307## Sorting 308 309Sort results using the `sortBy` parameter: 310 311```json 312{ 313 "sortBy": [ 314 { "field": "releaseDate", "direction": "desc" }, 315 { "field": "artist", "direction": "asc" } 316 ] 317} 318``` 319 320**Common sort patterns:** 321- Newest releases first: `[{ "field": "releaseDate", "direction": "desc" }]` 322- Alphabetical by artist: `[{ "field": "artist", "direction": "asc" }]` 323- By condition (best first): `[{ "field": "condition", "direction": "asc" }]` 324- Recently indexed: `[{ "field": "indexedAt", "direction": "desc" }]` 325 326## Pagination 327 328Use cursor-based pagination for large result sets: 329 330```javascript 331// First request 332const page1 = await fetch('/xrpc/com.recordcollector.album.getRecords', { 333 method: 'POST', 334 body: JSON.stringify({ 335 slice: 'at://your-slice-uri', 336 limit: 20 337 }) 338}); 339 340// Next page using cursor 341const page2 = await fetch('/xrpc/com.recordcollector.album.getRecords', { 342 method: 'POST', 343 body: JSON.stringify({ 344 slice: 'at://your-slice-uri', 345 limit: 20, 346 cursor: page1.cursor 347 }) 348}); 349``` 350 351## Error Responses 352 353All endpoints return consistent error format: 354 355```json 356{ 357 "error": "InvalidRequest", 358 "message": "Missing required parameter: slice" 359} 360``` 361 362**Common HTTP Status Codes:** 363- `200`: Success 364- `400`: Bad request (invalid parameters) 365- `401`: Unauthorized (missing/invalid auth token) 366- `403`: Forbidden (insufficient permissions) 367- `404`: Not found (record/collection doesn't exist) 368- `500`: Internal server error 369 370## OpenAPI Specification 371 372Get the OpenAPI spec for your slice: 373 374**Method:** `GET` 375**Endpoint:** `/xrpc/network.slices.slice.openapi` 376 377**Query Parameters:** 378- `slice` (string, required): The slice URI 379 380**Response:** OpenAPI 3.0 specification with all available endpoints 381 382## Example: Record Collector Application 383 384Here's a complete example using the record collector lexicon: 385 386### Lexicon Definition 387```json 388{ 389 "lexicon": 1, 390 "id": "com.recordcollector.album", 391 "defs": { 392 "main": { 393 "type": "record", 394 "record": { 395 "type": "object", 396 "required": ["title", "artist", "releaseDate"], 397 "properties": { 398 "title": { "type": "string", "description": "Album title" }, 399 "artist": { "type": "string", "description": "Artist or band name" }, 400 "releaseDate": { 401 "type": "string", 402 "format": "datetime", 403 "description": "Original release date" 404 }, 405 "genre": { 406 "type": "array", 407 "items": { "type": "string" }, 408 "description": "Music genres" 409 }, 410 "condition": { 411 "type": "string", 412 "description": "Vinyl condition (Mint, Near Mint, etc.)" 413 }, 414 "notes": { 415 "type": "string", 416 "description": "Collector notes" 417 } 418 } 419 } 420 } 421 } 422} 423``` 424 425### List Albums by Genre 426```bash 427curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.getRecords" \ 428 -H "Content-Type: application/json" \ 429 -d '{ 430 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 431 "where": { "genre": { "contains": "grunge" } }, 432 "sortBy": [{ "field": "releaseDate", "direction": "desc" }], 433 "limit": 10 434 }' 435``` 436 437### Add New Album to Collection 438```bash 439curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.createRecord" \ 440 -H "Authorization: Bearer YOUR_TOKEN" \ 441 -H "Content-Type: application/json" \ 442 -d '{ 443 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 444 "record": { 445 "$type": "com.recordcollector.album", 446 "title": "Superunknown", 447 "artist": "Soundgarden", 448 "releaseDate": "1994-03-08T00:00:00.000Z", 449 "genre": ["grunge", "alternative metal"], 450 "condition": "Near Mint", 451 "notes": "Limited edition orange vinyl" 452 } 453 }' 454``` 455 456### Search Collection by Condition 457```bash 458curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.getRecords" \ 459 -H "Content-Type: application/json" \ 460 -d '{ 461 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 462 "where": { 463 "condition": { "in": ["Mint", "Near Mint"] }, 464 "releaseDate": { "contains": "199" } 465 }, 466 "sortBy": [{ "field": "artist", "direction": "asc" }] 467 }' 468``` 469 470### Count Albums in Collection 471```bash 472curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.countRecords" \ 473 -H "Content-Type: application/json" \ 474 -d '{ 475 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 476 "where": { "condition": { "eq": "Mint" } } 477 }' 478``` 479 480### Update Album Condition 481```bash 482curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.updateRecord" \ 483 -H "Authorization: Bearer YOUR_TOKEN" \ 484 -H "Content-Type: application/json" \ 485 -d '{ 486 "slice": "at://did:plc:abc123/network.slices.slice/xyz789", 487 "rkey": "3abc456def", 488 "record": { 489 "$type": "com.recordcollector.album", 490 "title": "Ten", 491 "artist": "Pearl Jam", 492 "releaseDate": "1991-08-27T00:00:00.000Z", 493 "genre": ["grunge", "alternative rock"], 494 "condition": "Very Good", 495 "notes": "Updated after closer inspection - slight scuffs on Side B" 496 } 497 }' 498``` 499 500## Next Steps 501 502- [SDK Usage](./sdk-usage.md) - Using generated TypeScript clients 503- [Getting Started](./getting-started.md) - Build your first application 504- [Concepts](./concepts.md) - Understand the architecture