{ "openapi": "3.1.1", "info": { "title": "Clippr AppView API", "version": "1.0.1", "description": "API reference documentation for Clippr's backend.", "license": { "name": "GNU Affero General Public License v3.0 only", "identifier": "AGPL-3.0-only" } }, "servers": [ { "url": "http://localhost:9090", "description": "Development server" }, { "url": "https://api.clippr.social", "description": "Production server" } ], "tags": [ { "name": "Clips", "description": "API paths that relate to user bookmarks, or 'clips'." }, { "name": "Tags", "description": "API paths that relate to user tags." }, { "name": "Profile", "description": "API paths that relate to user profiles." }, { "name": "Misc", "description": "API paths that don't fit into any other category." } ], "paths": { "/xrpc/social.clippr.actor.getPreferences": { "get": { "tags": ["Profile"], "summary": "Get a user's preferences", "operationId": "social.clippr.actor.getPreferences", "description": "Get a user's private preferences. Requires authentication.", "security": [ { "Bearer": [] } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/social.clippr.actor.defs.preferences" } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" }, { "const": "ExpiredToken" }, { "const": "InvalidToken" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "AuthMissing" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.actor.getProfile": { "get": { "tags": ["Profile"], "summary": "Get a profile", "operationId": "social.clippr.actor.getProfile", "description": "Get a user's profile based on a given DID or handle.", "parameters": [ { "name": "actor", "in": "query", "description": "Handle or DID of account to fetch profile of", "required": true, "content": { "schema": { "type": "string", "description": "Handle or DID of account to fetch profile of", "format": "at-identifier" } }, "deprecated": false, "allowEmptyValue": false } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "$ref": "#/components/schemas/social.clippr.actor.defs.profileView" } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.actor.putPreferences": { "post": { "tags": ["Profile"], "summary": "Set a user's preferences", "operationId": "social.clippr.actor.putPreferences", "description": "Sets the private preferences attached to the account. Requires authentication.", "security": [ { "Bearer": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "preferences": { "$ref": "#/components/schemas/social.clippr.actor.defs.preferences" } } } } } }, "responses": { "200": { "description": "OK" }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "oneOf": [ { "const": "InvalidRequest" }, { "const": "ExpiredToken" }, { "const": "InvalidToken" } ], "description": "A general error code" }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "AuthMissing" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.actor.searchClips": { "get": { "tags": ["Clips"], "summary": "Search clips", "operationId": "social.clippr.actor.searchClips", "description": "Find clips matching search criteria.", "parameters": [ { "name": "q", "in": "query", "description": "Search query string", "required": true, "schema": { "type": "string", "description": "Search query string" } }, { "name": "limit", "in": "query", "description": "How many clips to return in the query output", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 } }, { "name": "actor", "in": "query", "description": "An actor to filter results to", "required": false, "schema": { "type": "string", "description": "An actor to filter results to", "format": "at-identifier" } }, { "name": "cursor", "in": "query", "description": "A parameter to paginate results", "required": false, "schema": { "type": "string", "description": "A parameter to paginate results" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "cursor": { "type": "string", "description": "A parameter to paginate results" }, "clips": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.clipView" } } } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.actor.searchProfiles": { "get": { "tags": ["Profile"], "summary": "Search profiles", "operationId": "social.clippr.actor.searchProfiles", "description": "Find profiles matching search criteria.", "parameters": [ { "name": "q", "in": "query", "description": "Search query string", "required": false, "schema": { "type": "string", "description": "Search query string" } }, { "name": "limit", "in": "query", "description": "The number of profiles to be returned in the query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 } }, { "name": "cursor", "in": "query", "description": "A parameter used for pagination", "required": false, "schema": { "type": "string", "description": "A parameter used for pagination" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "cursor": { "type": "string", "description": "A parameter used for pagination" }, "actors": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.actor.defs.profileView" } } } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.actor.searchTags": { "get": { "tags": ["Tags"], "summary": "Search tags", "operationId": "social.clippr.actor.searchTags", "description": "Find tags matching search criteria.", "parameters": [ { "name": "q", "in": "query", "description": "Search query string", "required": true, "schema": { "type": "string", "description": "Search query string" } }, { "name": "limit", "in": "query", "description": "How many tags to return in the query output", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 } }, { "name": "actor", "in": "query", "description": "An actor to filter results to", "required": false, "schema": { "type": "string", "description": "An actor to filter results to", "format": "at-identifier" } }, { "name": "cursor", "in": "query", "description": "A parameter to paginate results", "required": false, "schema": { "type": "string", "description": "A parameter to paginate results" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "cursor": { "type": "string", "description": "A parameter to paginate results" }, "tags": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.tagView" } } } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.feed.getClips": { "get": { "tags": ["Clips"], "summary": "Get clips", "operationId": "social.clippr.feed.getClips", "description": "Get the hydrated views of a list of clips from their AT URIs.", "parameters": [ { "name": "uris", "in": "query", "description": "List of tag AT-URIs to return hydrated views for", "required": true, "schema": { "type": "array", "items": { "type": "string", "format": "at-uri" }, "maxItems": 25 } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.clipView" } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.feed.getTags": { "get": { "tags": ["Tags"], "summary": "Get tags", "operationId": "social.clippr.feed.getTags", "description": "Get a the hydrated views of a list of tags from their AT URIs.", "parameters": [ { "name": "uris", "in": "query", "description": "List of tag AT-URIs to return hydrated views for", "required": true, "schema": { "type": "array", "items": { "type": "string", "format": "at-uri" }, "maxItems": 25 } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.tagView" } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.feed.getProfileClips": { "get": { "tags": ["Clips"], "summary": "Get a profile's clip feed", "operationId": "social.clippr.feed.getProfileClips", "description": "Get a view of a profile's reverse-chronological clips feed.", "parameters": [ { "name": "actor", "in": "query", "description": "An actor to get feed data from", "required": true, "schema": { "type": "string", "description": "An actor to get feed data from", "format": "at-identifier" } }, { "name": "limit", "in": "query", "description": "How many results to return with the query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }, { "name": "cursor", "in": "query", "description": "A parameter to paginate results", "required": false, "schema": { "type": "string", "description": "A parameter to paginate results" } }, { "name": "filter", "in": "query", "description": "What types to include in response", "required": false, "schema": { "type": "string", "description": "What types of clips to include in response", "default": "all_clips", "enum": ["all_clips", "tagged_clips", "untagged_clips"] } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "cursor": { "type": "string" }, "feed": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.clipView" } } } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.feed.getProfileTags": { "get": { "tags": ["Tags"], "summary": "Get a profile's tag feed", "operationId": "social.clippr.feed.getProfileTags", "description": "Get a view of a profile's reverse-chronological clips feed.", "parameters": [ { "name": "actor", "in": "query", "description": "An actor to get feed data from", "required": true, "schema": { "type": "string", "description": "An actor to get feed data from", "format": "at-identifier" } }, { "name": "limit", "in": "query", "description": "How many results to return with the query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }, { "name": "cursor", "in": "query", "description": "A parameter to paginate results", "required": false, "schema": { "type": "string", "description": "A parameter to paginate results" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "cursor": { "type": "string" }, "feed": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.tagView" } } } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "const": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/social.clippr.feed.getTagList": { "get": { "tags": ["Tags"], "summary": "Get a profile's tag list", "operationId": "social.clippr.feed.getProfileTags", "description": "Get a profile's complete list of tags.", "parameters": [ { "name": "actor", "in": "query", "description": "An actor to fetch the tag list from", "required": false, "schema": { "type": "string", "description": "An actor to fetch the tag list from", "format": "at-identifier" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "tags": { "type": "array", "items": { "$ref": "#/components/schemas/social.clippr.feed.defs.tagView" } } } } } } }, "400": { "description": "Bad Request", "content": { "application/json": { "schema": { "type": "object", "properties": { "error": { "type": "string", "description": "A general error code", "oneOf": [ { "error": "InvalidRequest" } ] }, "message": { "type": "string", "description": "A detailed description of the error" } } } } } } } } }, "/xrpc/_health": { "get": { "summary": "Health check", "description": "Check the health of the server. If it is functioning properly, you will receive the server's version number.", "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "version": { "type": "string", "description": "The version number of the AppView." } } } } } } }, "tags": ["Misc"] } } }, "components": { "schemas": { "com.atproto.repo.strongRef": { "type": "object", "required": ["uri", "cid"], "properties": { "uri": { "type": "string", "format": "at-uri" }, "cid": { "type": "string", "format": "cid" } } }, "social.clippr.actor.defs.profileView": { "type": "object", "description": "A view of an actor's profile", "required": ["did", "handle", "displayName"], "properties": { "did": { "type": "string", "description": "The DID of the profile", "format": "did" }, "handle": { "type": "string", "description": "The handle of the profile", "format": "handle" }, "displayName": { "type": "string", "description": "The display name associated to the profile", "maxLength": 64 }, "description": { "type": "string", "description": "The biography associated to the profile", "maxLength": 500 }, "avatar": { "type": "string", "description": "A link to the profile's avatar", "format": "uri" }, "createdAt": { "type": "string", "description": "When the profile record was first created", "format": "date-time" } } }, "social.clippr.actor.defs.preferences": { "type": "array", "items": { "oneOf": [ { "$ref": "#/components/schemas/social.clippr.actor.defs.publishingScopesPref" } ] } }, "social.clippr.actor.defs.publishingScopesPref": { "type": "object", "description": "Preferences for a user's publishing scopes", "required": ["defaultScope"], "properties": { "defaultScope": { "type": "string", "description": "What publishing scope to mark a clip as by default", "enum": ["public", "unlisted"] } } }, "social.clippr.feed.defs.clipView": { "type": "object", "description": "A view of a single bookmark (or 'clip')", "required": ["uri", "cid", "author", "record", "indexedAt"], "properties": { "uri": { "type": "string", "description": "The AT-URI of the clip", "format": "at-uri" }, "cid": { "type": "string", "description": "The CID of the clip", "format": "cid" }, "author": { "description": "A reference to the actor's profile", "$ref": "#/components/schemas/social.clippr.actor.defs.profileView" }, "record": { "type": "object", "description": "The raw record of the clip" }, "indexedAt": { "type": "string", "description": "The time in which the clip's record was indexed by the AppView", "format": "date-time" } } }, "social.clippr.feed.defs.tagView": { "type": "object", "description": "A view of a single tag", "required": ["uri", "cid", "author", "record", "indexedAt"], "properties": { "uri": { "type": "string", "description": "The AT-URI to the tag", "format": "at-uri" }, "cid": { "type": "string", "description": "The CID of the tag", "format": "cid" }, "author": { "description": "A reference to the actor's profile", "$ref": "#/components/schemas/social.clippr.actor.defs.profileView" }, "record": { "type": "object", "description": "The raw record of the clip" }, "indexedAt": { "type": "string", "description": "The time in which the tag's record was indexed by the AppView", "format": "date-time" } } }, "social.clippr.actor.profile": { "type": "object", "required": ["createdAt", "displayName"], "properties": { "displayName": { "type": "string", "description": "A display name to be shown on a profile", "maxLength": 64 }, "description": { "type": "string", "description": "Text for user to describe themselves", "maxLength": 500 }, "avatar": { "type": "blob", "maxSize": 1000000, "description": "Image to show on user's profiles" }, "createdAt": { "type": "string", "description": "The creation date of the profile", "format": "date-time" } } }, "social.clippr.feed.clip": { "type": "object", "required": ["url", "title", "description", "unlisted", "createdAt"], "properties": { "url": { "type": "string", "description": "The URL of the bookmark. Cannot be left empty or be modified after creation.", "format": "uri", "maxLength": 2000 }, "title": { "type": "string", "description": "The title of the bookmark. If left empty, reuse the URL.", "maxLength": 2048 }, "description": { "type": "string", "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.", "maxLength": 4096 }, "notes": { "type": "string", "description": "User-written notes for the bookmark. Public and personal.", "maxLength": 10000 }, "tags": { "type": "array", "description": "An array of tags. A format of solely alphanumeric characters and dashes should be used.", "items": { "$ref": "#/components/schemas/com.atproto.repo.strongRef" } }, "unlisted": { "type": "boolean", "description": "Whether the bookmark can be used for feed indexing and aggregation" }, "unread": { "type": "boolean", "description": "Whether the bookmark has been read by the user", "default": true }, "languages": { "type": "array", "items": { "type": "string", "format": "language" }, "maxItems": 5 }, "createdAt": { "type": "string", "description": "Client-declared timestamp when the bookmark is created", "format": "date-time" } } }, "social.clippr.feed.tag": { "type": "object", "required": ["name", "createdAt"], "properties": { "name": { "type": "string", "description": "A de-duplicated string containing the name of the tag", "maxLength": 64 }, "color": { "type": "string", "description": "A hexadecimal color code", "maxLength": 7 }, "description": { "type": "string", "description": "A description of the tag for additional context", "maxLength": 5000 }, "createdAt": { "type": "string", "description": "A client-defined timestamp for the creation of the tag", "format": "date-time" } } } } } }