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