API Reference#
Complete reference for Slices API endpoints.
Base URL#
https://api.slices.network/xrpc/
Authentication#
Most write operations require OAuth 2.0 authentication. Include the access token in the Authorization header:
Authorization: Bearer YOUR_ACCESS_TOKEN
Read operations typically work without authentication.
Dynamic Collection Endpoints#
For each collection in your slice, the following endpoints are automatically generated:
[collection].getRecords#
Get records in a collection.
Method: GET
Parameters:
slice(string, required): Slice URIlimit(number, optional): Maximum records (default: 50)cursor(string, optional): Pagination cursorwhere(object, optional): Filter conditions using field-specific queriessortBy(array, optional): Sort specification with field and direction objects
[collection].getRecord#
Get a single record.
Method: GET
Parameters:
slice(string, required): Slice URIuri(string, required): Record URI
[collection].countRecords#
Count records in a collection.
Method: GET
Parameters:
slice(string, required): Slice URIwhere(object, optional): Filter conditions using field-specific queries- Other filter parameters (no limit/cursor)
Response:
{
"count": 150
}
[collection].createRecord#
Create a new record.
Method: POST
Authentication: Required
Body:
{
"slice": "at://your-slice-uri",
"record": {
"$type": "com.recordcollector.album",
"title": "Superunknown",
"artist": "Soundgarden",
"releaseDate": "1994-03-08",
"condition": "Near Mint",
"genre": ["grunge", "alternative metal"]
},
"rkey": "3jklmno456"
}
[collection].updateRecord#
Update an existing record.
Method: POST
Authentication: Required
Body:
{
"slice": "at://your-slice-uri",
"rkey": "3xyz789abc",
"record": {
"$type": "com.recordcollector.album",
"title": "Dirt",
"artist": "Alice in Chains",
"releaseDate": "1992-09-29",
"condition": "Very Good Plus",
"notes": "Minor sleeve wear, vinyl plays perfectly"
}
}
[collection].deleteRecord#
Delete a record.
Method: POST
Authentication: Required
Body:
{
"rkey": "3abc123xyz"
}
Core Endpoints#
Slice Management#
network.slices.slice.getRecords#
Get all slices.
Method: GET
Parameters:
limit(number, optional): Maximum records to return (default: 50)cursor(string, optional): Pagination cursorwhere(object, optional): Filter conditions using field-specific queriessortBy(array, optional): Sort specification with field and direction objects
Response:
{
"records": [
{
"uri": "at://did:plc:abc/network.slices.slice/xyz",
"cid": "bafyrei...",
"did": "did:plc:abc",
"collection": "network.slices.slice",
"value": {
"name": "My Slice",
"domain": "com.example",
"createdAt": "2024-01-01T00:00:00Z"
},
"indexedAt": "2024-01-01T00:00:00Z"
}
],
"cursor": "next-page-cursor"
}
network.slices.slice.getRecord#
Get a specific slice by URI.
Method: GET
Parameters:
uri(string, required): AT Protocol URI of the slice
Response: Single record object (same structure as getRecords item)
network.slices.slice.createRecord#
Create a new slice.
Method: POST
Authentication: Required
Body:
{
"slice": "at://your-slice-uri",
"record": {
"$type": "network.slices.slice",
"name": "My New Slice",
"domain": "com.example",
"createdAt": "2024-01-01T00:00:00Z"
},
"rkey": "optional-record-key"
}
Response:
{
"uri": "at://did:plc:abc/network.slices.slice/xyz",
"cid": "bafyrei..."
}
Slice Operations#
network.slices.slice.stats#
Get statistics for a slice.
Method: POST
Body:
{
"slice": "at://your-slice-uri"
}
Response:
{
"success": true,
"collections": ["com.recordcollector.album", "com.recordcollector.review"],
"collectionStats": [
{
"collection": "com.recordcollector.album",
"recordCount": 427,
"uniqueActors": 23
}
],
"totalLexicons": 5,
"totalRecords": 500,
"totalActors": 25,
"message": "Statistics retrieved successfully"
}
network.slices.slice.listSliceRecords#
List records across multiple collections in a slice.
Method: POST
Body:
{
"slice": "at://your-slice-uri",
"collections": ["com.recordcollector.album", "com.recordcollector.review"],
"authors": ["did:plc:optional-filter"],
"limit": 20,
"cursor": "pagination-cursor"
}
Response:
{
"success": true,
"records": [
{
"uri": "at://did:plc:abc/com.recordcollector.album/xyz",
"cid": "bafyrei...",
"did": "did:plc:abc",
"collection": "com.recordcollector.album",
"value": {/* record data */},
"indexedAt": "2024-01-01T00:00:00Z"
}
],
"cursor": "next-page-cursor"
}
network.slices.slice.searchSliceRecords#
Search records across multiple collections in a slice by content.
Method: POST
Body:
{
"slice": "at://your-slice-uri",
"collections": ["com.recordcollector.album", "com.recordcollector.review"],
"search": "search term",
"authors": ["did:plc:optional-filter"],
"limit": 20,
"cursor": "pagination-cursor"
}
Response:
{
"success": true,
"records": [
{
"uri": "at://did:plc:abc/com.recordcollector.album/xyz",
"cid": "bafyrei...",
"did": "did:plc:abc",
"collection": "com.recordcollector.album",
"value": {/* record data */},
"indexedAt": "2024-01-01T00:00:00Z"
}
],
"cursor": "next-page-cursor"
}
network.slices.slice.syncUserCollections#
Synchronously sync collections for the authenticated user.
Method: POST
Authentication: Required
Body:
{
"slice": "at://your-slice-uri",
"timeoutSeconds": 30
}
Response:
{
"success": true,
"reposProcessed": 1,
"recordsSynced": 45,
"timedOut": false,
"message": "Sync completed successfully"
}
network.slices.slice.startSync#
Start an asynchronous bulk sync job.
Method: POST
Authentication: Required
Body:
{
"slice": "at://your-slice-uri",
"collections": ["com.recordcollector.album"],
"externalCollections": ["app.bsky.actor.profile"],
"repos": ["did:plc:abc", "did:plc:xyz"],
"limitPerRepo": 100
}
Response:
{
"success": true,
"jobId": "job-uuid",
"message": "Sync job started"
}
network.slices.slice.codegen#
Generate TypeScript client code.
Method: POST
Body:
{
"target": "typescript",
"slice": "at://your-slice-uri"
}
Response:
{
"success": true,
"generatedCode": "// Generated TypeScript client code..."
}
Lexicon Management#
network.slices.lexicon.getRecords#
Get lexicons in a slice.
Method: GET
Parameters: Same as collection.getRecords
network.slices.lexicon.countRecords#
Count lexicons in a slice.
Method: GET
Parameters: Same as collection.getRecords (except limit and cursor)
Response:
{
"count": 10
}
network.slices.lexicon.createRecord#
Add a lexicon to a slice.
Method: POST
Authentication: Required
Body:
{
"slice": "at://your-slice-uri",
"record": {
"$type": "network.slices.lexicon",
"nsid": "com.recordcollector.album",
"definitions": "{\"lexicon\": 1, ...}",
"createdAt": "2024-01-01T00:00:00Z",
"slice": "at://your-slice-uri"
}
}
Actor Management#
network.slices.slice.getActors#
Get actors (users) in a slice.
Method: GET
Parameters:
slice(string, required): Slice URIsearch(string, optional): Search querydids(string[], optional): Filter by DIDslimit(number, optional): Maximum resultscursor(string, optional): Pagination cursor
Response:
{
"actors": [
{
"did": "did:plc:abc",
"handle": "user.bsky.social",
"sliceUri": "at://slice-uri",
"indexedAt": "2024-01-01T00:00:00Z"
}
],
"cursor": "next-page"
}
Blob Upload#
com.atproto.repo.uploadBlob#
Upload a blob (image, file).
Method: POST
Authentication: Required
Headers:
Content-Type: MIME type of the blob
Body: Raw binary data
Response:
{
"blob": {
"$type": "blob",
"ref": { "$link": "bafkrei..." },
"mimeType": "image/jpeg",
"size": 127198
}
}
Error Responses#
All endpoints may return error responses:
{
"error": "InvalidRequest",
"message": "Detailed error message"
}
Common HTTP status codes:
200: Success400: Bad request401: Authentication required403: Forbidden404: Not found500: Internal server error
Pagination#
List endpoints support cursor-based pagination:
- Make initial request without cursor
- Use returned cursor for next page
- Continue until no cursor returned
Example:
let cursor = undefined;
do {
const response = await fetch(`/xrpc/collection.getRecords?cursor=${cursor}`);
const data = await response.json();
// Process records
cursor = data.cursor;
} while (cursor);
Filtering#
List endpoints support filtering using the where parameter with field-specific
query operators:
Filter Operators#
eq: Exact matchcontains: Partial text match (case-insensitive)in: Match any value in array
Examples#
Exact match filtering:
{
"where": {
"artist": { "eq": "Nirvana" },
"condition": { "eq": "Mint" }
}
}
Text search filtering:
{
"where": {
"title": { "contains": "nevermind" },
"genre": { "contains": "grunge" }
}
}
Array filtering:
{
"where": {
"condition": { "in": ["Mint", "Near Mint", "Very Good Plus"] },
"artist": { "in": ["Nirvana", "Pearl Jam", "Soundgarden"] }
}
}
Global search across all fields:
{
"where": {
"json": { "contains": "grunge" }
}
}
Sorting#
Sort parameter uses an array format with field and direction:
{
"sortBy": [
{ "field": "releaseDate", "direction": "desc" },
{ "field": "title", "direction": "asc" }
]
}
Examples:
[{ "field": "releaseDate", "direction": "desc" }]- Newest releases first[{ "field": "artist", "direction": "asc" }]- Alphabetical by artist[{ "field": "releaseDate", "direction": "desc" }, { "field": "title", "direction": "asc" }]- Newest first, then alphabetical by title
Next Steps#
- SDK Usage - Using generated TypeScript clients
- Getting Started - Build your first application
- Concepts - Understand the architecture