Auto-indexing service and GraphQL API for AT Protocol Records quickslice.slices.network/
atproto gleam graphql
at main 281 lines 5.4 kB view raw view rendered
1# Queries 2 3Quickslice generates a GraphQL query for each Lexicon record type at the `/graphql` endpoint. Queries are public; no authentication required. 4 5> **Endpoints:** Lexicon queries and mutations use `/graphql`. Admin operations (labels, reports, settings) use `/admin/graphql`. 6 7## Relay Connections 8 9Queries return data in the [Relay Connection](https://relay.dev/graphql/connections.htm) format: 10 11```graphql 12query { 13 xyzStatusphereStatus { 14 edges { 15 node { 16 uri 17 status 18 createdAt 19 } 20 cursor 21 } 22 pageInfo { 23 hasNextPage 24 endCursor 25 } 26 totalCount 27 } 28} 29``` 30 31- `edges`: Array of results, each containing a `node` (the record) and `cursor` (for pagination) 32- `pageInfo`: Pagination metadata 33- `totalCount`: Total number of matching records 34 35## Built-in Fields 36 37Every record includes these fields automatically: 38 39| Field | Description | 40|-------|-------------| 41| `uri` | The AT-URI of the record | 42| `cid` | Content identifier (hash) | 43| `did` | Author's decentralized identifier | 44| `collection` | The Lexicon collection (e.g., `app.bsky.feed.post`) | 45| `actorHandle` | Author's handle (e.g., `alice.bsky.social`) | 46| `indexedAt` | When Quickslice indexed the record | 47 48The `actorHandle` field resolves the author's DID to their current handle, useful for display without a separate join: 49 50```graphql 51query { 52 xyzStatusphereStatus(first: 10) { 53 edges { 54 node { 55 status 56 actorHandle 57 } 58 } 59 } 60} 61``` 62 63## Filtering 64 65Use the `where` argument to filter records: 66 67```graphql 68query { 69 xyzStatusphereStatus(where: { status: { eq: "🎉" } }) { 70 edges { 71 node { 72 status 73 createdAt 74 } 75 } 76 } 77} 78``` 79 80### Filter Operators 81 82| Operator | Description | Example | 83|----------|-------------|---------| 84| `eq` | Equal to | `{ status: { eq: "👍" } }` | 85| `ne` | Not equal to | `{ status: { ne: "👎" } }` | 86| `in` | In array | `{ status: { in: ["👍", "🎉"] } }` | 87| `contains` | String contains (case-insensitive) | `{ displayName: { contains: "alice" } }` | 88| `gt` | Greater than | `{ createdAt: { gt: "2025-01-01T00:00:00Z" } }` | 89| `lt` | Less than | `{ createdAt: { lt: "2025-06-01T00:00:00Z" } }` | 90| `gte` | Greater than or equal | `{ position: { gte: 1 } }` | 91| `lte` | Less than or equal | `{ position: { lte: 10 } }` | 92| `isNull` | Null check | `{ reply: { isNull: true } }` | 93 94### Filtering Ref Fields 95 96Reference fields (AT-URIs or strong refs pointing to other records) only support `isNull`. Use it to find records with or without a reference: 97 98```graphql 99query { 100 # Find root posts (no reply) 101 appBskyFeedPost(where: { reply: { isNull: true } }) { 102 edges { 103 node { 104 text 105 } 106 } 107 } 108} 109``` 110 111```graphql 112query { 113 # Find replies only 114 appBskyFeedPost(where: { reply: { isNull: false } }) { 115 edges { 116 node { 117 text 118 } 119 } 120 } 121} 122``` 123 124### Multiple Conditions 125 126Combine multiple conditions (they're ANDed together): 127 128```graphql 129query { 130 appBskyActorProfile(where: { 131 displayName: { contains: "alice" } 132 createdAt: { gt: "2025-01-01T00:00:00Z" } 133 }) { 134 edges { 135 node { 136 displayName 137 description 138 } 139 } 140 } 141} 142``` 143 144## Sorting 145 146Use `sortBy` to order results: 147 148```graphql 149query { 150 xyzStatusphereStatus(sortBy: [{ field: createdAt, direction: DESC }]) { 151 edges { 152 node { 153 status 154 createdAt 155 } 156 } 157 } 158} 159``` 160 161### Multi-Field Sorting 162 163Sort by multiple fields (applied in order): 164 165```graphql 166query { 167 appBskyActorProfile(sortBy: [ 168 { field: displayName, direction: ASC } 169 { field: createdAt, direction: DESC } 170 ]) { 171 edges { 172 node { 173 displayName 174 createdAt 175 } 176 } 177 } 178} 179``` 180 181## Pagination 182 183### Forward Pagination 184 185Use `first` to limit results and `after` to get the next page: 186 187```graphql 188# First page 189query { 190 xyzStatusphereStatus(first: 10) { 191 edges { 192 node { status } 193 cursor 194 } 195 pageInfo { 196 hasNextPage 197 endCursor 198 } 199 } 200} 201 202# Next page (use endCursor from previous response) 203query { 204 xyzStatusphereStatus(first: 10, after: "cursor_from_previous_page") { 205 edges { 206 node { status } 207 cursor 208 } 209 pageInfo { 210 hasNextPage 211 endCursor 212 } 213 } 214} 215``` 216 217### Backward Pagination 218 219Use `last` and `before` to paginate backward: 220 221```graphql 222query { 223 xyzStatusphereStatus(last: 10, before: "some_cursor") { 224 edges { 225 node { status } 226 cursor 227 } 228 pageInfo { 229 hasPreviousPage 230 startCursor 231 } 232 } 233} 234``` 235 236### PageInfo Fields 237 238| Field | Description | 239|-------|-------------| 240| `hasNextPage` | More items exist after this page | 241| `hasPreviousPage` | More items exist before this page | 242| `startCursor` | Cursor of the first item | 243| `endCursor` | Cursor of the last item | 244 245## Complete Example 246 247Combining filtering, sorting, and pagination: 248 249```graphql 250query GetRecentStatuses($pageSize: Int!, $cursor: String) { 251 xyzStatusphereStatus( 252 where: { status: { in: ["👍", "🎉", "💙"] } } 253 sortBy: [{ field: createdAt, direction: DESC }] 254 first: $pageSize 255 after: $cursor 256 ) { 257 edges { 258 node { 259 uri 260 status 261 createdAt 262 } 263 cursor 264 } 265 pageInfo { 266 hasNextPage 267 endCursor 268 } 269 totalCount 270 } 271} 272``` 273 274Variables: 275 276```json 277{ 278 "pageSize": 20, 279 "cursor": null 280} 281```