{
  "openapi": "3.1.0",
  "info": {
    "title": "Pexafy API",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://api.pexafy.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/v1/search/photos": {
      "get": {
        "tags": [
          "Search"
        ],
        "summary": "Search photos by text",
        "description": "Search the photo library with **natural language**, not keywords. Pexafy understands the *meaning, mood and story* of a scene, so full descriptive sentences return far better matches than a couple of tags. For example:\n\n- `an old man sitting at a café table he has visited every morning for thirty years`\n- `two people sharing a bench in comfortable silence`\n- `the last sunlight of the day hitting a dusty windowsill`\n- `a child discovering snow for the first time`\n\nShort queries like `mountain sunset` still work, but the more you describe the scene, light and emotion you have in mind, the closer the results.\n\nYou can combine your text query with filters (color, orientation, source, license, photographer, date) to narrow the results. **At least one criterion is required**: either a text query (`q`) or one of the filters.\n\n### What you get back\nA list of photos in `data`. The most useful fields on each photo are:\n\n| Field | Description |\n| --- | --- |\n| `photo_id` | Unique Pexafy identifier — use it with the **Photos** and **Collections** endpoints. |\n| `urls` | Ready-to-use image links in five sizes: `thumb`, `small`, `regular`, `large`, `full`. |\n| `description` / `alt_description` | A short caption and accessibility-friendly text. |\n| `color_name`, `color_hex`, `orientation` | Visual attributes of the photo. |\n| `source`, `license_type` | Where the photo comes from and how it may be used. |\n| `photographer_username`, `attribution` | Credit information. `attribution.html` and `attribution.plain` are ready to display. |\n| `relevance_score` | How closely the photo matches your query, from `0` to `1` (higher is better). |\n\nResults are returned page by page — see the [Pagination](/pagination) guide to fetch the next page.",
        "operationId": "search_photos_api_v1_search_photos_get",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 500
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            },
            "description": "Your search query in plain language — full descriptive sentences work best (e.g. `two people sharing a bench in comfortable silence`), though short queries like `mountain sunset` are fine too. Up to 500 characters. Optional if you provide at least one filter instead."
          },
          {
            "name": "color_name",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Color Name"
            },
            "description": "Keep only photos whose dominant color matches this name (e.g. `blue`, `red`, `teal`). Call `GET /api/v1/facets/colors` (see the **Facets** section) to get the list of available color names. Cannot be combined with `color_hex`."
          },
          {
            "name": "color_hex",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Color Hex"
            },
            "description": "Keep only photos close to this hex color (e.g. `#1E90FF`). Cannot be combined with `color_name`. Use `color_tolerance` to widen or tighten the match."
          },
          {
            "name": "color_tolerance",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 255,
                  "minimum": 0
                },
                {
                  "type": "null"
                }
              ],
              "title": "Color Tolerance"
            },
            "description": "How far a photo's color may be from `color_hex` and still match, from `0` (exact match) to `255` (very loose). Defaults to `20`. Only applies when `color_hex` is set."
          },
          {
            "name": "orientation",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "title": "Orientation"
            },
            "description": "Keep only photos with these shapes: `landscape`, `portrait` and/or `square`. Repeat the parameter to pass several. See `GET /api/v1/facets/orientations`."
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "title": "Source"
            },
            "description": "Keep only photos from these providers (e.g. `Pexels`, `Unsplash`, `Pixabay`). Repeat the parameter to pass several. Call `GET /api/v1/facets/sources` to list every available source."
          },
          {
            "name": "license_type",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "title": "License Type"
            },
            "description": "Keep only photos with these license types (e.g. `free`). Call `GET /api/v1/facets/licenses` to list the available license types."
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 100,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Per Page"
            },
            "description": "Number of photos per page, from 1 to 100. Defaults to 20."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 100,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum TOTAL number of results to return across all pages — NOT the page size (use `per_page` for that). e.g. limit=4 with per_page=2 returns two pages of 2 results, then stops. Omit for no cap.",
              "title": "Limit"
            },
            "description": "Maximum TOTAL number of results to return across all pages — NOT the page size (use `per_page` for that). e.g. limit=4 with per_page=2 returns two pages of 2 results, then stops. Omit for no cap."
          },
          {
            "name": "score_threshold",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "number",
                  "maximum": 1.0,
                  "minimum": 0.0
                },
                {
                  "type": "null"
                }
              ],
              "title": "Score Threshold"
            },
            "description": "Minimum relevance a photo must reach to appear, from `0` to `1`. Raise it (e.g. `0.3`) to keep only strong matches and drop loosely related photos; leave it unset to get the widest set of results."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            },
            "description": "Token used to fetch the next page. Take the `pagination.next_cursor` value from a previous response and pass it back here. See the [Pagination](/pagination) guide."
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Fields"
            },
            "description": "Comma-separated list to return only the fields you need (e.g. `photo_id,urls,attribution`), which makes responses smaller. Omit to get every field your plan allows."
          },
          {
            "name": "after_date",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only return photos published on or after this date, formatted `YYYY-MM-DD`.",
              "title": "After Date"
            },
            "description": "Only return photos published on or after this date, formatted `YYYY-MM-DD`."
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "enum": [
                    "relevance",
                    "newest"
                  ],
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Order of the results: `relevance` (default — best match first) or `newest` (most recently added first).",
              "title": "Sort By"
            },
            "description": "Order of the results: `relevance` (default — best match first) or `newest` (most recently added first)."
          },
          {
            "name": "photographer",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only return photos from this photographer's username. Use `GET /api/v1/facets/photographers/suggest` to find usernames.",
              "title": "Photographer"
            },
            "description": "Only return photos from this photographer's username. Use `GET /api/v1/facets/photographers/suggest` to find usernames."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Search photos by image",
        "description": "Upload an image and get visually similar photos in return — same subject, composition, colors or style. Ideal for finding alternatives to a photo you already have.\n\nYou can also pass a text query (`q`) together with the image to steer the results: the search then balances *what the image looks like* with *what your words describe*. Use `text_alpha` to control that balance.\n\n**Accepted formats:** JPEG, PNG, WebP or AVIF, up to 10 MB.\n\nThe same filters as text search are available, and the response has the exact same shape — see **Search photos by text** for the list of fields you get back.",
        "operationId": "search_photos_by_image_api_v1_search_photos_post",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 500
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional words, in plain language, to steer the visual match (e.g. `the same scene but at golden hour` or `warmer and more cheerful`). When set, results match both the picture and your text.",
              "title": "Q"
            },
            "description": "Optional words, in plain language, to steer the visual match (e.g. `the same scene but at golden hour` or `warmer and more cheerful`). When set, results match both the picture and your text."
          },
          {
            "name": "text_alpha",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "number",
                  "maximum": 10.0,
                  "minimum": 0.0
                },
                {
                  "type": "null"
                }
              ],
              "description": "Balance between your text and the image when both are provided, from `0` to `10`. `0` ignores the text (pure visual search), `1.7` (the default) is balanced, and higher values give your words more weight. Has no effect without `q`.",
              "title": "Text Alpha"
            },
            "description": "Balance between your text and the image when both are provided, from `0` to `10`. `0` ignores the text (pure visual search), `1.7` (the default) is balanced, and higher values give your words more weight. Has no effect without `q`."
          },
          {
            "name": "color_name",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Color Name"
            },
            "description": "Keep only photos whose dominant color matches this name (e.g. `blue`, `red`, `teal`). Call `GET /api/v1/facets/colors` (see the **Facets** section) to get the list of available color names. Cannot be combined with `color_hex`."
          },
          {
            "name": "color_hex",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Color Hex"
            },
            "description": "Keep only photos close to this hex color (e.g. `#1E90FF`). Cannot be combined with `color_name`. Use `color_tolerance` to widen or tighten the match."
          },
          {
            "name": "color_tolerance",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 255,
                  "minimum": 0
                },
                {
                  "type": "null"
                }
              ],
              "title": "Color Tolerance"
            },
            "description": "How far a photo's color may be from `color_hex` and still match, from `0` (exact match) to `255` (very loose). Defaults to `20`. Only applies when `color_hex` is set."
          },
          {
            "name": "orientation",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "title": "Orientation"
            },
            "description": "Keep only photos with these shapes: `landscape`, `portrait` and/or `square`. Repeat the parameter to pass several. See `GET /api/v1/facets/orientations`."
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "title": "Source"
            },
            "description": "Keep only photos from these providers (e.g. `Pexels`, `Unsplash`, `Pixabay`). Repeat the parameter to pass several. Call `GET /api/v1/facets/sources` to list every available source."
          },
          {
            "name": "license_type",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "null"
                }
              ],
              "title": "License Type"
            },
            "description": "Keep only photos with these license types (e.g. `free`). Call `GET /api/v1/facets/licenses` to list the available license types."
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Per Page"
            },
            "description": "Number of photos per page, from 1 to 100. Defaults to 20."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 100,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum TOTAL number of results to return across all pages — NOT the page size (use `per_page` for that). Omit for no cap.",
              "title": "Limit"
            },
            "description": "Maximum TOTAL number of results to return across all pages — NOT the page size (use `per_page` for that). Omit for no cap."
          },
          {
            "name": "score_threshold",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "number",
                  "maximum": 1.0,
                  "minimum": 0.0
                },
                {
                  "type": "null"
                }
              ],
              "title": "Score Threshold"
            },
            "description": "Minimum relevance a photo must reach to appear, from `0` to `1`. Raise it (e.g. `0.3`) to keep only strong matches and drop loosely related photos; leave it unset to get the widest set of results."
          },
          {
            "name": "after_date",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only return photos published on or after this date, formatted `YYYY-MM-DD`.",
              "title": "After Date"
            },
            "description": "Only return photos published on or after this date, formatted `YYYY-MM-DD`."
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "enum": [
                    "relevance",
                    "newest"
                  ],
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Order of the results: `relevance` (default — best match first) or `newest` (most recently added first).",
              "title": "Sort By"
            },
            "description": "Order of the results: `relevance` (default — best match first) or `newest` (most recently added first)."
          },
          {
            "name": "photographer",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only return photos from this photographer's username. Use `GET /api/v1/facets/photographers/suggest` to find usernames.",
              "title": "Photographer"
            },
            "description": "Only return photos from this photographer's username. Use `GET /api/v1/facets/photographers/suggest` to find usernames."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Token to fetch the next page. Take `pagination.next_cursor` from a previous response and pass it back here — no need to re-upload the image. See the Pagination guide.",
              "title": "Cursor"
            },
            "description": "Token to fetch the next page. Take `pagination.next_cursor` from a previous response and pass it back here — no need to re-upload the image. See the Pagination guide."
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_search_photos_by_image_api_v1_search_photos_post"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/photos/{photo_id}": {
      "get": {
        "tags": [
          "Photos"
        ],
        "summary": "Get a photo",
        "operationId": "get_photo_api_v1_photos__photo_id__get",
        "parameters": [
          {
            "name": "photo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Photo Id"
            },
            "description": "The photo's unique Pexafy identifier (a UUID), as returned by search."
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Fields"
            },
            "description": "Comma-separated list to return only the fields you need (e.g. `photo_id,urls,attribution`). Omit to get everything."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Retrieve the full details of a single photo by its Pexafy `photo_id` (the identifier returned by every search result).\n\nYou get everything search returns, plus extra metadata when available: exact `width` and `height`, the original `source_image_url`, the photographer's `full_name` and profile `url`, and the upload date (`uploaded_on`). The `urls` object gives you the image in five ready-to-use sizes."
      }
    },
    "/api/v1/photos/{photo_id}/similar": {
      "get": {
        "tags": [
          "Photos"
        ],
        "summary": "Find similar photos",
        "operationId": "photo_similar_api_v1_photos__photo_id__similar_get",
        "parameters": [
          {
            "name": "photo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Photo Id"
            },
            "description": "The reference photo's unique Pexafy identifier (a UUID)."
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Per Page"
            },
            "description": "Number of similar photos to return, from 1 to 100. Defaults to 20."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 100,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum TOTAL number of similar photos across all pages — NOT the page size (use `per_page` for that). Omit for no cap.",
              "title": "Limit"
            },
            "description": "Maximum TOTAL number of similar photos across all pages — NOT the page size (use `per_page` for that). Omit for no cap."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Token to fetch the next page. Take `pagination.next_cursor` from a previous response and pass it back here. See the Pagination guide.",
              "title": "Cursor"
            },
            "description": "Token to fetch the next page. Take `pagination.next_cursor` from a previous response and pass it back here. See the Pagination guide."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Return photos that look similar to a given one — a quick way to offer alternatives or build a visually consistent set. The reference photo itself is never included in the results. Each result has the same fields as a search result."
      }
    },
    "/api/v1/facets/colors": {
      "get": {
        "tags": [
          "Facets"
        ],
        "summary": "List colors",
        "description": "List the dominant colors you can filter photos by. Each entry has a `name` (pass it as `color_name` when searching) and its `hex` code — handy for building a color picker.\n\n> **Facets** are simply the lists of values that the search filters accept. Read them once to populate your filter UI, then feed the chosen value back into **Search photos**.",
        "operationId": "facet_colors_api_v1_facets_colors_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ColorsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/facets/sources": {
      "get": {
        "tags": [
          "Facets"
        ],
        "summary": "List sources",
        "description": "List the photo providers available in the library (for example Unsplash, Pexels, Pixabay). Use a `name` as the `source` filter when searching. Each entry also includes a `license_url` pointing to that provider's licensing terms.",
        "operationId": "facet_sources_api_v1_facets_sources_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SourcesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/facets/orientations": {
      "get": {
        "tags": [
          "Facets"
        ],
        "summary": "List orientations",
        "description": "List the available photo shapes — `landscape`, `portrait` and `square`. Use a `name` as the `orientation` filter when searching.",
        "operationId": "facet_orientations_api_v1_facets_orientations_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrientationsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/facets/licenses": {
      "get": {
        "tags": [
          "Facets"
        ],
        "summary": "List license types",
        "description": "List the license types available in the library. Use a `name` as the `license_type` filter when searching to keep only photos you are allowed to use in a given way.",
        "operationId": "facet_licenses_api_v1_facets_licenses_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicensesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/facets/photographers/suggest": {
      "get": {
        "tags": [
          "Facets"
        ],
        "summary": "Search photographers",
        "description": "Autocomplete photographer names as the user types. Pass a partial name or username in `q` and get back the best-matching photographers, the most prolific first. Use a returned `username` as the `photographer` filter when searching.",
        "operationId": "suggest_photographers_api_v1_facets_photographers_suggest_get",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100,
              "description": "What the user has typed so far — a partial name or username (1–100 characters).",
              "title": "Q"
            },
            "description": "What the user has typed so far — a partial name or username (1–100 characters)."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "default": 10,
              "title": "Limit"
            },
            "description": "Maximum number of suggestions to return, from 1 to 50. Defaults to 10."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotographersResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/facets/photographers/{username}": {
      "get": {
        "tags": [
          "Facets"
        ],
        "summary": "Get a photographer's profiles",
        "description": "Return every profile for a photographer across providers. The same `username` can exist on several sources (Unsplash, Pexels, Pixabay) and may even be different people, so this returns a **list** — one entry per source, each with its own `full_name`, profile `url` and per-source `photos_count`.",
        "operationId": "get_photographer_api_v1_facets_photographers__username__get",
        "parameters": [
          {
            "name": "username",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Username"
            },
            "description": "The photographer's exact username, as returned by the suggest endpoint or found on a photo."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotographerResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/collections": {
      "get": {
        "tags": [
          "Collections"
        ],
        "summary": "List collections",
        "description": "List all the collections (saved photo albums) that belong to your account, newest first. Each entry includes its `name`, `description`, `photos_count` and `cover_photo_id`.\n\n> A **collection** is a named group of photos you save to your account, like an album or a moodboard.",
        "operationId": "list_collections_api_v1_collections_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Collections"
        ],
        "summary": "Create a collection",
        "description": "Create a new collection (a saved album of photos). Your plan may limit how many collections you can have; if you reach the limit you'll get a `403` asking you to upgrade.",
        "operationId": "create_collection_api_v1_collections_post",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionCreateBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/collections/{collection_id}": {
      "get": {
        "tags": [
          "Collections"
        ],
        "summary": "Get a collection",
        "description": "Retrieve a single collection together with the photos it contains, the most recently added first.",
        "operationId": "get_collection_api_v1_collections__collection_id__get",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Collection Id"
            },
            "description": "The collection's numeric identifier."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Collections"
        ],
        "summary": "Delete a collection",
        "description": "Permanently delete a collection and remove every photo saved in it. This cannot be undone (the original photos in the library are not affected).",
        "operationId": "delete_collection_api_v1_collections__collection_id__delete",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Collection Id"
            },
            "description": "The collection's numeric identifier."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/collections/{collection_id}/photos": {
      "post": {
        "tags": [
          "Collections"
        ],
        "summary": "Add a photo to a collection",
        "description": "Save a photo into a collection. The photo automatically becomes the collection's cover if it is the first one added. Adding the same photo twice returns a `409`.",
        "operationId": "add_photo_to_collection_api_v1_collections__collection_id__photos_post",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Collection Id"
            },
            "description": "The numeric identifier of the collection to add the photo to."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddPhotoBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionItemResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/collections/{collection_id}/photos/{photo_id}": {
      "delete": {
        "tags": [
          "Collections"
        ],
        "summary": "Remove a photo from a collection",
        "description": "Remove a photo from a collection. If it was the cover, the most recently added remaining photo becomes the new cover.",
        "operationId": "remove_photo_from_collection_api_v1_collections__collection_id__photos__photo_id__delete",
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Collection Id"
            },
            "description": "The numeric identifier of the collection to remove the photo from."
          },
          {
            "name": "photo_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Photo Id"
            },
            "description": "The Pexafy `photo_id` of the photo to remove from the collection."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Current month usage",
        "description": "See how many API requests you have made during the current billing month and how many you have left under your plan. Counters update in real time.\n\nThe response contains the `period` (e.g. `2026-06`) and a `requests` object with `used`, `limit` and `remaining`.",
        "operationId": "get_usage_api_v1_usage_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Usage counters for the current month.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/usage/daily": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Daily usage history",
        "description": "Get your request count for each day over a recent window (up to the last 90 days), oldest day first. Useful for drawing a usage chart. Days older than 90 days are not kept.",
        "operationId": "get_daily_usage_api_v1_usage_daily_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "How many days back to include, from 1 to 90. Defaults to 30.",
              "default": 30,
              "title": "Days"
            },
            "description": "How many days back to include, from 1 to 90. Defaults to 30."
          }
        ],
        "responses": {
          "200": {
            "description": "List of daily usage records for the requested period.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyUsageResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/usage/monthly": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Monthly usage history",
        "description": "Get your total request count for each month (up to the last 24), the most recent month first. Useful for tracking long-term usage and billing history.",
        "operationId": "get_monthly_usage_api_v1_usage_monthly_get",
        "parameters": [
          {
            "name": "months",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 24,
              "minimum": 1,
              "description": "How many months to include, from 1 to 24. Defaults to 12.",
              "default": 12,
              "title": "Months"
            },
            "description": "How many months to include, from 1 to 24. Defaults to 12."
          }
        ],
        "responses": {
          "200": {
            "description": "List of monthly usage records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonthlyUsageResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/usage/by-key": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Usage by API key",
        "description": "Break your usage down by individual API key — see this month's and today's request count for each active key. Handy for spotting which key (or which app) drives the most traffic.",
        "operationId": "get_usage_by_key_api_v1_usage_by_key_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of API keys with their individual usage counters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageByKeyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AddPhotoBody": {
        "properties": {
          "photo_id": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Photo Id"
          },
          "photo_thumbnail_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "title": "Photo Thumbnail Url"
          },
          "photo_source": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "Photo Source"
          },
          "photo_photographer": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "title": "Photo Photographer"
          }
        },
        "type": "object",
        "required": [
          "photo_id"
        ],
        "title": "AddPhotoBody"
      },
      "Body_search_photos_by_image_api_v1_search_photos_post": {
        "properties": {
          "image": {
            "type": "string",
            "format": "binary",
            "title": "Image",
            "description": "Image file (JPEG, PNG, WebP, or AVIF)"
          }
        },
        "type": "object",
        "title": "Body_search_photos_by_image_api_v1_search_photos_post",
        "required": [
          "image"
        ]
      },
      "CollectionCreateBody": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "is_public": {
            "type": "boolean",
            "title": "Is Public",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "CollectionCreateBody"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      },
      "Meta": {
        "type": "object",
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Unique id for this request (quote it in support tickets)."
          },
          "took_ms": {
            "type": "number",
            "description": "Server processing time in milliseconds."
          }
        }
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code (e.g. `MISSING_PARAMS`, `PHOTO_NOT_FOUND`)."
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message."
          },
          "request_id": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass back as `cursor` for the next page; `null` when `has_more` is false."
          },
          "per_page": {
            "type": "integer",
            "description": "Number of items per page."
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether another page exists."
          }
        }
      },
      "PhotoUrls": {
        "type": "object",
        "description": "Ready-to-use image links in five sizes.",
        "properties": {
          "thumb": {
            "type": "string",
            "format": "uri"
          },
          "small": {
            "type": "string",
            "format": "uri"
          },
          "regular": {
            "type": "string",
            "format": "uri"
          },
          "large": {
            "type": "string",
            "format": "uri"
          },
          "full": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Attribution": {
        "type": "object",
        "description": "Ready-to-display credit for the photographer/source.",
        "properties": {
          "html": {
            "type": "string",
            "description": "HTML attribution snippet."
          },
          "plain": {
            "type": "string",
            "description": "Plain-text attribution."
          }
        }
      },
      "Photo": {
        "type": "object",
        "description": "A photo result. Fields returned can be narrowed with the `fields` parameter and may depend on your plan.",
        "properties": {
          "photo_id": {
            "type": "string",
            "description": "Unique Pexafy identifier (UUID)."
          },
          "image_url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical source image URL."
          },
          "urls": {
            "$ref": "#/components/schemas/PhotoUrls"
          },
          "width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "blur_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "BlurHash placeholder string."
          },
          "orientation": {
            "type": "string",
            "enum": [
              "landscape",
              "portrait",
              "square"
            ]
          },
          "color_name": {
            "type": "string",
            "description": "Dominant color name."
          },
          "color_hex": {
            "type": "string",
            "description": "Dominant color hex code."
          },
          "photographer_username": {
            "type": "string"
          },
          "photographer_full_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "photographer_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "source": {
            "type": "string",
            "description": "Provider (e.g. `Pexels`, `Unsplash`, `Pixabay`)."
          },
          "license_type": {
            "type": "string",
            "description": "License type (e.g. `free`)."
          },
          "source_image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "URL of the photo's page on the provider."
          },
          "source_description": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "AI-generated caption."
          },
          "alt_description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Accessibility-friendly text."
          },
          "uploaded_on": {
            "type": [
              "string",
              "null"
            ],
            "description": "Publication date (YYYY-MM-DD)."
          },
          "relevance_score": {
            "type": [
              "number",
              "null"
            ],
            "description": "Match score 0–1 (higher is better). Only on search results."
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        }
      },
      "Collection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_public": {
            "type": "boolean"
          },
          "cover_photo_id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "photos_count": {
            "type": "integer"
          }
        }
      },
      "CollectionItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "photo_id": {
            "type": "string"
          },
          "photo_thumbnail_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "photo_source": {
            "type": [
              "string",
              "null"
            ]
          },
          "photo_photographer": {
            "type": [
              "string",
              "null"
            ]
          },
          "added_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Photographer": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          },
          "full_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": "string"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "photos_count": {
            "type": "integer"
          }
        }
      },
      "PhotoListResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Photo"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          },
          "pagination": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Pagination"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PhotoResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "$ref": "#/components/schemas/Photo"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ColorsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "hex": {
                  "type": "string"
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "SourcesResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "license_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "OrientationsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "LicensesResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PhotographersResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Photographer"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PhotographerResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Photographer"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CollectionListResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Collection"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CollectionResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Collection"
              },
              {
                "type": "object",
                "properties": {
                  "photos": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/CollectionItem"
                    }
                  }
                }
              }
            ]
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CollectionItemResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "$ref": "#/components/schemas/CollectionItem"
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "DeletedResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "deleted": {
                "type": "boolean"
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "UsageResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "period": {
                "type": "string",
                "description": "YYYY-MM"
              },
              "requests": {
                "type": "object",
                "properties": {
                  "used": {
                    "type": "integer"
                  },
                  "limit": {
                    "type": "integer"
                  },
                  "remaining": {
                    "type": "integer"
                  }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "DailyUsageResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "period_days": {
                "type": "integer"
              },
              "records": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "date": {
                      "type": "string"
                    },
                    "requests": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "MonthlyUsageResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "period_months": {
                "type": "integer"
              },
              "records": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "month": {
                      "type": "string",
                      "description": "YYYY-MM"
                    },
                    "requests": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "UsageByKeyResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "keys": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "key_id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "last_used_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "requests_this_month": {
                      "type": "integer"
                    },
                    "requests_today": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/Meta"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApiError"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Pass your Pexafy API key in this header."
      }
    }
  }
}
