Highly ambitious ATProtocol AppView service and sdks

API Reference#

Base URL#

https://api.slices.network/xrpc/

For local development:

http://localhost:3000/xrpc/

Authentication#

Write operations require OAuth 2.0 authentication with a Bearer token:

Authorization: Bearer YOUR_ACCESS_TOKEN

Read operations are public by default.

Collection Endpoints#

For each collection in your slice (e.g., com.recordcollector.album), the following endpoints are automatically generated:

{collection}.getRecords#

List records with filtering, sorting, and pagination.

Method: POST Endpoint: /xrpc/{collection}.getRecords Example: /xrpc/com.recordcollector.album.getRecords

Request Body:

{
  "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
  "limit": 20,
  "cursor": "optional-pagination-cursor",
  "where": {
    "genre": { "contains": "grunge" },
    "condition": { "in": ["Mint", "Near Mint"] }
  },
  "sortBy": [
    { "field": "releaseDate", "direction": "desc" }
  ]
}

Parameters:

  • slice (string, required): The slice URI to query
  • limit (number, optional): Maximum records to return (default: 50, max: 100)
  • cursor (string, optional): Pagination cursor from previous response
  • where (object, optional): Filter conditions. Field filters support operators: eq, contains, in. Special field json searches across all fields
  • sortBy (array, optional): Sort specification. Each item has field and direction ("asc" or "desc")

Response:

{
  "records": [
    {
      "uri": "at://did:plc:user123/com.recordcollector.album/3l2w4x5y6z",
      "cid": "bafyreigbtj4x7ip5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua",
      "did": "did:plc:user123",
      "collection": "com.recordcollector.album",
      "value": {
        "$type": "com.recordcollector.album",
        "title": "Nevermind",
        "artist": "Nirvana",
        "releaseDate": "1991-09-24T00:00:00.000Z",
        "genre": ["grunge", "alternative rock"],
        "condition": "Near Mint",
        "notes": "Original pressing, includes poster"
      },
      "indexedAt": "2024-03-15T10:30:15.123Z"
    }
  ],
  "cursor": "next-page-cursor-xyz789"
}

{collection}.getRecord#

Get a single record by URI.

Method: GET Endpoint: /xrpc/{collection}.getRecord Example: /xrpc/com.recordcollector.album.getRecord

Query Parameters:

  • slice (string, required): The slice URI
  • uri (string, required): The AT Protocol URI of the record

Example Request:

GET /xrpc/com.recordcollector.album.getRecord?slice=at://did:plc:abc123/network.slices.slice/xyz789&uri=at://did:plc:user123/com.recordcollector.album/3l2w4x5y6z

Response:

{
  "uri": "at://did:plc:user123/com.recordcollector.album/3l2w4x5y6z",
  "cid": "bafyreigbtj4x7ip5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua",
  "did": "did:plc:user123",
  "collection": "com.recordcollector.album",
  "value": {
    "$type": "com.recordcollector.album",
    "title": "Nevermind",
    "artist": "Nirvana",
    "releaseDate": "1991-09-24T00:00:00.000Z",
    "genre": ["grunge", "alternative rock"],
    "condition": "Near Mint",
    "notes": "Original pressing, includes poster"
  },
  "indexedAt": "2024-03-15T10:30:15.123Z"
}

{collection}.countRecords#

Count records matching filter criteria.

Method: POST Endpoint: /xrpc/{collection}.countRecords Example: /xrpc/com.recordcollector.album.countRecords

Request Body:

{
  "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
  "where": {
    "condition": { "in": ["Mint", "Near Mint"] },
    "genre": { "contains": "grunge" }
  }
}

Response:

{
  "success": true,
  "count": 42,
  "message": "Count retrieved successfully"
}

{collection}.createRecord#

Create a new record.

Method: POST Endpoint: /xrpc/{collection}.createRecord Example: /xrpc/com.recordcollector.album.createRecord Authentication: Required

Request Body:

{
  "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
  "rkey": "optional-custom-key",
  "record": {
    "$type": "com.recordcollector.album",
    "title": "In Utero",
    "artist": "Nirvana",
    "releaseDate": "1993-09-21T00:00:00.000Z",
    "genre": ["grunge", "alternative rock"],
    "condition": "Very Good Plus",
    "notes": "Some light wear on sleeve"
  }
}

Parameters:

  • slice (string, required): The slice URI
  • rkey (string, optional): Custom record key (auto-generated if omitted)
  • record (object, required): The record data matching your lexicon schema

Response:

{
  "uri": "at://did:plc:user123/com.recordcollector.album/3abc456def",
  "cid": "bafyreihj7x5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua"
}

{collection}.updateRecord#

Update an existing record.

Method: POST Endpoint: /xrpc/{collection}.updateRecord Example: /xrpc/com.recordcollector.album.updateRecord Authentication: Required

Request Body:

{
  "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
  "rkey": "3abc456def",
  "record": {
    "$type": "com.recordcollector.album",
    "title": "In Utero",
    "artist": "Nirvana",
    "releaseDate": "1993-09-21T00:00:00.000Z",
    "genre": ["grunge", "alternative rock", "noise rock"],
    "condition": "Very Good",
    "notes": "Updated: slight ring wear visible, plays perfectly"
  }
}

Parameters:

  • slice (string, required): The slice URI
  • rkey (string, required): The record key to update
  • record (object, required): The complete updated record data

Response:

{
  "uri": "at://did:plc:user123/com.recordcollector.album/3abc456def",
  "cid": "bafyreiabc123legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua"
}

{collection}.deleteRecord#

Delete a record.

Method: POST Endpoint: /xrpc/{collection}.deleteRecord Example: /xrpc/com.recordcollector.album.deleteRecord Authentication: Required

Request Body:

{
  "rkey": "3abc456def"
}

Response:

{}

Filtering#

The where parameter supports powerful filtering:

Filter Operators#

  • eq: Exact match
{ "condition": { "eq": "Mint" } }
  • contains: Partial text match (case-insensitive)
{ "artist": { "contains": "pearl jam" } }
  • in: Match any value in array
{ "condition": { "in": ["Mint", "Near Mint", "Very Good Plus"] } }

Special Fields#

  • json: Search across all fields
{ "json": { "contains": "nirvana" } }
  • System fields: Filter by record metadata
{
  "did": { "eq": "did:plc:user123" },
  "collection": { "eq": "com.recordcollector.album" },
  "indexedAt": { "contains": "2024-03" }
}

Complex Filtering Examples#

Multiple conditions (AND logic):

{
  "where": {
    "genre": { "contains": "grunge" },
    "condition": { "in": ["Mint", "Near Mint"] },
    "releaseDate": { "contains": "1991" }
  }
}

Array field filtering:

{
  "where": {
    "genre": { "contains": "alternative" }
  }
}

Sorting#

Sort results using the sortBy parameter:

{
  "sortBy": [
    { "field": "releaseDate", "direction": "desc" },
    { "field": "artist", "direction": "asc" }
  ]
}

Common sort patterns:

  • Newest releases first: [{ "field": "releaseDate", "direction": "desc" }]
  • Alphabetical by artist: [{ "field": "artist", "direction": "asc" }]
  • By condition (best first): [{ "field": "condition", "direction": "asc" }]
  • Recently indexed: [{ "field": "indexedAt", "direction": "desc" }]

Pagination#

Use cursor-based pagination for large result sets:

// First request
const page1 = await fetch('/xrpc/com.recordcollector.album.getRecords', {
  method: 'POST',
  body: JSON.stringify({
    slice: 'at://your-slice-uri',
    limit: 20
  })
});

// Next page using cursor
const page2 = await fetch('/xrpc/com.recordcollector.album.getRecords', {
  method: 'POST',
  body: JSON.stringify({
    slice: 'at://your-slice-uri',
    limit: 20,
    cursor: page1.cursor
  })
});

Error Responses#

All endpoints return consistent error format:

{
  "error": "InvalidRequest",
  "message": "Missing required parameter: slice"
}

Common HTTP Status Codes:

  • 200: Success
  • 400: Bad request (invalid parameters)
  • 401: Unauthorized (missing/invalid auth token)
  • 403: Forbidden (insufficient permissions)
  • 404: Not found (record/collection doesn't exist)
  • 500: Internal server error

OpenAPI Specification#

Get the OpenAPI spec for your slice:

Method: GET Endpoint: /xrpc/network.slices.slice.openapi

Query Parameters:

  • slice (string, required): The slice URI

Response: OpenAPI 3.0 specification with all available endpoints

Example: Record Collector Application#

Here's a complete example using the record collector lexicon:

Lexicon Definition#

{
  "lexicon": 1,
  "id": "com.recordcollector.album",
  "defs": {
    "main": {
      "type": "record",
      "record": {
        "type": "object",
        "required": ["title", "artist", "releaseDate"],
        "properties": {
          "title": { "type": "string", "description": "Album title" },
          "artist": { "type": "string", "description": "Artist or band name" },
          "releaseDate": {
            "type": "string",
            "format": "datetime",
            "description": "Original release date"
          },
          "genre": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Music genres"
          },
          "condition": {
            "type": "string",
            "description": "Vinyl condition (Mint, Near Mint, etc.)"
          },
          "notes": {
            "type": "string",
            "description": "Collector notes"
          }
        }
      }
    }
  }
}

List Albums by Genre#

curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.getRecords" \
  -H "Content-Type: application/json" \
  -d '{
    "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
    "where": { "genre": { "contains": "grunge" } },
    "sortBy": [{ "field": "releaseDate", "direction": "desc" }],
    "limit": 10
  }'

Add New Album to Collection#

curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.createRecord" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
    "record": {
      "$type": "com.recordcollector.album",
      "title": "Superunknown",
      "artist": "Soundgarden",
      "releaseDate": "1994-03-08T00:00:00.000Z",
      "genre": ["grunge", "alternative metal"],
      "condition": "Near Mint",
      "notes": "Limited edition orange vinyl"
    }
  }'

Search Collection by Condition#

curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.getRecords" \
  -H "Content-Type: application/json" \
  -d '{
    "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
    "where": {
      "condition": { "in": ["Mint", "Near Mint"] },
      "releaseDate": { "contains": "199" }
    },
    "sortBy": [{ "field": "artist", "direction": "asc" }]
  }'

Count Albums in Collection#

curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.countRecords" \
  -H "Content-Type: application/json" \
  -d '{
    "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
    "where": { "condition": { "eq": "Mint" } }
  }'

Update Album Condition#

curl -X POST "https://api.slices.network/xrpc/com.recordcollector.album.updateRecord" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "slice": "at://did:plc:abc123/network.slices.slice/xyz789",
    "rkey": "3abc456def",
    "record": {
      "$type": "com.recordcollector.album",
      "title": "Ten",
      "artist": "Pearl Jam",
      "releaseDate": "1991-08-27T00:00:00.000Z",
      "genre": ["grunge", "alternative rock"],
      "condition": "Very Good",
      "notes": "Updated after closer inspection - slight scuffs on Side B"
    }
  }'

Next Steps#