{"openapi": "3.1.0", "info": {"title": "AgentGIF API", "version": "1.0.0", "description": "Developer GIF hosting with dual layers: GIF for humans, Cast for agents."}, "paths": {"/api/v1/users/me/": {"get": {"operationId": "listMeProfiles", "description": "GET /api/v1/users/me/ \u2014 authenticated user profile with api_key.\nPATCH /api/v1/users/me/ \u2014 update display_name, bio, website_url.", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}, "patch": {"operationId": "partialUpdateMeProfile", "description": "GET /api/v1/users/me/ \u2014 authenticated user profile with api_key.\nPATCH /api/v1/users/me/ \u2014 update display_name, bio, website_url.", "parameters": [], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"200": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/me/": {"get": {"operationId": "listGifLists", "description": "GET /api/v1/gifs/me/ \u2014 authenticated user's GIFs (all visibilities).", "parameters": [{"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/GifList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/generate/{job_id}/": {"get": {"operationId": "retrievegenerate_status", "description": "Poll status of a tape generation job.\n\nGET /api/v1/gifs/generate/<job_id>/\nReturns 200 with full job status and any generated GIFs.", "parameters": [{"name": "job_id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/": {"get": {"operationId": "listGifLists", "description": "GET /api/v1/gifs/ \u2014 list public GIFs, newest first.", "parameters": [{"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/GifList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/{id}/": {"get": {"operationId": "retrieveGifDetail", "description": "GET /api/v1/gifs/<id>/ \u2014 full detail with embed codes.", "parameters": [{"name": "id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/GifDetail"}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/{id}/cast/": {"get": {"operationId": "listgif_casts", "description": "GET /api/v1/gifs/<id>/cast/ \u2014 redirect to raw cast file on R2.", "parameters": [{"name": "id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/{id}/transcript/": {"get": {"operationId": "listgif_transcripts", "description": "GET /api/v1/gifs/<id>/transcript/ \u2014 plain text transcript.", "parameters": [{"name": "id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/users/{username}/": {"get": {"operationId": "retrieveUserProfile", "description": "GET /api/v1/users/<username>/ \u2014 public profile.", "parameters": [{"name": "username", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/users/{username}/gifs/": {"get": {"operationId": "listGifLists", "description": "GET /api/v1/users/<username>/gifs/ \u2014 user's public GIFs.", "parameters": [{"name": "username", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}, {"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/GifList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/users/{username}/collections/": {"get": {"operationId": "listCollectionLists", "description": "GET /api/v1/users/<username>/collections/ \u2014 user's collections.", "parameters": [{"name": "username", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}, {"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/CollectionList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/tags/": {"get": {"operationId": "listtag_lists", "description": "GET /api/v1/tags/ \u2014 all tags with gif counts.", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/tags/{slug}/gifs/": {"get": {"operationId": "listGifLists", "description": "GET /api/v1/tags/<slug>/gifs/ \u2014 GIFs with a specific tag.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}, {"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/GifList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/": {"get": {"operationId": "listCollectionLists", "description": "GET /api/v1/collections/ \u2014 list all public collections.", "parameters": [{"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/CollectionList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/featured/": {"get": {"operationId": "listCollectionLists", "description": "GET /api/v1/collections/featured/ \u2014 featured collections.", "parameters": [{"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/CollectionList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/": {"get": {"operationId": "retrieveCollectionDetail", "description": "GET /api/v1/collections/<slug>/ \u2014 full detail with ordered GIFs.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CollectionDetail"}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/featured/": {"get": {"operationId": "listGifLists", "description": "GET /api/v1/featured/ \u2014 featured GIFs.", "parameters": [{"name": "page", "required": false, "in": "query", "description": "A page number within the paginated result set.", "schema": {"type": "integer"}}, {"name": "page_size", "required": false, "in": "query", "description": "Number of results to return per page.", "schema": {"type": "integer"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "required": ["count", "results"], "properties": {"count": {"type": "integer", "example": 123}, "next": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=4"}, "previous": {"type": "string", "nullable": true, "format": "uri", "example": "http://api.example.org/accounts/?page=2"}, "results": {"type": "array", "items": {"$ref": "#/components/schemas/GifList"}}}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/search/": {"get": {"operationId": "listsearch_gifs", "description": "GET /api/v1/search/?q=query \u2014 PostgreSQL full-text search.", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/themes/": {"get": {"operationId": "listtheme_lists", "description": "GET /api/v1/themes/ \u2014 all terminal themes, ordered by sort_order.", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/themes/badges/": {"get": {"operationId": "listbadge_themes", "description": "GET /api/v1/themes/badges/ \u2014 List terminal themes available for badges.\n\nReturns themes with preview badge URLs so CLIs can show available options.", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/themes/{slug}/": {"get": {"operationId": "retrievetheme_detail", "description": "GET /api/v1/themes/<slug>/ \u2014 single theme with colors.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/badge-url/": {"get": {"operationId": "listbadge_urls", "description": "GET /api/v1/badge-url/ \u2014 Generate badge URL and embed codes.\n\nQuery params:\n    provider (required): pypi, npm, crates, github\n    package (required): package name (e.g. colorfyi, @fyipedia/colorfyi, owner/repo)\n    metric: version (default), license, downloads, stars, forks, issues\n    theme: terminal theme slug (e.g. dracula)\n    style: default or flat", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/cli/version/": {"get": {"operationId": "listcli_versions", "description": "GET /api/v1/cli/version/ \u2014 CLI version information for update checks.\n\nReturns the latest CLI version, minimum supported version, and changelog URL.\nCLIs call this on startup to check if an update is available.", "parameters": [], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array", "items": {}}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/users/me/api-key/reset/": {"post": {"operationId": "createMeApiKeyReset", "description": "POST /api/v1/users/me/api-key/reset/ \u2014 regenerate API key.", "parameters": [], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"201": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/generate/": {"post": {"operationId": "creategenerate_create", "description": "Create a new tape generation job.\n\nPOST /api/v1/gifs/generate/\nReturns 202 Accepted with job ID for polling.", "parameters": [], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"201": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/upload/": {"post": {"operationId": "creategif_upload_api", "description": "POST /api/v1/gifs/ \u2014 upload a GIF via API (requires auth).\n\nAccepts multipart/form-data with:\n  - gif: GIF file (required)\n  - cast: Cast file (optional)\n  - title, description, command, shell, visibility, tags (optional)", "parameters": [], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"201": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/create/": {"post": {"operationId": "createCollectionCreate", "description": "POST /api/v1/collections/ \u2014 create a new collection.", "parameters": [], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CollectionCreate"}}, "application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/CollectionCreate"}}, "multipart/form-data": {"schema": {"$ref": "#/components/schemas/CollectionCreate"}}}}, "responses": {"201": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CollectionCreate"}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/gifs/": {"post": {"operationId": "createcollection_add_gif", "description": "POST /api/v1/collections/<slug>/gifs/ \u2014 add a GIF to the collection.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"201": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/{id}/edit/": {"patch": {"operationId": "partialUpdateGifUpdate", "description": "PATCH /api/v1/gifs/<id>/ \u2014 edit GIF metadata (owner only).", "parameters": [{"name": "id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/GifUpdate"}}, "application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/GifUpdate"}}, "multipart/form-data": {"schema": {"$ref": "#/components/schemas/GifUpdate"}}}}, "responses": {"200": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/GifUpdate"}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/edit/": {"patch": {"operationId": "partialUpdateCollectionUpdate", "description": "PATCH /api/v1/collections/<slug>/ \u2014 edit collection metadata (owner only).", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CollectionUpdate"}}, "application/x-www-form-urlencoded": {"schema": {"$ref": "#/components/schemas/CollectionUpdate"}}, "multipart/form-data": {"schema": {"$ref": "#/components/schemas/CollectionUpdate"}}}}, "responses": {"200": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CollectionUpdate"}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/feature/": {"patch": {"operationId": "partialUpdatecollection_feature_api", "description": "Toggle is_featured on a collection. Staff only.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"200": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/gifs/reorder/": {"patch": {"operationId": "partialUpdatecollection_reorder_gifs", "description": "PATCH /api/v1/collections/<slug>/gifs/ \u2014 reorder GIFs.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {}}, "application/x-www-form-urlencoded": {"schema": {}}, "multipart/form-data": {"schema": {}}}}, "responses": {"200": {"content": {"application/json": {"schema": {}}}, "description": ""}}, "tags": ["api"]}}, "/api/v1/gifs/{id}/delete/": {"delete": {"operationId": "destroyGifDetail", "description": "DELETE /api/v1/gifs/<id>/ \u2014 soft-delete (owner only).", "parameters": [{"name": "id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"204": {"description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/delete/": {"delete": {"operationId": "destroyCollectionDetail", "description": "DELETE /api/v1/collections/<slug>/ \u2014 delete collection (owner only).", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"204": {"description": ""}}, "tags": ["api"]}}, "/api/v1/collections/{slug}/gifs/{gif_id}/": {"delete": {"operationId": "destroycollection_remove_gif", "description": "DELETE /api/v1/collections/<slug>/gifs/<gif_id>/ \u2014 remove a GIF.", "parameters": [{"name": "slug", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}, {"name": "gif_id", "in": "path", "required": true, "description": "", "schema": {"type": "string"}}], "responses": {"204": {"description": ""}}, "tags": ["api"]}}}, "components": {"schemas": {"GifList": {"type": "object", "properties": {"id": {"type": "string", "readOnly": true}, "slug": {"type": "string", "maxLength": 200, "pattern": "^[-a-zA-Z0-9_]+$"}, "title": {"type": "string", "maxLength": 300}, "command": {"type": "string", "maxLength": 500}, "shell": {"enum": ["zsh", "bash", "fish", "powershell", "sh", "other"], "type": "string"}, "gif_url": {"type": "string", "readOnly": true}, "thumbnail_url": {"type": "string", "readOnly": true}, "width": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "height": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "frames": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "duration_ms": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "file_size_bytes": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "author": {"type": "object", "properties": {"username": {"type": "string"}, "profile_url": {"type": "string", "readOnly": true}, "github_url": {"type": "string", "readOnly": true}}, "required": ["username"]}, "tags": {"type": "array", "items": {"type": "object", "properties": {"slug": {"type": "string", "maxLength": 100, "pattern": "^[-a-zA-Z0-9_]+$"}, "name": {"type": "string", "maxLength": 200}, "description": {"type": "string"}, "category": {"enum": ["command", "tool", "concept", "language", "os"], "type": "string"}, "gif_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}}, "required": ["slug", "name"]}, "readOnly": true}, "view_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "embed_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "homepage_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}, "github_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}, "created_at": {"type": "string", "format": "date-time", "readOnly": true}}, "required": ["slug", "title", "width", "height", "author"]}, "GifDetail": {"type": "object", "properties": {"id": {"type": "string", "readOnly": true}, "slug": {"type": "string", "maxLength": 200, "pattern": "^[-a-zA-Z0-9_]+$"}, "title": {"type": "string", "maxLength": 300}, "description": {"type": "string"}, "command": {"type": "string", "maxLength": 500}, "shell": {"enum": ["zsh", "bash", "fish", "powershell", "sh", "other"], "type": "string"}, "gif_url": {"type": "string", "readOnly": true}, "mp4_url": {"type": "string", "readOnly": true}, "cast_url": {"type": "string", "readOnly": true}, "thumbnail_url": {"type": "string", "readOnly": true}, "transcript": {"type": "string"}, "dimensions": {"type": "string", "readOnly": true}, "frames": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "duration_ms": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "file_size_bytes": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "theme": {"type": "string", "readOnly": true}, "author": {"type": "object", "properties": {"username": {"type": "string"}, "profile_url": {"type": "string", "readOnly": true}, "github_url": {"type": "string", "readOnly": true}}, "required": ["username"]}, "repo": {"type": "object", "properties": {"slug": {"type": "string", "maxLength": 200, "pattern": "^[-a-zA-Z0-9_]+$"}, "url": {"type": "string", "readOnly": true}, "github_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}, "description": {"type": "string"}, "gif_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}}, "required": ["slug"], "readOnly": true}, "tags": {"type": "array", "items": {"type": "object", "properties": {"slug": {"type": "string", "maxLength": 100, "pattern": "^[-a-zA-Z0-9_]+$"}, "name": {"type": "string", "maxLength": 200}, "description": {"type": "string"}, "category": {"enum": ["command", "tool", "concept", "language", "os"], "type": "string"}, "gif_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}}, "required": ["slug", "name"]}, "readOnly": true}, "embed": {"type": "string", "readOnly": true}, "view_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "embed_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "download_count": {"type": "integer", "maximum": 2147483647, "minimum": 0}, "homepage_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}, "github_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}, "visibility": {"enum": ["public", "unlisted"], "type": "string"}, "created_at": {"type": "string", "format": "date-time", "readOnly": true}}, "required": ["slug", "title", "author"]}, "CollectionList": {"type": "object", "properties": {"slug": {"type": "string", "maxLength": 200, "pattern": "^[-a-zA-Z0-9_]+$"}, "title": {"type": "string", "maxLength": 300}, "description": {"type": "string"}, "gif_count": {"type": "string", "readOnly": true}, "cover_gif": {"type": "string", "readOnly": true}, "author": {"type": "object", "properties": {"username": {"type": "string"}, "profile_url": {"type": "string", "readOnly": true}, "github_url": {"type": "string", "readOnly": true}}, "required": ["username"], "readOnly": true}, "url": {"type": "string", "readOnly": true}, "is_featured": {"type": "boolean"}, "created_at": {"type": "string", "format": "date-time", "readOnly": true}}, "required": ["slug", "title"]}, "CollectionDetail": {"type": "object", "properties": {"slug": {"type": "string", "maxLength": 200, "pattern": "^[-a-zA-Z0-9_]+$"}, "title": {"type": "string", "maxLength": 300}, "description": {"type": "string"}, "gifs": {"type": "string", "readOnly": true}, "gif_count": {"type": "string", "readOnly": true}, "author": {"type": "object", "properties": {"username": {"type": "string"}, "profile_url": {"type": "string", "readOnly": true}, "github_url": {"type": "string", "readOnly": true}}, "required": ["username"], "readOnly": true}, "url": {"type": "string", "readOnly": true}, "is_featured": {"type": "boolean"}, "created_at": {"type": "string", "format": "date-time", "readOnly": true}}, "required": ["slug", "title"]}, "CollectionCreate": {"type": "object", "properties": {"title": {"type": "string", "maxLength": 300}, "description": {"type": "string"}}, "required": ["title"]}, "GifUpdate": {"type": "object", "properties": {"title": {"type": "string", "maxLength": 300}, "description": {"type": "string"}, "command": {"type": "string", "maxLength": 500}, "shell": {"enum": ["zsh", "bash", "fish", "powershell", "sh", "other"], "type": "string"}, "visibility": {"enum": ["public", "unlisted"], "type": "string"}, "tags": {"type": "array", "items": {"type": "string"}}, "homepage_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}, "github_url": {"type": "string", "format": "uri", "maxLength": 500, "pattern": "^(?:[a-z0-9.+-]*)://(?:[^\\s:@/]+(?::[^\\s:@/]*)?@)?(?:(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)(?:\\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}|\\[[0-9a-f:.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}[a-z\u00a1-\uffff0-9])?(?:\\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(?<!-))*\\.(?!-)(?:[a-z\u00a1-\uffff-]{2,63}|xn--[a-z0-9]{1,59})(?<!-)\\.?|localhost))(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?\\z"}}, "required": ["title"]}, "CollectionUpdate": {"type": "object", "properties": {"title": {"type": "string", "maxLength": 300}, "description": {"type": "string"}}, "required": ["title"]}}}, "servers": [{"url": "https://agentgif.com", "description": "Production"}]}