social bookmarking for atproto

[backend] Add models to OpenAPI document

hexmani.ac 66c3593b b7a485ce

verified
+449 -143
+1
.idea/dictionaries/project.xml
··· 1 1 <component name="ProjectDictionaryState"> 2 2 <dictionary name="project"> 3 3 <words> 4 + <w>affero</w> 4 5 <w>agpl</w> 5 6 <w>appview</w> 6 7 <w>atcute</w>
+448 -143
backend/static/api.json
··· 1 1 { 2 - "openapi": "3.1.1", 3 - "servers": [ 4 - { 5 - "url": "http://localhost:9090", 6 - "description": "Development server" 7 - }, 8 - { 9 - "url": "https://clippr.social", 10 - "description": "Production server" 11 - } 12 - ], 13 - "info": { 14 - "title": "Clippr AppView API", 15 - "version": "0.1.0", 16 - "description": "Official API reference documentation for Clippr's backend." 17 - }, 18 - "tags": [ 19 - { 20 - "name": "Profile", 21 - "description": "API paths that relate to user profiles." 22 - }, 23 - { 24 - "name": "Misc", 25 - "description": "API paths that don't fit into any other category." 26 - } 27 - ], 28 - "paths": { 29 - "/xrpc/social.clippr.actor.getProfile": { 30 - "get": { 31 - "summary": "Get a profile", 32 - "description": "Get an user's profile based on their DID or handle.", 33 - "parameters": [ 34 - { 35 - "name": "actor", 36 - "in": "query", 37 - "description": "The DID or handle of the account to get the profile record of.", 38 - "required": true, 39 - "content": { 40 - "schema": { 41 - "type": "string" 42 - } 43 - }, 44 - "deprecated": false, 45 - "allowEmptyValue": false 46 - } 47 - ], 48 - "responses": { 49 - "200": { 50 - "description": "OK", 51 - "content": { 52 - "application/json": { 53 - "schema": { 54 - "type": "object", 55 - "properties": { 56 - "did": { 57 - "type": "string", 58 - "description": "The decentralized identifier associated to the profile.", 59 - "example": "did:plc:z72i7hdynmk6r22z27h6tvur" 60 - }, 61 - "handle": { 62 - "type": "string", 63 - "description": "The handle associated to the profile.", 64 - "example": "alice.bsky.social" 65 - }, 66 - "displayName": { 67 - "type": "string", 68 - "description": "The display name associated to the profile.", 69 - "example": "Alice" 70 - }, 71 - "avatar": { 72 - "type": "string", 73 - "format": "uri", 74 - "description": "A URI linking to an JPEG or PNG file.", 75 - "example": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:b6bhzquz665p6bgjuaqz6xjp/bafkreicoqygyiqhhmjod4hvezo3besjyza24neldcxkz55keos3dg5mmj4@jpeg" 76 - }, 77 - "description": { 78 - "type": "string", 79 - "description": "A biography associated to the profile.", 80 - "example": "This is an example bio." 81 - }, 82 - "createdAt": { 83 - "type": "string", 84 - "format": "date-time", 85 - "description": "The date and time of the creation of the profile record." 86 - } 87 - } 88 - } 89 - } 90 - } 91 - }, 92 - "400": { 93 - "description": "Bad Request", 94 - "content": { 95 - "application/json": { 96 - "schema": { 97 - "type": "object", 98 - "properties": { 99 - "error": { 100 - "type": "string", 101 - "description": "A general error code.", 102 - "example": "InvalidRequest" 103 - }, 104 - "message": { 105 - "type": "string", 106 - "description": "A detailed description of the error.", 107 - "example": "Error: Parameters must have the actor property included" 108 - } 109 - } 110 - } 111 - } 112 - } 113 - } 114 - }, 115 - "tags": ["Profile"] 116 - } 117 - }, 118 - "/xrpc/_health": { 119 - "get": { 120 - "summary": "Health check", 121 - "description": "Check the health of the server. If it is functioning properly, you will receive the server's version number.", 122 - "responses": { 123 - "200": { 124 - "description": "OK", 125 - "content": { 126 - "application/json": { 127 - "schema": { 128 - "type": "object", 129 - "properties": { 130 - "version": { 131 - "type": "string", 132 - "description": "The version number of the AppView.", 133 - "example": "0.1.0" 134 - } 135 - } 136 - } 137 - } 138 - } 139 - } 140 - }, 141 - "tags": ["Misc"] 142 - } 143 - } 144 - } 2 + "openapi": "3.1.1", 3 + "info": { 4 + "title": "Clippr AppView API", 5 + "version": "1.0.0", 6 + "description": "Official API reference documentation for Clippr's backend.", 7 + "license": { 8 + "name": "GNU Affero General Public License v3.0 only", 9 + "identifier": "AGPL-3.0-only" 10 + } 11 + }, 12 + "servers": [ 13 + { 14 + "url": "http://localhost:9090", 15 + "description": "Development server" 16 + }, 17 + { 18 + "url": "https://clippr.social", 19 + "description": "Production server" 20 + } 21 + ], 22 + "tags": [ 23 + { 24 + "name": "Clips", 25 + "description": "API paths that relate to user clips." 26 + }, 27 + { 28 + "name": "Tags", 29 + "description": "API paths that relate to user tags." 30 + }, 31 + { 32 + "name": "Profile", 33 + "description": "API paths that relate to user profiles." 34 + }, 35 + { 36 + "name": "Misc", 37 + "description": "API paths that don't fit into any other category." 38 + } 39 + ], 40 + "paths": { 41 + "/xrpc/social.clippr.actor.getProfile": { 42 + "get": { 43 + "summary": "Get a profile", 44 + "description": "Get an user's profile based on their DID or handle.", 45 + "parameters": [ 46 + { 47 + "name": "actor", 48 + "in": "query", 49 + "description": "The DID or handle of the account to get the profile record of.", 50 + "required": true, 51 + "content": { 52 + "schema": { 53 + "type": "string" 54 + } 55 + }, 56 + "deprecated": false, 57 + "allowEmptyValue": false 58 + } 59 + ], 60 + "responses": { 61 + "200": { 62 + "description": "OK", 63 + "content": { 64 + "application/json": { 65 + "schema": { 66 + "type": "object", 67 + "properties": { 68 + "did": { 69 + "type": "string", 70 + "description": "The decentralized identifier associated to the profile.", 71 + "example": "did:plc:z72i7hdynmk6r22z27h6tvur" 72 + }, 73 + "handle": { 74 + "type": "string", 75 + "description": "The handle associated to the profile.", 76 + "example": "alice.bsky.social" 77 + }, 78 + "displayName": { 79 + "type": "string", 80 + "description": "The display name associated to the profile.", 81 + "example": "Alice" 82 + }, 83 + "avatar": { 84 + "type": "string", 85 + "format": "uri", 86 + "description": "A URI linking to an JPEG or PNG file.", 87 + "example": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:b6bhzquz665p6bgjuaqz6xjp/bafkreicoqygyiqhhmjod4hvezo3besjyza24neldcxkz55keos3dg5mmj4@jpeg" 88 + }, 89 + "description": { 90 + "type": "string", 91 + "description": "A biography associated to the profile.", 92 + "example": "This is an example bio." 93 + }, 94 + "createdAt": { 95 + "type": "string", 96 + "format": "date-time", 97 + "description": "The date and time of the creation of the profile record." 98 + } 99 + } 100 + } 101 + } 102 + } 103 + }, 104 + "400": { 105 + "description": "Bad Request", 106 + "content": { 107 + "application/json": { 108 + "schema": { 109 + "type": "object", 110 + "properties": { 111 + "error": { 112 + "type": "string", 113 + "description": "A general error code.", 114 + "example": "InvalidRequest" 115 + }, 116 + "message": { 117 + "type": "string", 118 + "description": "A detailed description of the error.", 119 + "example": "Error: Parameters must have the actor property included" 120 + } 121 + } 122 + } 123 + } 124 + } 125 + } 126 + }, 127 + "tags": [ 128 + "Profile" 129 + ] 130 + } 131 + }, 132 + "/xrpc/_health": { 133 + "get": { 134 + "summary": "Health check", 135 + "description": "Check the health of the server. If it is functioning properly, you will receive the server's version number.", 136 + "responses": { 137 + "200": { 138 + "description": "OK", 139 + "content": { 140 + "application/json": { 141 + "schema": { 142 + "type": "object", 143 + "properties": { 144 + "version": { 145 + "type": "string", 146 + "description": "The version number of the AppView.", 147 + "example": "0.1.0" 148 + } 149 + } 150 + } 151 + } 152 + } 153 + } 154 + }, 155 + "tags": [ 156 + "Misc" 157 + ] 158 + } 159 + } 160 + }, 161 + "components": { 162 + "schemas": { 163 + "com.atproto.repo.strongRef": { 164 + "type": "object", 165 + "required": [ 166 + "uri", 167 + "cid" 168 + ], 169 + "properties": { 170 + "uri": { 171 + "type": "string", 172 + "format": "at-uri" 173 + }, 174 + "cid": { 175 + "type": "string", 176 + "format": "cid" 177 + } 178 + } 179 + }, 180 + "social.clippr.actor.defs#profileView": { 181 + "type": "object", 182 + "description": "A view of an actor's profile.", 183 + "required": [ 184 + "did", 185 + "handle" 186 + ], 187 + "properties": { 188 + "did": { 189 + "type": "string", 190 + "description": "The DID of the profile", 191 + "format": "did" 192 + }, 193 + "handle": { 194 + "type": "string", 195 + "description": "The handle of the profile", 196 + "format": "handle" 197 + }, 198 + "displayName": { 199 + "type": "string", 200 + "description": "The display name associated to the profile", 201 + "minLength": 1, 202 + "maxLength": 64 203 + }, 204 + "description": { 205 + "type": "string", 206 + "description": "The biography associated to the profile", 207 + "maxLength": 500 208 + }, 209 + "avatar": { 210 + "type": "string", 211 + "description": "A link to the profile's avatar", 212 + "format": "uri" 213 + }, 214 + "createdAt": { 215 + "type": "string", 216 + "description": "When the profile record was first created", 217 + "format": "date-time" 218 + } 219 + } 220 + }, 221 + "social.clippr.actor.defs#preferences": { 222 + "type": "array", 223 + "items": { 224 + "oneOf": [ 225 + { 226 + "$ref": "#/components/schemas/social.clippr.actor.defs#publishingScopesPref" 227 + } 228 + ] 229 + } 230 + }, 231 + "social.clippr.actor.defs#publishingScopesPref": { 232 + "type": "object", 233 + "description": "Preferences for an user's publishing scopes", 234 + "required": [ 235 + "defaultScope" 236 + ], 237 + "properties": { 238 + "defaultScope": { 239 + "type": "string", 240 + "description": "What publishing scope to mark a clip as by default", 241 + "enum": [ 242 + "public", 243 + "unlisted" 244 + ] 245 + } 246 + } 247 + }, 248 + "social.clippr.feed.defs#clipView": { 249 + "type": "object", 250 + "description": "A view of a single bookmark (or 'clip').", 251 + "required": [ 252 + "uri", 253 + "cid", 254 + "author", 255 + "record", 256 + "indexedAt" 257 + ], 258 + "properties": { 259 + "uri": { 260 + "type": "string", 261 + "description": "The AT-URI of the clip", 262 + "format": "at-uri" 263 + }, 264 + "cid": { 265 + "type": "string", 266 + "description": "The CID of the clip", 267 + "format": "cid" 268 + }, 269 + "author": { 270 + "description": "A reference to the actor's profile", 271 + "$ref": "#/components/schemas/social.clippr.actor.defs#profileView" 272 + }, 273 + "record": { 274 + "type": "object", 275 + "description": "The raw record of the clip" 276 + }, 277 + "indexedAt": { 278 + "type": "string", 279 + "description": "The time in which the clip's record was indexed by the AppView", 280 + "format": "date-time" 281 + } 282 + } 283 + }, 284 + "social.clippr.feed.defs#tagView": { 285 + "type": "object", 286 + "description": "A view of a single tag.", 287 + "required": [ 288 + "uri", 289 + "cid", 290 + "author", 291 + "record", 292 + "indexedAt" 293 + ], 294 + "properties": { 295 + "uri": { 296 + "type": "string", 297 + "description": "The AT-URI to the tag", 298 + "format": "at-uri" 299 + }, 300 + "cid": { 301 + "type": "string", 302 + "description": "The CID of the tag", 303 + "format": "cid" 304 + }, 305 + "author": { 306 + "description": "A reference to the actor's profile", 307 + "$ref": "#/components/schemas/social.clippr.actor.defs#profileView" 308 + }, 309 + "record": { 310 + "type": "object", 311 + "description": "The raw record of the clip" 312 + }, 313 + "indexedAt": { 314 + "type": "string", 315 + "description": "The time in which the tag's recoord was indexed by the AppView", 316 + "format": "date-time" 317 + } 318 + } 319 + }, 320 + "social.clippr.actor.profile": { 321 + "type": "object", 322 + "required": [ 323 + "createdAt", 324 + "displayName" 325 + ], 326 + "properties": { 327 + "displayName": { 328 + "type": "string", 329 + "description": "A display name to be shown on a profile", 330 + "minLength": 1, 331 + "maxLength": 64 332 + }, 333 + "description": { 334 + "type": "string", 335 + "description": "Text for user to describe themselves", 336 + "maxLength": 500 337 + }, 338 + "avatar": { 339 + "type": "blob", 340 + "maxSize": 1000000, 341 + "description": "Image to show on user's profiles" 342 + }, 343 + "createdAt": { 344 + "type": "string", 345 + "description": "The creation date of the profile", 346 + "format": "date-time" 347 + } 348 + } 349 + }, 350 + "social.clippr.feed.clip": { 351 + "type": "object", 352 + "required": [ 353 + "url", 354 + "title", 355 + "description", 356 + "unlisted", 357 + "createdAt" 358 + ], 359 + "properties": { 360 + "url": { 361 + "type": "string", 362 + "description": "The URL of the bookmark. Cannot be left empty or be modified after creation.", 363 + "format": "uri", 364 + "minLength": 3, 365 + "maxLength": 2000 366 + }, 367 + "title": { 368 + "type": "string", 369 + "description": "The title of the bookmark. If left empty, reuse the URL.", 370 + "minLength": 1, 371 + "maxLength": 2048 372 + }, 373 + "description": { 374 + "type": "string", 375 + "description": "A description of the bookmark's content. This should be ripped from the URL metadata and be static for all records using the URL.", 376 + "minLength": 1, 377 + "maxLength": 4096 378 + }, 379 + "notes": { 380 + "type": "string", 381 + "description": "User-written notes for the bookmark. Public and personal.", 382 + "minLength": 1, 383 + "maxLength": 10000 384 + }, 385 + "tags": { 386 + "type": "array", 387 + "description": "An array of tags. A format of solely alphanumeric characters and dashes should be used.", 388 + "items": { 389 + "$ref": "#/components/schemas/com.atproto.repo.strongRef" 390 + } 391 + }, 392 + "unlisted": { 393 + "type": "boolean", 394 + "description": "Whether the bookmark can be used for feed indexing and aggregation" 395 + }, 396 + "unread": { 397 + "type": "boolean", 398 + "description": "Whether the bookmark has been read by the user", 399 + "default": true 400 + }, 401 + "languages": { 402 + "type": "array", 403 + "items": { 404 + "type": "string", 405 + "format": "language" 406 + }, 407 + "maxItems": 5 408 + }, 409 + "createdAt": { 410 + "type": "string", 411 + "description": "Client-declared timestamp when the bookmark is created", 412 + "format": "date-time" 413 + } 414 + } 415 + }, 416 + "social.clippr.feed.tag": { 417 + "type": "object", 418 + "required": [ 419 + "name", 420 + "createdAt" 421 + ], 422 + "properties": { 423 + "name": { 424 + "type": "string", 425 + "description": "A de-duplicated string containing the name of the tag", 426 + "minLength": 1, 427 + "maxLength": 64 428 + }, 429 + "color": { 430 + "type": "string", 431 + "description": "A hexadecimal color code", 432 + "minLength": 4, 433 + "maxLength": 7 434 + }, 435 + "description": { 436 + "type": "string", 437 + "description": "A description of the tag for additional context", 438 + "minLength": 1, 439 + "maxLength": 5000 440 + }, 441 + "createdAt": { 442 + "type": "string", 443 + "description": "A client-defined timestamp for the creation of the tag", 444 + "format": "date-time" 445 + } 446 + } 447 + } 448 + } 449 + } 145 450 }