{
  "openapi": "3.1.0",
  "info": {
    "title": "GifSnap GIF Search API",
    "version": "1.0.0",
    "description": "Read-only search, trending, and GIF lookup endpoints. This description covers the current public, best-effort API, which does not require an API key. No SLA or unlimited-capacity commitment is made. Media URLs may use external CDNs and formats such as GIF or WebP; use returned URLs unchanged. Software package licensing does not grant rights to media."
  },
  "servers": [
    {
      "url": "https://gifsnap.com/api/v1"
    }
  ],
  "security": [],
  "paths": {
    "/gifs/search": {
      "get": {
        "operationId": "searchGifs",
        "summary": "Search gifs",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "A non-empty search phrase. URL-encode query parameters.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "One-based page number. Pass a positive integer.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, from 1 to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Media results with pagination. Empty data is a valid result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaPage"
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Read the error message and show a recoverable state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "The q query parameter is missing or empty.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/gifs/trending": {
      "get": {
        "operationId": "trendingGifs",
        "summary": "Trending gifs",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "One-based page number. Pass a positive integer.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, from 1 to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Media results with pagination. Empty data is a valid result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaPage"
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Read the error message and show a recoverable state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/stickers/search": {
      "get": {
        "operationId": "searchStickers",
        "summary": "Search stickers",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "A non-empty search phrase. URL-encode query parameters.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "One-based page number. Pass a positive integer.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, from 1 to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Media results with pagination. Empty data is a valid result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaPage"
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Read the error message and show a recoverable state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "The q query parameter is missing or empty.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/stickers/trending": {
      "get": {
        "operationId": "trendingStickers",
        "summary": "Trending stickers",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "One-based page number. Pass a positive integer.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page, from 1 to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Media results with pagination. Empty data is a valid result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaPage"
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Read the error message and show a recoverable state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/gifs/{id}": {
      "get": {
        "operationId": "getGif",
        "summary": "Read a GIF by its catalog ID",
        "description": "Use an id returned by search or trending. Do not construct IDs from media URLs.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One GIF object, without a data wrapper.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Gif"
                }
              }
            }
          },
          "404": {
            "description": "GIF not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Request could not be completed. Read the error message and show a recoverable state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Gif": {
        "type": "object",
        "required": [
          "id",
          "title",
          "url",
          "preview_url",
          "width",
          "height",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Full media URL. Keep for sending, sharing and full-quality playback; use returned URLs unchanged."
          },
          "preview_url": {
            "type": "string",
            "format": "uri",
            "description": "Poster or legacy preview, which can be static. Do not assume this URL is animated."
          },
          "width": {
            "type": "number",
            "minimum": 0
          },
          "height": {
            "type": "number",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "enum": [
              "gif",
              "sticker"
            ]
          },
          "source": {
            "type": "string",
            "description": "Provider metadata returned by the catalog."
          },
          "created_at": {
            "type": "string"
          },
          "content_id": {
            "type": "string",
            "description": "Optional verified provider identity shared by known alternate encodings of the same item. Use for presentation deduplication when present; preserve the original id for lookups."
          },
          "animated_preview": {
            "$ref": "#/components/schemas/AnimatedPreview"
          }
        }
      },
      "Pagination": {
        "type": "object",
        "required": [
          "page",
          "limit",
          "total",
          "has_next",
          "next_page",
          "offset"
        ],
        "properties": {
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50
          },
          "total": {
            "type": "number",
            "minimum": 0,
            "description": "Reported result count; may change between requests."
          },
          "has_next": {
            "type": "boolean"
          },
          "next_page": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "MediaPage": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Gif"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "query": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "data": {
            "type": "array"
          },
          "pagination": {
            "type": [
              "object",
              "null"
            ]
          }
        }
      },
      "AnimatedPreview": {
        "type": "object",
        "description": "Optional verified small animation for picker grids. Use only when the renderer supports mime_type; fall back to the full url if absent or loading fails. Do not replace the selected item full url with this preview.",
        "required": [
          "url",
          "mime_type",
          "width",
          "height",
          "animated"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "mime_type": {
            "type": "string",
            "enum": [
              "image/gif",
              "image/webp",
              "video/mp4",
              "video/webm"
            ]
          },
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 480
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 480
          },
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 524288
          },
          "animated": {
            "type": "boolean",
            "const": true
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "GifSnap SDK quickstarts and API integration reference",
    "url": "https://gifsnap.com/docs"
  }
}
