{
  "openapi": "3.1.0",
  "x-logo": {
    "url": "./images/vwd-logo.svg"
  },
  "x-apiVersion": "1.0.0",
  "x-changelogUrl": "https://github.com/get-vwd/vwd-docs/releases",
  "info": {
    "title": "VwD External API",
    "description": "External API for accessing VwD creators data.",
    "version": "1.0.0",
    "contact": {
      "name": "VwD API Support",
      "email": "support@vwd.ai"
    },
    "license": {
      "name": "MIT",
      "url": "https://opensource.org/licenses/MIT"
    }
  },
  "servers": [
    {
      "url": "https://api.vwd.ai/api/public/v1",
      "description": "VwD Production API Server"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Creators",
      "description": "Endpoints related to creators information and searches.",
      "x-displayName": "Creator Management"
    },
    {
      "name": "Brands",
      "description": "Endpoints for brand search and management.",
      "x-displayName": "Brand Management"
    },
    {
      "name": "Lists",
      "description": "Endpoints for managing creator lists.",
      "x-displayName": "List Management"
    },
    {
      "name": "X-Ray",
      "description": "Endpoints for retrieving creators posts with labels.",
      "x-displayName": "Content Analysis"
    },
    {
      "name": "X-Ray Brands",
      "description": "Endpoints for creators posts and timelines related to brands.",
      "x-displayName": "Brand Mentions"
    },
    {
      "name": "X-Ray Compliance",
      "description": "Endpoints for creators compliance data.",
      "x-displayName": "Compliance Monitoring"
    },
    {
      "name": "Search",
      "description": "Full-text search endpoints powered by Elasticsearch.",
      "x-displayName": "Search"
    },
    {
      "name": "Account",
      "x-displayName": "Account & Tokens",
      "description": "Token-budget discovery and scan-catalog endpoints for the prepaid token model that powers\ncreator scans, re-scans, and monitoring.\n\n**Prepaid tokens.** Billable actions (new scans via `POST /creators/`, re-scans via\n`POST /creators/{id}/rescan/`, monitoring via `POST /creators/{id}/monitor/`) consume tokens\nfrom your organization's API budget. Read the current balance with `GET /account/usage/`.\nToken purchasing happens outside the API — contact your account manager to top up.\n\n**Scan tiers.** A scan tier determines how much creator history is analyzed and the token\ncost. Initial-scan tiers (`scan_1y` / `scan_2y` / `scan_full`) are used on creator create;\nre-scan tiers (`rescan_lite` / `rescan_mild` / `rescan_full`) refresh or deepen an existing\ncreator. Costs are admin-configurable — always read `GET /scan-catalog/` for live values\ninstead of hardcoding tiers.\n\n**Data visibility windows.** Historical sub-resources (posts, timeline, brands, compliance)\nfor newly-added creators are scoped to the time range covered by the scan tier purchased.\nThe `visibility{}` block on `GET /creators/{id}/` tells you the exact window and whether\na deeper scan is available. Creators added before the token-model launch (2026-05-30) remain\nunrestricted.\n\n**Previewing cost.** Append `?dry_run=true` on `POST /creators/` (single & bulk) or\n`POST /creators/{id}/monitor/` to preview the token cost and outcome without making any\nchange or debiting tokens. Validation still runs.\n\nSee the [PLG launch changelog post](/docs/changelog/2026-05-30-plg-token-model) for the\nfull migration guide.\n"
    }
  ],
  "x-tagGroups": [
    {
      "name": "Core API",
      "tags": [
        "Creators",
        "Brands",
        "Lists",
        "Search",
        "Account"
      ]
    },
    {
      "name": "Content Analysis",
      "tags": [
        "X-Ray",
        "X-Ray Brands",
        "X-Ray Compliance"
      ]
    }
  ],
  "paths": {
    "/creators/search/": {
      "post": {
        "summary": "Search and list creators",
        "description": "**Public API Endpoint**\n\nUse this endpoint to search creators based on various filters, with support for pagination and ordering.\nThis is a POST request and requires an API key for authentication.\n\nProvide filters to narrow down the search results. If no filters are provided, all creators are listed with pagination applied.\n",
        "operationId": "public_search_creators",
        "tags": [
          "Creators"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Number of results per page.",
            "example": 10,
            "x-traitTag": true
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Page number for pagination.",
            "example": 1,
            "x-traitTag": true
          },
          {
            "name": "ordering",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "-created_at",
                "followers_reach",
                "-followers_reach"
              ]
            },
            "description": "Ordering of results. Use a minus (`-`) prefix for descending order.",
            "example": "-created_at",
            "x-traitTag": true
          },
          {
            "name": "include_child_scores",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "- true (default): return both top-level parent categories and child/leaf tags (zero-filled)\n- false: return parent category scores only (top-level categories)\n",
            "example": true,
            "x-traitTag": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "region": {
                    "type": "string",
                    "description": "Filter creators by their region.",
                    "example": "europe"
                  },
                  "gender": {
                    "type": "string",
                    "description": "Filter creators by gender.",
                    "example": "male"
                  },
                  "followers_reach": {
                    "type": "integer",
                    "description": "Minimum follower reach for filtering.",
                    "example": 720000
                  },
                  "platform": {
                    "type": "object",
                    "description": "Platform filters (e.g., Instagram, Facebook).",
                    "properties": {
                      "instagram": {
                        "type": "boolean",
                        "example": true
                      },
                      "facebook": {
                        "type": "boolean",
                        "example": false
                      }
                    }
                  },
                  "content_alignment": {
                    "type": "object",
                    "description": "Content alignment filters for various types of content.",
                    "properties": {
                      "language_content": {
                        "type": "integer",
                        "example": 85
                      },
                      "sexual_content": {
                        "type": "integer",
                        "example": 85
                      },
                      "violence_content": {
                        "type": "integer",
                        "example": 86
                      },
                      "cyber_bully": {
                        "type": "integer",
                        "example": 84
                      },
                      "drug_content": {
                        "type": "integer",
                        "example": 84
                      },
                      "hate_content": {
                        "type": "integer",
                        "example": 82
                      },
                      "alcohol_content": {
                        "type": "integer",
                        "example": 83
                      },
                      "gambling_content": {
                        "type": "integer",
                        "example": 82
                      },
                      "politics_content": {
                        "type": "integer",
                        "example": 81
                      },
                      "religion_content": {
                        "type": "integer",
                        "example": 80
                      },
                      "youth_content": {
                        "type": "integer",
                        "example": 79
                      },
                      "digital_safety": {
                        "type": "integer",
                        "example": 78
                      }
                    }
                  },
                  "brands": {
                    "type": "array",
                    "description": "Filter by associated brands.",
                    "items": {
                      "type": "string"
                    },
                    "example": []
                  },
                  "creators_display_name": {
                    "type": "string",
                    "description": "Filter by the creator's display name (partial match allowed).",
                    "example": "John"
                  },
                  "is_filtered": {
                    "type": "boolean",
                    "description": "Whether to apply the filters or not.",
                    "example": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A paginated list of creators matching the provided filters.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "next": {
                      "type": "string",
                      "description": "URL for the next page of results.",
                      "example": "https://api.vwd.ai/api/public/v1/creators/search/?limit=10&ordering=-created_at&page=2"
                    },
                    "previous": {
                      "type": "string",
                      "description": "URL for the previous page of results.",
                      "example": null
                    },
                    "total_pages": {
                      "type": "integer",
                      "description": "Total number of pages available.",
                      "example": 15
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of creators matching the filters.",
                      "example": 144
                    },
                    "creators": {
                      "type": "array",
                      "description": "A list of creators matching the filters.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "description": "Unique ID of the creators.",
                            "example": 3975
                          },
                          "name": {
                            "type": "string",
                            "description": "Creator's name or brand.",
                            "example": "BMW"
                          },
                          "photo_url": {
                            "type": "string",
                            "description": "URL of the creator's profile picture.",
                            "example": "https://media.qa.vwd.ai/media/creators-profile-pics/instagram_bmw.jpg"
                          },
                          "region": {
                            "type": "string",
                            "description": "Region of the creators.",
                            "example": "india"
                          },
                          "gender": {
                            "type": "string",
                            "description": "Gender of the creators.",
                            "example": "non_binary"
                          },
                          "is_public": {
                            "type": "boolean",
                            "description": "Indicates whether the creators is public or private.",
                            "example": false
                          },
                          "followers_reach": {
                            "type": "integer",
                            "description": "Total number of followers reached by the creators.",
                            "example": 40337817
                          },
                          "follower_reach_normalised": {
                            "type": "string",
                            "description": "Normalized follower reach.",
                            "example": "40.3 m"
                          },
                          "pronoun": {
                            "type": "string",
                            "description": "Pronoun of the creators.",
                            "example": ""
                          },
                          "age": {
                            "type": "integer",
                            "description": "Age of the creators.",
                            "example": 34
                          },
                          "social_profiles": {
                            "type": "array",
                            "description": "List of creator's social profiles.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer",
                                  "description": "Social profile ID.",
                                  "example": 4189
                                },
                                "profile_url": {
                                  "type": "string",
                                  "description": "URL of the social profile.",
                                  "example": "https://www.instagram.com/ttt"
                                },
                                "platform": {
                                  "type": "string",
                                  "description": "Platform name (e.g., Instagram, Facebook).",
                                  "example": "instagram"
                                },
                                "social_handle": {
                                  "type": "string",
                                  "description": "Handle of the social profile.",
                                  "example": "ttt"
                                }
                              }
                            }
                          },
                          "scores": {
                            "type": "object",
                            "description": "Scores across various compliance and risk categories.",
                            "additionalProperties": {
                              "type": "object",
                              "properties": {
                                "value": {
                                  "type": "number",
                                  "example": 1.38
                                }
                              }
                            }
                          },
                          "summary": {
                            "type": "string",
                            "description": "Summary of the creator's profile.",
                            "example": "BMW is a non-binary creators based in India, active on Instagram."
                          },
                          "avg_comments_per_post": {
                            "type": "string",
                            "description": "Average comments per post.",
                            "example": "494 "
                          },
                          "avg_likes_per_post": {
                            "type": "string",
                            "description": "Average likes per post.",
                            "example": "108.2 k"
                          },
                          "avg_views_per_video": {
                            "type": "string",
                            "description": "Average views per video.",
                            "example": "60.4 k"
                          },
                          "total_compliance_violations": {
                            "type": "integer",
                            "description": "Total compliance violations by the creators.",
                            "example": 86
                          },
                          "compliance_violations_by_category": {
                            "type": "object",
                            "description": "Total compliance violations for this creator broken down by compliance family.\nSum of values equals `total_compliance_violations`. All four keys are always\npresent (zeros when no violations); values are non-negative integers.\n",
                            "properties": {
                              "FTC": {
                                "type": "integer",
                                "minimum": 0,
                                "example": 60
                              },
                              "FINRA": {
                                "type": "integer",
                                "minimum": 0,
                                "example": 0
                              },
                              "Healthcare": {
                                "type": "integer",
                                "minimum": 0,
                                "example": 26
                              },
                              "TTB": {
                                "type": "integer",
                                "minimum": 0,
                                "example": 0
                              }
                            },
                            "required": [
                              "FTC",
                              "FINRA",
                              "Healthcare",
                              "TTB"
                            ],
                            "example": {
                              "FTC": 60,
                              "FINRA": 0,
                              "Healthcare": 26,
                              "TTB": 0
                            }
                          },
                          "is_monitored": {
                            "type": "boolean",
                            "description": "Indicates whether the creator is currently being monitored (actively scanned for new content).",
                            "example": true
                          },
                          "brands": {
                            "type": "array",
                            "description": "List of associated brands",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer",
                                  "description": "Brand ID",
                                  "example": 1
                                },
                                "name": {
                                  "type": "string",
                                  "description": "Brand name (lowercased)",
                                  "example": "nike"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Invalid input data."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Authentication credentials were not provided."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - API key does not have access.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "You do not have permission to perform this action."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/": {
      "get": {
        "summary": "Retrieve an creator's profile",
        "description": "**Public API Endpoint**\n\nUse this endpoint to retrieve an creator's profile. Only accessible if the API key is valid and the creators\nbelongs to the organization associated with the API key.\n",
        "operationId": "public_retrieve_creators_profile",
        "tags": [
          "Creators"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The ID of the creators to retrieve.",
            "schema": {
              "type": "integer"
            },
            "example": 12345
          },
          {
            "name": "include_child_scores",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "- true (default): return both top-level parent categories and child/leaf tags (zero-filled)\n- false: return parent category scores only (top-level categories)\n",
            "example": true,
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Creator profile. Returns the same shape as the creator list (`GET /creators/`) plus two\nPLG-specific blocks: `scan_statuses[]` (per-scan state, freshness, pipeline stage,\navailable re-scan options) and `visibility{}` (history window). Pre-PLG creators\nreturn `scan_statuses: []` and `visibility.is_restricted: false`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatorProfile"
                },
                "examples": {
                  "plg_creator": {
                    "summary": "PLG creator with a Comprehensive scan",
                    "value": {
                      "id": 84213,
                      "name": "Kennedy Sur",
                      "deepest_scan": null,
                      "scan_statuses": [
                        {
                          "scan_type": "scan_full",
                          "scan_type_display": "Comprehensive Scan",
                          "status": "fresh",
                          "can_rescan": true,
                          "rescan_options": [
                            {
                              "scan_type": "rescan_full",
                              "display": "Comprehensive Re-scan",
                              "token_cost": 3,
                              "data_coverage_days": null
                            }
                          ],
                          "last_scanned_at": "2026-05-01T12:34:56Z",
                          "monitoring_active": true,
                          "monitoring_user_disabled": false,
                          "monitoring_expires_at": "2026-06-01T00:00:00Z",
                          "token_cost": 3,
                          "pipeline_stage": "completed"
                        }
                      ],
                      "visibility": {
                        "visible_from": "2025-05-18",
                        "visible_until": "2026-05-18",
                        "is_restricted": true,
                        "deeper_scan_available": false,
                        "upgrade_scan_type": null
                      }
                    }
                  },
                  "pre_plg_creator": {
                    "summary": "Pre-PLG creator (unrestricted, no scan statuses)",
                    "value": {
                      "id": 12345,
                      "name": "Legacy Creator",
                      "deepest_scan": null,
                      "scan_statuses": [],
                      "visibility": {
                        "visible_from": null,
                        "visible_until": null,
                        "is_restricted": false,
                        "deeper_scan_available": false,
                        "upgrade_scan_type": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Creators not found or not accessible.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/posts/": {
      "get": {
        "summary": "Retrieve Creators Posts with Labels",
        "description": "**Public API Endpoint**\n\nFetch all posts for a specific creators tagged with the specified media category.\nOptional year and month parameters can be used to filter posts by date.\nRequires an API key for authentication.\n",
        "operationId": "public_get_posts_with_labels",
        "tags": [
          "X-Ray"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators whose posts are being retrieved.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "year",
            "in": "query",
            "description": "Year for filtering posts (optional).",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "x-traitTag": true
          },
          {
            "name": "month",
            "in": "query",
            "description": "Month for filtering posts (optional).",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "x-traitTag": true
          },
          {
            "name": "media_category",
            "in": "query",
            "description": "Top-level content category for filtering posts. Child subcategories are also accepted.\n",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "sexual_content",
                "violence_content",
                "drug_content",
                "alcohol_content",
                "cyber_bully",
                "gambling_content",
                "hate_content",
                "language_content",
                "politics_content",
                "religion_content",
                "youth_content",
                "digital_safety"
              ]
            },
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "A list of posts with labels.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Post ID.",
                        "example": 12345
                      },
                      "platform_name": {
                        "type": "string",
                        "description": "Platform name.",
                        "example": "Instagram"
                      },
                      "date": {
                        "type": "string",
                        "description": "Date of the post.",
                        "example": "January 1, 2024"
                      },
                      "link": {
                        "type": "string",
                        "description": "Link to the post.",
                        "example": "https://instagram.com/post/12345"
                      },
                      "score": {
                        "type": "number",
                        "format": "float",
                        "description": "Normalized confidence score of the post.",
                        "example": 95.5
                      },
                      "reasons": {
                        "type": "array",
                        "description": "Content analysis reasons for the post, grouped by category.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "reason": {
                              "type": "string",
                              "description": "Description of why the content was flagged.",
                              "example": "Image contains alcoholic beverages."
                            },
                            "category": {
                              "type": "string",
                              "description": "Top-level content category.",
                              "example": "alcohol_content"
                            },
                            "subcategory": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Specific child category, or null if the flag is at the top level.",
                              "example": "alcoholic_beverages"
                            },
                            "score": {
                              "type": "number",
                              "description": "Confidence score for this reason.",
                              "example": 0.95
                            },
                            "source_type": {
                              "type": "string",
                              "description": "Type of content source (image, video, text, or transcription).",
                              "example": "image"
                            },
                            "timestamps": {
                              "type": "array",
                              "description": "Timestamps in seconds where the content was detected (video only).",
                              "items": {
                                "type": "number"
                              },
                              "example": []
                            },
                            "text_preview": {
                              "type": "string",
                              "description": "Text content associated with the detection (included for text/transcription sources)."
                            }
                          }
                        }
                      },
                      "brands": {
                        "type": "array",
                        "description": "Brands mentioned in the post.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer",
                              "example": 1
                            },
                            "name": {
                              "type": "string",
                              "example": "nike"
                            }
                          }
                        }
                      },
                      "is_dismissed": {
                        "type": "boolean",
                        "description": "Whether the post has been dismissed.",
                        "example": false
                      },
                      "article_title": {
                        "type": "string",
                        "description": "Article title (Google News posts only)."
                      },
                      "image_url": {
                        "type": "string",
                        "description": "Image URL (Google News posts only)."
                      },
                      "article_text": {
                        "type": "string",
                        "description": "Article text content (Google News and Reddit posts only)."
                      },
                      "source_name": {
                        "type": "string",
                        "description": "Source name (Google News posts only)."
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid media category provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/posts/{post_id}/brands/": {
      "get": {
        "summary": "Retrieve All Brands for a Specific Post",
        "description": "**Public API Endpoint**\n\nFetch all brands mentioned in a specific post for a given creators.\nReturns brands sorted by mention count in descending order.\nRequires an API key for authentication.\n",
        "operationId": "public_get_post_brand_details",
        "tags": [
          "X-Ray Brands"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "post_id",
            "in": "path",
            "description": "ID of the post.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of all brands mentioned in the post.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Brand ID.",
                        "example": 1
                      },
                      "name": {
                        "type": "string",
                        "description": "Brand name.",
                        "example": "nike"
                      },
                      "count": {
                        "type": "integer",
                        "description": "Number of times the brand is mentioned in the post.",
                        "example": 3
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Post or creators not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/timeline/": {
      "get": {
        "summary": "Retrieve creators Timeline by Media Category",
        "description": "**Public API Endpoint**\n\nFetch a timeline of posts for a given creators based on the specified media category.\nThe response groups posts by year and month.\nRequires an API key for authentication.\n",
        "operationId": "public_get_creators_timeline",
        "tags": [
          "X-Ray"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "media_category",
            "in": "query",
            "description": "Top-level content category for filtering posts. Child subcategories are also accepted.\n",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "sexual_content",
                "violence_content",
                "drug_content",
                "alcohol_content",
                "cyber_bully",
                "gambling_content",
                "hate_content",
                "language_content",
                "politics_content",
                "religion_content",
                "youth_content",
                "digital_safety"
              ]
            },
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Timeline of posts grouped by year and month.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "year": {
                        "type": "integer",
                        "description": "Year of the timeline.",
                        "example": 2024
                      },
                      "months": {
                        "type": "array",
                        "description": "List of months with active status.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "description": "Month name.",
                              "example": "January"
                            },
                            "active": {
                              "type": "boolean",
                              "description": "Indicates if posts exist for the month.",
                              "example": true
                            },
                            "month": {
                              "type": "integer",
                              "description": "Numeric representation of the month.",
                              "example": 1
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid media category provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/brands-timeline/": {
      "get": {
        "summary": "Retrieve Creators Brand Timeline",
        "description": "**Public API Endpoint**\n\nFetch a timeline of posts for a given creators mentioning one or more brands.\nThe timeline groups posts by year and month.\nRequires an API key for authentication.\n",
        "operationId": "public_get_brand_timeline_for_creators",
        "tags": [
          "X-Ray Brands"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "brand_ids",
            "in": "query",
            "description": "Comma-separated brand IDs (e.g., 123,456,789).",
            "required": true,
            "schema": {
              "type": "string"
            },
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Timeline of posts mentioning the brands, grouped by year and month.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "year": {
                        "type": "integer",
                        "description": "Year of the timeline.",
                        "example": 2024
                      },
                      "months": {
                        "type": "array",
                        "description": "List of months with active status.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "description": "Month name.",
                              "example": "January"
                            },
                            "active": {
                              "type": "boolean",
                              "description": "Indicates if posts exist for the month.",
                              "example": true
                            },
                            "month": {
                              "type": "integer",
                              "description": "Numeric representation of the month.",
                              "example": 1
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid brand IDs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/brands-posts/": {
      "get": {
        "summary": "Retrieve Creators Brand Posts",
        "description": "**Public API Endpoint**\n\nFetch all posts for a specific creators mentioning one or more brands.\nEach post includes associated brands information with id, name, and count.\nOptional filters for year and month can be applied.\nRequires an API key for authentication.\n",
        "operationId": "public_get_brand_posts",
        "tags": [
          "X-Ray Brands"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "brand_ids",
            "in": "query",
            "description": "Comma-separated brand IDs (e.g., 123,456,789).",
            "required": true,
            "schema": {
              "type": "string"
            },
            "x-traitTag": true
          },
          {
            "name": "year",
            "in": "query",
            "description": "Year filter for posts (optional).",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "x-traitTag": true
          },
          {
            "name": "month",
            "in": "query",
            "description": "Month filter for posts (optional).",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "List of posts mentioning the brands, with details and associated brands data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Post ID.",
                        "example": 12345
                      },
                      "platform_name": {
                        "type": "string",
                        "description": "Platform name where the post was published.",
                        "example": "Instagram"
                      },
                      "date": {
                        "type": "string",
                        "description": "Date of the post.",
                        "example": "January 1, 2024"
                      },
                      "link": {
                        "type": "string",
                        "description": "URL link to the post.",
                        "example": "https://instagram.com/post/12345"
                      },
                      "score": {
                        "type": "number",
                        "format": "float",
                        "description": "Normalized confidence score of the post.",
                        "example": 95.5
                      },
                      "reasons": {
                        "type": "array",
                        "description": "Brand mention reasons for the post.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "reason": {
                              "type": "string",
                              "description": "Description of the brand mention.",
                              "example": "Brand logo visible in image."
                            },
                            "category": {
                              "type": "string",
                              "description": "Brand name.",
                              "example": "nike"
                            },
                            "subcategory": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Subcategory (null for brand mentions).",
                              "example": null
                            },
                            "score": {
                              "type": "number",
                              "description": "Confidence score for this detection.",
                              "example": 0.92
                            },
                            "source_type": {
                              "type": "string",
                              "description": "Type of content source (image, video, text, or transcription).",
                              "example": "image"
                            },
                            "timestamps": {
                              "type": "array",
                              "description": "Timestamps in seconds where the brand was detected (video only).",
                              "items": {
                                "type": "number"
                              },
                              "example": []
                            },
                            "text_preview": {
                              "type": "string",
                              "description": "Text content associated with the detection (included for text/transcription sources)."
                            }
                          }
                        }
                      },
                      "brands": {
                        "type": "array",
                        "description": "Brands mentioned in the post with mention counts.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer",
                              "description": "Brand ID.",
                              "example": 1
                            },
                            "name": {
                              "type": "string",
                              "description": "Brand name.",
                              "example": "nike"
                            },
                            "count": {
                              "type": "integer",
                              "description": "Number of mentions.",
                              "example": 3
                            }
                          }
                        }
                      },
                      "is_dismissed": {
                        "type": "boolean",
                        "description": "Whether the post has been dismissed.",
                        "example": false
                      },
                      "article_title": {
                        "type": "string",
                        "description": "Article title (Google News posts only)."
                      },
                      "image_url": {
                        "type": "string",
                        "description": "Image URL (Google News posts only)."
                      },
                      "article_text": {
                        "type": "string",
                        "description": "Article text content (Google News and Reddit posts only)."
                      },
                      "source_name": {
                        "type": "string",
                        "description": "Source name (Google News posts only)."
                      }
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "No posts found for the specified parameters."
          },
          "400": {
            "description": "Missing or invalid parameters (e.g., creators ID or brand IDs).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/compliance-timeline/": {
      "get": {
        "summary": "Retrieve Creators Compliance Timeline",
        "description": "**Public API Endpoint**\n\nFetch a timeline of compliance violations for a given creators.\nThe response groups compliance violations by year and month.\nRequires an API key for authentication.\n",
        "operationId": "public_get_compliance_timeline_for_creators",
        "tags": [
          "X-Ray Compliance"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "compliance_key",
            "in": "query",
            "description": "Compliance framework or specific violation subcategory to filter by.\n\n**Top-level frameworks:** FTC, FINRA, Healthcare, TTB\n\n**FTC subcategories:** FTC_PARTNERSHIP, FTC_FALSE_CLAIMS, FTC_FALSE_ADVICE, FTC_COPPA, FTC_PRIVACY\n\n**FINRA subcategories:** FINRA_FALSE_CLAIMS, FINRA_FALSE_STATEMENTS, FINRA_FALSE_ADVICE, FINRA_COMPARATIVE_STATEMENTS, FINRA_MEMBERSHIP, FINRA_FIGURES\n\n**Healthcare subcategories:** HEALTHCARE_PERSONAL_INFORMATION, HEALTHCARE_FALSE_INFORMATION, HEALTHCARE_PRODUCT_USE, HEALTHCARE_CLINICAL_INACCURACY, HEALTHCARE_NON_ACCESSIBLE_CONTENT, HEALTHCARE_INFORMATION_LIMITATIONS\n\n**TTB subcategories:** TTB_LABELING_ACCURACY, TTB_ADVERTISING_CONTENT, TTB_YOUTH_TARGETING, TTB_HEALTH_SAFETY_MESSAGING, TTB_SOCIAL_RESPONSIBILITY, TTB_SPONSORSHIP_EVENT, TTB_PRODUCT_PACKAGING, TTB_DIGITAL_SOCIAL_MEDIA\n",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "FTC",
                "FINRA",
                "Healthcare",
                "TTB",
                "FTC_PARTNERSHIP",
                "FTC_FALSE_CLAIMS",
                "FTC_FALSE_ADVICE",
                "FTC_COPPA",
                "FTC_PRIVACY",
                "FINRA_FALSE_CLAIMS",
                "FINRA_FALSE_STATEMENTS",
                "FINRA_FALSE_ADVICE",
                "FINRA_COMPARATIVE_STATEMENTS",
                "FINRA_MEMBERSHIP",
                "FINRA_FIGURES",
                "HEALTHCARE_PERSONAL_INFORMATION",
                "HEALTHCARE_FALSE_INFORMATION",
                "HEALTHCARE_PRODUCT_USE",
                "HEALTHCARE_CLINICAL_INACCURACY",
                "HEALTHCARE_NON_ACCESSIBLE_CONTENT",
                "HEALTHCARE_INFORMATION_LIMITATIONS",
                "TTB_LABELING_ACCURACY",
                "TTB_ADVERTISING_CONTENT",
                "TTB_YOUTH_TARGETING",
                "TTB_HEALTH_SAFETY_MESSAGING",
                "TTB_SOCIAL_RESPONSIBILITY",
                "TTB_SPONSORSHIP_EVENT",
                "TTB_PRODUCT_PACKAGING",
                "TTB_DIGITAL_SOCIAL_MEDIA"
              ]
            },
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Timeline of compliance violations grouped by year and month.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "year": {
                        "type": "integer",
                        "description": "Year of the timeline.",
                        "example": 2024
                      },
                      "months": {
                        "type": "array",
                        "description": "List of months with active status.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "description": "Month name.",
                              "example": "January"
                            },
                            "active": {
                              "type": "boolean",
                              "description": "Indicates if violations exist for the month.",
                              "example": true
                            },
                            "month": {
                              "type": "integer",
                              "description": "Numeric representation of the month.",
                              "example": 1
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid compliance key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/compliance-posts/": {
      "get": {
        "summary": "Retrieve Creators Compliance Posts",
        "description": "**Public API Endpoint**\n\nFetch all posts for a given creators with compliance violations.\nOptional filters for year and month can be applied.\nRequires an API key for authentication.\n",
        "operationId": "public_get_compliance_posts",
        "tags": [
          "X-Ray Compliance"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "ID of the creators.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "compliance_key",
            "in": "query",
            "description": "Compliance framework or specific violation subcategory to filter by.\n\n**Top-level frameworks:** FTC, FINRA, Healthcare, TTB\n\n**FTC subcategories:** FTC_PARTNERSHIP, FTC_FALSE_CLAIMS, FTC_FALSE_ADVICE, FTC_COPPA, FTC_PRIVACY\n\n**FINRA subcategories:** FINRA_FALSE_CLAIMS, FINRA_FALSE_STATEMENTS, FINRA_FALSE_ADVICE, FINRA_COMPARATIVE_STATEMENTS, FINRA_MEMBERSHIP, FINRA_FIGURES\n\n**Healthcare subcategories:** HEALTHCARE_PERSONAL_INFORMATION, HEALTHCARE_FALSE_INFORMATION, HEALTHCARE_PRODUCT_USE, HEALTHCARE_CLINICAL_INACCURACY, HEALTHCARE_NON_ACCESSIBLE_CONTENT, HEALTHCARE_INFORMATION_LIMITATIONS\n\n**TTB subcategories:** TTB_LABELING_ACCURACY, TTB_ADVERTISING_CONTENT, TTB_YOUTH_TARGETING, TTB_HEALTH_SAFETY_MESSAGING, TTB_SOCIAL_RESPONSIBILITY, TTB_SPONSORSHIP_EVENT, TTB_PRODUCT_PACKAGING, TTB_DIGITAL_SOCIAL_MEDIA\n",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "FTC",
                "FINRA",
                "Healthcare",
                "TTB",
                "FTC_PARTNERSHIP",
                "FTC_FALSE_CLAIMS",
                "FTC_FALSE_ADVICE",
                "FTC_COPPA",
                "FTC_PRIVACY",
                "FINRA_FALSE_CLAIMS",
                "FINRA_FALSE_STATEMENTS",
                "FINRA_FALSE_ADVICE",
                "FINRA_COMPARATIVE_STATEMENTS",
                "FINRA_MEMBERSHIP",
                "FINRA_FIGURES",
                "HEALTHCARE_PERSONAL_INFORMATION",
                "HEALTHCARE_FALSE_INFORMATION",
                "HEALTHCARE_PRODUCT_USE",
                "HEALTHCARE_CLINICAL_INACCURACY",
                "HEALTHCARE_NON_ACCESSIBLE_CONTENT",
                "HEALTHCARE_INFORMATION_LIMITATIONS",
                "TTB_LABELING_ACCURACY",
                "TTB_ADVERTISING_CONTENT",
                "TTB_YOUTH_TARGETING",
                "TTB_HEALTH_SAFETY_MESSAGING",
                "TTB_SOCIAL_RESPONSIBILITY",
                "TTB_SPONSORSHIP_EVENT",
                "TTB_PRODUCT_PACKAGING",
                "TTB_DIGITAL_SOCIAL_MEDIA"
              ]
            },
            "x-traitTag": true
          },
          {
            "name": "year",
            "in": "query",
            "description": "Year filter for posts (optional).",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "x-traitTag": true
          },
          {
            "name": "month",
            "in": "query",
            "description": "Month filter for posts (optional).",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "List of posts with compliance violations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Post ID.",
                        "example": 12345
                      },
                      "platform_name": {
                        "type": "string",
                        "description": "Platform name where the post was published.",
                        "example": "Instagram"
                      },
                      "date": {
                        "type": "string",
                        "description": "Date of the post.",
                        "example": "January 1, 2024"
                      },
                      "link": {
                        "type": "string",
                        "description": "URL link to the post.",
                        "example": "https://instagram.com/post/12345"
                      },
                      "reasons": {
                        "type": "array",
                        "description": "List of compliance violation reasons associated with the post.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "reason": {
                              "type": "string",
                              "description": "Description of the compliance violation.",
                              "example": "Post promotes a product without disclosing the paid partnership."
                            },
                            "category": {
                              "type": "string",
                              "description": "Top-level compliance framework (FTC, FINRA, Healthcare, or TTB).",
                              "example": "FTC"
                            },
                            "subcategory": {
                              "type": "string",
                              "description": "Specific violation type key.",
                              "example": "FTC_PARTNERSHIP"
                            },
                            "text_preview": {
                              "type": "string",
                              "description": "Text content associated with the violation (included when available)."
                            }
                          }
                        }
                      },
                      "brands": {
                        "type": "array",
                        "description": "Brands mentioned in the post.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer",
                              "example": 1
                            },
                            "name": {
                              "type": "string",
                              "example": "nike"
                            }
                          }
                        }
                      },
                      "is_dismissed": {
                        "type": "boolean",
                        "description": "Whether the post has been dismissed.",
                        "example": false
                      },
                      "article_title": {
                        "type": "string",
                        "description": "Article title (Google News posts only)."
                      },
                      "image_url": {
                        "type": "string",
                        "description": "Image URL (Google News posts only)."
                      },
                      "article_text": {
                        "type": "string",
                        "description": "Article text content (Google News and Reddit posts only)."
                      },
                      "source_name": {
                        "type": "string",
                        "description": "Source name (Google News posts only)."
                      }
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "No posts found for the specified parameters."
          },
          "400": {
            "description": "Missing or invalid parameters (e.g., creators ID or compliance key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/brands/": {
      "get": {
        "summary": "Find brand by name",
        "description": "**Public API Endpoint**\n\nFind brand by name (case-insensitive exact match). Returns an array with 0 or 1 item, each with id and name.\n",
        "operationId": "public_get_brands",
        "tags": [
          "Brands"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "Case-insensitive brand name to match exactly. If omitted or blank, returns an empty list.",
            "schema": {
              "type": "string"
            },
            "example": "NIKE",
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved brands matching the name.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Brand ID",
                        "example": 1
                      },
                      "name": {
                        "type": "string",
                        "description": "Brand name (stored normalized to lowercase)",
                        "example": "nike"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/": {
      "get": {
        "summary": "List all creators",
        "description": "**Public API Endpoint**\n\nList creators for the authenticated organization with pagination. Response items include associated brands with IDs.\n",
        "operationId": "public_list_creators",
        "tags": [
          "Creators"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Page number for pagination.",
            "example": 1,
            "x-traitTag": true
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Number of results per page.",
            "example": 10,
            "x-traitTag": true
          },
          {
            "name": "include_child_scores",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "- false (default): return parent category scores only (top-level categories)\n- true: return both top-level parent categories and child/leaf tags (zero-filled)\n",
            "example": false,
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved creators list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "creators": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CreatorWithBrands"
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of creators",
                      "example": 100
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of creators in current page",
                      "example": 10
                    },
                    "next": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "URL for next page",
                      "example": "https://api.vwd.ai/api/public/v1/creators/?page=2&limit=10"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Add creators (single or bulk)",
        "description": "**Public API Endpoint**\n\nAdd creators either one at a time (single JSON object) or in bulk (object with an `items`\narray). Tokens are debited per creator according to the `scan_type` tier (default\n`scan_full` = 3 tokens) plus monitoring (+1 token) if enabled.\n\n**Bulk semantics** — all-or-nothing at the budget gate: if the aggregate cost of all\nbillable rows exceeds your token balance, the whole request returns `402` and nothing is\ncreated or charged. After the gate, per-row save failures (rare race conditions) appear as\n`status: \"failed\"` in the results and do **not** consume tokens; the batch continues.\n\nAppend `?dry_run=true` to preview the token cost and outcome without side effects (no\ncreator created, no tokens debited). Validation still runs.\n\nRe-adding a creator the same org previously hard-deleted restores the archived scan purchase\nand is **not** charged (rebind). Bulk `?dry_run=true` excludes predicted rebinds from the\naggregate cost — the live debit matches.\n",
        "operationId": "public_create_creators",
        "tags": [
          "Creators"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "If `true`, return a cost preview (`200` with `DryRunResponse`) instead of creating\nanything. Accepts `true`/`1` (case-insensitive). Zero side effects.\n",
            "example": false
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/SingleCreatorRequest"
                  },
                  {
                    "$ref": "#/components/schemas/BulkCreatorRequest"
                  }
                ]
              },
              "examples": {
                "single": {
                  "summary": "Add single creator",
                  "value": {
                    "name": "Jane Doe",
                    "social_profiles": [
                      {
                        "platform": "instagram",
                        "profile_url": "https://instagram.com/janedoe"
                      }
                    ],
                    "scan_type": "scan_1y",
                    "monitoring": true,
                    "confirm_duplicate": false
                  }
                },
                "bulk": {
                  "summary": "Add multiple creators (top-level scan_type as fallback)",
                  "value": {
                    "scan_type": "scan_full",
                    "monitoring": false,
                    "confirm_duplicates": false,
                    "items": [
                      {
                        "name": "Creator A",
                        "social_profiles": [
                          {
                            "platform": "instagram",
                            "profile_url": "https://instagram.com/a"
                          }
                        ]
                      },
                      {
                        "name": "Creator B",
                        "social_profiles": [
                          {
                            "platform": "tiktok",
                            "profile_url": "https://tiktok.com/@b"
                          }
                        ],
                        "scan_type": "scan_1y",
                        "monitoring": true
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk request processed, or dry-run preview returned. The bulk live response carries a\n`results` array (per-row outcomes) and a `summary`. The dry-run response (`?dry_run=true`,\non single or bulk) carries cost + would-succeed.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/BulkCreatorResponse"
                    },
                    {
                      "$ref": "#/components/schemas/DryRunResponse"
                    }
                  ]
                },
                "examples": {
                  "bulk_live": {
                    "summary": "Bulk live response (mixed row statuses)",
                    "value": {
                      "results": [
                        {
                          "index": 0,
                          "status": "created",
                          "id": 84230
                        },
                        {
                          "index": 1,
                          "status": "duplicate_requires_confirmation",
                          "message": "A creator with this profile already exists in your organization."
                        },
                        {
                          "index": 2,
                          "status": "invalid",
                          "errors": {
                            "social_profiles": [
                              "At least one valid social profile is required."
                            ]
                          }
                        },
                        {
                          "index": 3,
                          "status": "failed",
                          "errors": {
                            "_": [
                              "<server-side save/debit error message>"
                            ]
                          }
                        }
                      ],
                      "summary": {
                        "requested": 4,
                        "valid": 2,
                        "created": 1,
                        "failed": 3
                      }
                    }
                  },
                  "dry_run_ok": {
                    "summary": "Dry-run preview, would succeed",
                    "value": {
                      "dry_run": true,
                      "token_cost": 3,
                      "available": 10,
                      "would_succeed": true,
                      "reason": null
                    }
                  },
                  "dry_run_insufficient": {
                    "summary": "Dry-run preview, insufficient tokens",
                    "value": {
                      "dry_run": true,
                      "token_cost": 4,
                      "available": 1,
                      "would_succeed": false,
                      "reason": "insufficient_tokens"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Single creator created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatorCreatedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Uses the dict-of-lists shape keyed by field name (or `_` for non-field\nerrors).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error400Create"
                },
                "examples": {
                  "bad_scan_type": {
                    "value": {
                      "errors": {
                        "scan_type": [
                          "Must be one of: ['scan_1y', 'scan_2y', 'scan_full']"
                        ]
                      }
                    }
                  },
                  "no_valid_profiles": {
                    "value": {
                      "errors": {
                        "social_profiles": [
                          "At least one valid social profile is required."
                        ]
                      }
                    }
                  },
                  "invalid_name": {
                    "value": {
                      "errors": {
                        "name": [
                          "Name contains invalid characters. Please use only letters, numbers, spaces, hyphens (-), periods (.), and ampersands (&)."
                        ]
                      }
                    }
                  },
                  "virtual_platform": {
                    "value": {
                      "errors": {
                        "social_profiles": [
                          "Virtual profiles (google_news) cannot be manually set. They are automatically created by the system."
                        ]
                      }
                    }
                  },
                  "concurrent_upload": {
                    "value": {
                      "errors": {
                        "_": [
                          "Another upload is currently in progress for this organization. Please try again later."
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Token-budget failure. Precedence on create: insufficient → disabled → exhausted.\nFor bulk, the budget gate fires **before** any debit — the whole batch fails if the\naggregate cost is unaffordable; nothing is created or charged.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Error402InsufficientTokens"
                    },
                    {
                      "$ref": "#/components/schemas/Error402ApiDisabled"
                    },
                    {
                      "$ref": "#/components/schemas/Error402ApiBudgetExhausted"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "Duplicate detected — requires confirmation. Single-create only; bulk reports duplicates as a `duplicate_requires_confirmation` row status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DuplicateDetected"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/monitor/": {
      "post": {
        "summary": "Enable creator monitoring",
        "description": "**Public API Endpoint**\n\nEnables monitoring for an existing creator in your organization. Idempotent: calling again\nwhen already enabled still returns `is_monitored: true`. Charges the per-cycle monitoring\ncost from `GET /scan-catalog/` → `monitoring.token_cost` on first enable.\n\nAppend `?dry_run=true` to preview cost without enabling monitoring.\n",
        "operationId": "public_monitor_creator",
        "tags": [
          "Creators"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Creator ID to enable monitoring for.",
            "schema": {
              "type": "integer"
            },
            "example": 123
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "If `true`, return a cost preview (`200` with `DryRunResponse`) instead of enabling monitoring.\nAccepts `true`/`1` (case-insensitive). Zero side effects. The 404 check runs before dry-run.\n",
            "example": false
          }
        ],
        "responses": {
          "200": {
            "description": "Monitoring enabled (idempotent), or dry-run preview returned. The live shape is\n`{is_monitored: true}`; the dry-run shape is `DryRunResponse`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "is_monitored"
                      ],
                      "additionalProperties": false,
                      "properties": {
                        "is_monitored": {
                          "type": "boolean",
                          "example": true
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/DryRunResponse"
                    }
                  ]
                },
                "examples": {
                  "live": {
                    "summary": "Monitoring enabled",
                    "value": {
                      "is_monitored": true
                    }
                  },
                  "dry_run_ok": {
                    "summary": "Dry-run preview, would succeed",
                    "value": {
                      "dry_run": true,
                      "token_cost": 1,
                      "available": 12,
                      "would_succeed": true,
                      "reason": null
                    }
                  },
                  "dry_run_disabled": {
                    "summary": "Dry-run preview, API disabled",
                    "value": {
                      "dry_run": true,
                      "token_cost": 1,
                      "available": 0,
                      "would_succeed": false,
                      "reason": "api_disabled"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Token-budget failure. Precedence on monitor: disabled → exhausted → insufficient.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Error402InsufficientTokens"
                    },
                    {
                      "$ref": "#/components/schemas/Error402ApiDisabled"
                    },
                    {
                      "$ref": "#/components/schemas/Error402ApiBudgetExhausted"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Creator not found in your organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Creator not found"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/lists/": {
      "get": {
        "summary": "List creator lists",
        "description": "**Public API Endpoint**\n\nList creator lists for the organization (API key). Supports pagination via page and limit query params.\n",
        "operationId": "public_list_lists",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Page number for pagination.",
            "example": 1,
            "x-traitTag": true
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Number of results per page.",
            "example": 10,
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved lists.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "lists": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "List ID",
                            "example": "00000000-0000-0000-0000-000000000000"
                          },
                          "name": {
                            "type": "string",
                            "description": "List name",
                            "example": "List A"
                          },
                          "influencers_count": {
                            "type": "integer",
                            "description": "Number of influencers in the list",
                            "example": 2
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of lists",
                      "example": 10
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of lists in current page",
                      "example": 2
                    },
                    "next": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "URL for next page",
                      "example": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/lists/{id}/": {
      "get": {
        "summary": "Get list details",
        "description": "**Public API Endpoint**\n\nRetrieve a single list with metadata and a paginated preview of its creators.\n",
        "operationId": "public_get_list",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "List ID (UUID)",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "00000000-0000-0000-0000-000000000000"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Page number for pagination.",
            "example": 1,
            "x-traitTag": true
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Number of results per page.",
            "example": 10,
            "x-traitTag": true
          },
          {
            "name": "include_child_scores",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true
            },
            "description": "- true (default): return both top-level parent categories and child/leaf tags (zero-filled)\n- false: return parent category scores only (top-level categories)\n",
            "example": true,
            "x-traitTag": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully retrieved list details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "example": "00000000-0000-0000-0000-000000000000"
                    },
                    "name": {
                      "type": "string",
                      "example": "List A"
                    },
                    "influencers_count": {
                      "type": "integer",
                      "example": 5
                    },
                    "creators": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CreatorWithBrands"
                      }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of creators in the list",
                      "example": 5
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of creators in current page",
                      "example": 2
                    },
                    "next": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "URL for next page",
                      "example": "/api/public/v1/lists/000.../?page=2&limit=2"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "List not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/lists/{id}/creators/": {
      "post": {
        "summary": "Add creators to list",
        "description": "**Public API Endpoint**\n\nAdd existing creators (by id) to a list. Idempotent: adding the same creator again returns it under already_present.\n",
        "operationId": "public_add_creators_to_list",
        "tags": [
          "Lists"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "List ID (UUID)",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "00000000-0000-0000-0000-000000000000"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "influencer_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Array of creator IDs to add to the list",
                    "example": [
                      1,
                      2,
                      3
                    ]
                  }
                },
                "required": [
                  "influencer_ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Creators added to list successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "added_influencers": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "description": "IDs of creators successfully added",
                      "example": [
                        1,
                        2
                      ]
                    },
                    "already_present": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "description": "IDs of creators already in the list",
                      "example": [
                        2
                      ]
                    },
                    "not_found_influencers": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "description": "IDs of creators not found or not accessible",
                      "example": [
                        999
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "List not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/search/creators/": {
      "post": {
        "summary": "Search creators by content",
        "description": "Full-text search across creator names, summaries, and associated post content powered by Elasticsearch.\nSupports boolean keyword logic (AND/OR/NOT), exact phrase matching, platform filtering,\nlist filtering, and multiple sort options.\n\nResults are automatically scoped to the organization associated with the API key.\n",
        "operationId": "public_search_creators_es",
        "tags": [
          "Search"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "q"
                ],
                "properties": {
                  "q": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500,
                    "description": "Free-text search query matched against the creator's name, summary,\nand associated post content. Maximum 500 characters.\n",
                    "example": "sustainable fashion"
                  },
                  "exact": {
                    "type": "boolean",
                    "default": false,
                    "description": "When true the query is treated as an exact phrase — the words must appear\nconsecutively and in the given order. When false (default) the query is\ntokenised and matched with partial/fuzzy logic.\n",
                    "example": false
                  },
                  "must_include_all": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "maxItems": 10,
                    "description": "AND logic — every keyword in this list must be present in the matching post content. Maximum 10 items, each up to 200 characters.",
                    "example": [
                      "vegan",
                      "organic"
                    ]
                  },
                  "must_not_include": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "maxItems": 10,
                    "description": "NOT logic — none of the keywords in this list should appear in the matching post content. Maximum 10 items, each up to 200 characters.",
                    "example": [
                      "spam"
                    ]
                  },
                  "may_include_any": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "maxItems": 10,
                    "description": "OR logic — at least one keyword from this list must be present in the matching post content. Maximum 10 items, each up to 200 characters.",
                    "example": [
                      "eco-friendly",
                      "green"
                    ]
                  },
                  "sort_by": {
                    "type": "string",
                    "enum": [
                      "relevance",
                      "followers_reach",
                      "name",
                      "avg_likes_per_post",
                      "avg_views_per_video",
                      "avg_comments_per_post",
                      "total_compliance_violations",
                      "created_at",
                      "posts_count",
                      "-followers_reach",
                      "-name",
                      "-avg_likes_per_post",
                      "-avg_views_per_video",
                      "-avg_comments_per_post",
                      "-total_compliance_violations",
                      "-created_at",
                      "-posts_count"
                    ],
                    "default": "relevance",
                    "description": "Sort order for results. Use `relevance` (default) to rank by search score.\nPrefix a field name with `-` for descending order.\n",
                    "example": "-followers_reach"
                  },
                  "page": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 1,
                    "description": "1-based page number (1–100). Defaults to 1.",
                    "example": 1
                  },
                  "page_size": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 10,
                    "description": "Number of results per page (1–100). Defaults to 10.",
                    "example": 10
                  },
                  "filters": {
                    "type": "object",
                    "description": "Optional nested object with platform, creator, and list filters.",
                    "properties": {
                      "platforms": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "instagram",
                            "facebook",
                            "youtube",
                            "tiktok",
                            "twitter",
                            "google_news",
                            "reddit"
                          ]
                        },
                        "description": "Filter results to specific platforms.",
                        "example": [
                          "instagram",
                          "tiktok"
                        ]
                      },
                      "influencer_id": {
                        "type": "integer",
                        "description": "Filter results to a single creator by their numeric ID.",
                        "example": 12345
                      },
                      "list_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Filter results to creators that belong to a specific creator list (UUID).",
                        "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully retrieved search results.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatorSearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — invalid input (e.g., stopwords-only query, page_size > 100).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Invalid input data."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/search/posts/": {
      "post": {
        "summary": "Search posts by content",
        "description": "Full-text search across post content (captions, descriptions, transcripts) powered by Elasticsearch.\nSupports boolean keyword logic (AND/OR/NOT), exact phrase matching, platform filtering,\nlist filtering, and sorting by relevance or date.\n\nResults are automatically scoped to the organization associated with the API key.\n",
        "operationId": "public_search_posts_es",
        "tags": [
          "Search"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "q"
                ],
                "properties": {
                  "q": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500,
                    "description": "Free-text search query matched against post content. Maximum 500 characters.\n",
                    "example": "brand partnership"
                  },
                  "exact": {
                    "type": "boolean",
                    "default": false,
                    "description": "When true the query is treated as an exact phrase — the words must appear\nconsecutively and in the given order. When false (default) the query is\ntokenised and matched with partial/fuzzy logic.\n",
                    "example": false
                  },
                  "must_include_all": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "maxItems": 10,
                    "description": "AND logic — every keyword in this list must be present in the post content. Maximum 10 items, each up to 200 characters.",
                    "example": [
                      "sponsored",
                      "ad"
                    ]
                  },
                  "must_not_include": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "maxItems": 10,
                    "description": "NOT logic — none of the keywords in this list should appear in the post content. Maximum 10 items, each up to 200 characters.",
                    "example": [
                      "giveaway"
                    ]
                  },
                  "may_include_any": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "maxItems": 10,
                    "description": "OR logic — at least one keyword from this list must be present in the post content. Maximum 10 items, each up to 200 characters.",
                    "example": [
                      "collab",
                      "partnership"
                    ]
                  },
                  "sort_by": {
                    "type": "string",
                    "enum": [
                      "relevance",
                      "posted_at",
                      "-posted_at"
                    ],
                    "default": "relevance",
                    "description": "Sort order for results. `relevance` (default) ranks by search score.\n`posted_at` sorts chronologically (oldest first), `-posted_at` sorts\nreverse-chronologically (newest first).\n",
                    "example": "-posted_at"
                  },
                  "page": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 1,
                    "description": "1-based page number (1–100). Defaults to 1.",
                    "example": 1
                  },
                  "page_size": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 10,
                    "description": "Number of results per page (1–100). Defaults to 10.",
                    "example": 10
                  },
                  "filters": {
                    "type": "object",
                    "description": "Optional nested object with platform, creator, and list filters.",
                    "properties": {
                      "platforms": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "instagram",
                            "facebook",
                            "youtube",
                            "tiktok",
                            "twitter",
                            "google_news",
                            "reddit"
                          ]
                        },
                        "description": "Filter results to specific platforms.",
                        "example": [
                          "instagram",
                          "youtube"
                        ]
                      },
                      "influencer_id": {
                        "type": "integer",
                        "description": "Filter results to posts belonging to a single creator by their numeric ID.",
                        "example": 12345
                      },
                      "list_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Filter results to posts from creators in a specific creator list (UUID).",
                        "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully retrieved search results.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostSearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request — invalid input (e.g., stopwords-only query, page_size > 100).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Invalid input data."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/account/usage/": {
      "get": {
        "summary": "Get token budget",
        "description": "**Public API Endpoint**\n\nDiscover the API token budget for your organization: lifetime limit, lifetime usage,\nremaining balance, disabled state, and budget-state band (`NORMAL` / `LOW` / `CRITICAL` / `EMPTY`).\n\nToken purchasing happens outside the API — contact your account manager to top up.\n",
        "operationId": "public_account_usage",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Token budget snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountUsage"
                },
                "examples": {
                  "normal": {
                    "summary": "Capped org with remaining balance",
                    "value": {
                      "api_token_limit": 5000,
                      "api_tokens_used": 320,
                      "api_tokens_remaining": 4680,
                      "api_disabled": false,
                      "state": "NORMAL"
                    }
                  },
                  "unlimited": {
                    "summary": "Unlimited org",
                    "value": {
                      "api_token_limit": null,
                      "api_tokens_used": 412,
                      "api_tokens_remaining": null,
                      "api_disabled": false,
                      "state": "NORMAL"
                    }
                  },
                  "disabled": {
                    "summary": "API-disabled org (limit = 0)",
                    "value": {
                      "api_token_limit": 0,
                      "api_tokens_used": 0,
                      "api_tokens_remaining": 0,
                      "api_disabled": true,
                      "state": "EMPTY"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/scan-catalog/": {
      "get": {
        "summary": "List scan tiers and costs",
        "description": "**Public API Endpoint**\n\nThe live, authoritative list of `scan_type` values and their token costs. Use this to\npopulate UI pickers and to verify costs before adding creators or re-scanning. Values are\nadmin-editable — always read this endpoint instead of hardcoding tiers.\n",
        "operationId": "public_scan_catalog",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Scan catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanCatalog"
                },
                "example": {
                  "initial_scans": [
                    {
                      "scan_type": "scan_1y",
                      "display": "Lite Scan",
                      "token_cost": 1,
                      "data_coverage_days": 365
                    },
                    {
                      "scan_type": "scan_2y",
                      "display": "Medium Scan",
                      "token_cost": 2,
                      "data_coverage_days": 730
                    },
                    {
                      "scan_type": "scan_full",
                      "display": "Comprehensive Scan",
                      "token_cost": 3,
                      "data_coverage_days": null
                    }
                  ],
                  "rescans": [
                    {
                      "scan_type": "rescan_lite",
                      "display": "Lite Re-scan",
                      "token_cost": 1,
                      "data_coverage_days": 365
                    },
                    {
                      "scan_type": "rescan_mild",
                      "display": "Medium Re-scan",
                      "token_cost": 2,
                      "data_coverage_days": 730
                    },
                    {
                      "scan_type": "rescan_full",
                      "display": "Comprehensive Re-scan",
                      "token_cost": 3,
                      "data_coverage_days": null
                    }
                  ],
                  "monitoring": {
                    "token_cost": 1
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/creators/{id}/rescan/": {
      "post": {
        "summary": "Deepen or refresh a creator",
        "description": "**Public API Endpoint**\n\nTrigger a re-scan of an existing creator at a specified tier. Tokens are debited on success.\nUse `GET /scan-catalog/` for valid `scan_type` slugs and current costs. Re-scan slugs use\nthe `rescan_*` namespace — do not send a `scan_*` initial-tier slug here. No `?dry_run=true`\nsupport on this endpoint.\n",
        "operationId": "public_creator_rescan",
        "tags": [
          "Creators"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Numeric identifier of the creator.",
            "example": 84213
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scan_type": {
                    "type": "string",
                    "description": "Re-scan tier slug. Must be a `rescan_*` value from `GET /scan-catalog/` → `rescans[]`.",
                    "example": "rescan_full"
                  }
                },
                "required": [
                  "scan_type"
                ]
              },
              "examples": {
                "full_rescan": {
                  "summary": "Comprehensive re-scan",
                  "value": {
                    "scan_type": "rescan_full"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Re-scan triggered; tokens debited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RescanResponse"
                },
                "example": {
                  "success": true,
                  "influencer_id": 84213,
                  "scan_type": "rescan_full",
                  "tokens_debited": 3
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing `scan_type`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error400Drf"
                },
                "examples": {
                  "invalid": {
                    "summary": "Unknown rescan slug",
                    "value": {
                      "type": "client_error",
                      "errors": [
                        {
                          "code": "invalid",
                          "detail": "Invalid scan_type: rescan_bogus",
                          "attr": "scan_type"
                        }
                      ]
                    }
                  },
                  "missing": {
                    "summary": "scan_type omitted",
                    "value": {
                      "type": "validation_error",
                      "errors": [
                        {
                          "code": "required",
                          "detail": "This field is required.",
                          "attr": "scan_type"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Token-budget failure (insufficient / disabled / exhausted). Live precedence is disabled → exhausted → insufficient.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Error402InsufficientTokens"
                    },
                    {
                      "$ref": "#/components/schemas/Error402ApiDisabled"
                    },
                    {
                      "$ref": "#/components/schemas/Error402ApiBudgetExhausted"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Creator not in your organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Creator not found or not accessible"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Re-scan already in progress for this creator — no charge.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string",
                      "example": "Rescan already in progress for this creator."
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Type of the problem.",
            "example": "Unauthorized"
          },
          "title": {
            "type": "string",
            "description": "Short title of the problem.",
            "example": "Invalid API Key"
          },
          "detail": {
            "type": "string",
            "description": "Detailed explanation of the problem.",
            "example": "The provided API key is invalid."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code.",
            "example": 401
          }
        }
      },
      "CreatorWithBrands": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 10
          },
          "name": {
            "type": "string",
            "example": "Influencer 1"
          },
          "photo_url": {
            "type": [
              "string",
              "null"
            ],
            "example": "https://media.vwd.ai/media/creators-profile-pics/influencer.jpg"
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "example": "europe"
          },
          "gender": {
            "type": [
              "string",
              "null"
            ],
            "example": "female"
          },
          "is_public": {
            "type": "boolean",
            "example": true
          },
          "followers_reach": {
            "type": [
              "integer",
              "null"
            ],
            "example": 500000
          },
          "follower_reach_normalised": {
            "type": "string",
            "example": "500 k"
          },
          "pronoun": {
            "type": [
              "string",
              "null"
            ],
            "example": "she/her"
          },
          "age": {
            "type": [
              "integer",
              "null"
            ],
            "example": 28
          },
          "social_profiles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "example": 1
                },
                "profile_url": {
                  "type": "string",
                  "example": "https://instagram.com/influencer1"
                },
                "platform": {
                  "type": "string",
                  "example": "instagram"
                },
                "social_handle": {
                  "type": "string",
                  "example": "influencer1"
                }
              }
            }
          },
          "scores": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "number",
                  "example": 85.5
                }
              }
            }
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "example": "Popular lifestyle influencer based in North America"
          },
          "avg_comments_per_post": {
            "type": "string",
            "example": "150"
          },
          "avg_likes_per_post": {
            "type": "string",
            "example": "5.2 k"
          },
          "avg_views_per_video": {
            "type": "string",
            "example": "12.5 k"
          },
          "total_compliance_violations": {
            "type": "integer",
            "example": 0
          },
          "compliance_violations_by_category": {
            "type": "object",
            "description": "Total compliance violations for this creator broken down by compliance family.\nSum of values equals `total_compliance_violations`. All four keys are always\npresent (zeros when no violations); values are non-negative integers.\n",
            "properties": {
              "FTC": {
                "type": "integer",
                "minimum": 0,
                "example": 0
              },
              "FINRA": {
                "type": "integer",
                "minimum": 0,
                "example": 0
              },
              "Healthcare": {
                "type": "integer",
                "minimum": 0,
                "example": 0
              },
              "TTB": {
                "type": "integer",
                "minimum": 0,
                "example": 0
              }
            },
            "required": [
              "FTC",
              "FINRA",
              "Healthcare",
              "TTB"
            ],
            "example": {
              "FTC": 0,
              "FINRA": 0,
              "Healthcare": 0,
              "TTB": 0
            }
          },
          "is_monitored": {
            "type": "boolean",
            "description": "Indicates whether the creator is currently being monitored (actively scanned for new content).",
            "example": true
          },
          "brands": {
            "type": "array",
            "description": "List of associated brands",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "example": 1
                },
                "name": {
                  "type": "string",
                  "example": "nike"
                }
              }
            }
          },
          "deepest_scan": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DeepestScan"
              },
              {
                "type": "null"
              }
            ],
            "description": "Deepest scan tier the calling org has purchased for this creator. `null` when the org\nhas no scan purchase (pre-PLG creators, or creators returned by the profile endpoint —\non `GET /creators/{id}/` this field is always `null`; read `scan_statuses[]` instead).\n",
            "example": {
              "scan_type": "scan_full",
              "display": "Comprehensive",
              "purchased_at": "2026-05-01T12:34:56.789012Z"
            }
          }
        }
      },
      "SingleCreatorRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Creator display name. Letters, digits, spaces, `-`, `.`, `&` only — no emoji/symbols. Trimmed; empty/whitespace → 400.",
            "example": "Jane Doe"
          },
          "social_profiles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "platform": {
                  "type": "string",
                  "enum": [
                    "instagram",
                    "tiktok",
                    "youtube",
                    "twitter",
                    "facebook"
                  ],
                  "description": "Social media platform. `google_news`/`reddit` are system-created and rejected on input; `onlyfans` is output-only.",
                  "example": "instagram"
                },
                "profile_url": {
                  "type": "string",
                  "example": "https://instagram.com/janedoe"
                }
              },
              "required": [
                "platform",
                "profile_url"
              ]
            },
            "minItems": 1
          },
          "scan_type": {
            "type": "string",
            "default": "scan_full",
            "description": "Initial scan tier slug. Determines history coverage and token cost. Default `scan_full`\n(3 tokens, full history). Valid values are the active slugs returned by\n`GET /scan-catalog/` → `initial_scans[]` (seeded defaults: `scan_1y` / `scan_2y` / `scan_full`).\nInvalid slug → 400.\n",
            "example": "scan_full"
          },
          "monitoring": {
            "type": "boolean",
            "default": false,
            "description": "Enable monitoring at creation (+1 token, see `GET /scan-catalog/` → `monitoring.token_cost`). Saves a follow-up call to `/monitor/`.",
            "example": false
          },
          "confirm_duplicate": {
            "type": "boolean",
            "default": false,
            "description": "When set to true, allows adding creators despite them already existing in the organization.\nDuplicates within the same request are always omitted regardless of this flag.\n",
            "example": false
          }
        },
        "required": [
          "name",
          "social_profiles"
        ]
      },
      "BulkCreatorRequest": {
        "type": "object",
        "properties": {
          "scan_type": {
            "type": "string",
            "default": "scan_full",
            "description": "Top-level fallback `scan_type` applied to any row that doesn't specify its own.\nInvalid top-level value → whole request 400 (vs. invalid per-item value → just that\nrow reports `status: \"invalid\"`). See `GET /scan-catalog/` → `initial_scans[]`.\n",
            "example": "scan_full"
          },
          "monitoring": {
            "type": "boolean",
            "default": false,
            "description": "Top-level fallback monitoring flag applied to any row that doesn't specify its own.",
            "example": false
          },
          "confirm_duplicates": {
            "type": "boolean",
            "default": false,
            "description": "When set to true, allows adding creators despite them already existing in the organization.\nDuplicates within the same request are always omitted regardless of this flag.\n",
            "example": false
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "social_profiles": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "platform": {
                        "type": "string",
                        "enum": [
                          "instagram",
                          "tiktok",
                          "youtube",
                          "twitter",
                          "facebook"
                        ],
                        "description": "Social media platform name"
                      },
                      "profile_url": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "platform",
                      "profile_url"
                    ]
                  }
                },
                "scan_type": {
                  "type": "string",
                  "description": "Per-row scan tier (overrides the top-level fallback). See `GET /scan-catalog/`.",
                  "example": "scan_1y"
                },
                "monitoring": {
                  "type": "boolean",
                  "description": "Per-row monitoring flag (overrides the top-level fallback).",
                  "example": true
                }
              }
            },
            "minItems": 1
          }
        },
        "required": [
          "items"
        ]
      },
      "CreatorCreatedResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 123
          },
          "name": {
            "type": "string",
            "example": "Jane Doe"
          },
          "overall_status": {
            "type": "string",
            "example": "pending"
          },
          "is_monitored": {
            "type": "boolean",
            "example": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2025-01-01T10:00:00Z"
          },
          "social_profiles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "platform": {
                  "type": "string",
                  "enum": [
                    "instagram",
                    "tiktok",
                    "youtube",
                    "twitter",
                    "facebook"
                  ],
                  "description": "Social media platform name",
                  "example": "instagram"
                },
                "profile_url": {
                  "type": "string",
                  "example": "https://instagram.com/janedoe"
                }
              }
            }
          }
        }
      },
      "BulkCreatorResponse": {
        "type": "object",
        "description": "Bulk create response (HTTP 200 even with row failures). Each row reports its outcome via\n`status`; the `summary` aggregates counts. `summary.failed = requested − created` (so it\nsums both `\"invalid\"` and `\"failed\"` rows). **Note:** the legacy top-level `quota` object\nand the `quota_exceeded` row status were removed when the token model launched — budget\nfailures now return 402 at the request level (not per-row).\n",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "Zero-based index of the row in the request `items[]`.",
                  "example": 0
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "created",
                    "duplicate_requires_confirmation",
                    "invalid",
                    "failed"
                  ],
                  "description": "Row outcome:\n- `created` — saved + charged. Carries `id`.\n- `duplicate_requires_confirmation` — existing creator detected; resend with `confirm_duplicates: true`. Carries `message`.\n- `invalid` — validation/dedup rejection (Phase 1). Carries `errors` (dict-of-lists). **Not charged.**\n- `failed` — post-validation save or debit error inside the per-row savepoint (race condition, IntegrityError, …). Carries `errors._`. **Not charged.**\n",
                  "example": "created"
                },
                "id": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Present when `status == \"created\"`.",
                  "example": 101
                },
                "message": {
                  "type": "string",
                  "description": "Present when `status == \"duplicate_requires_confirmation\"`.",
                  "example": "A creator with this profile already exists in your organization."
                },
                "errors": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "description": "Present when `status` is `invalid` or `failed`. Dict-of-lists keyed by field (or `_` for non-field errors).",
                  "example": {
                    "social_profiles": [
                      "At least one valid social profile is required."
                    ]
                  }
                }
              }
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "requested": {
                "type": "integer",
                "description": "`len(items)` from the request.",
                "example": 4
              },
              "valid": {
                "type": "integer",
                "description": "Number of rows that passed Phase-1 filtering (validation + dedup).",
                "example": 2
              },
              "created": {
                "type": "integer",
                "description": "Number of rows actually saved + charged.",
                "example": 1
              },
              "failed": {
                "type": "integer",
                "description": "`requested − created` — sums both `\"invalid\"` and `\"failed\"` row statuses.",
                "example": 3
              }
            }
          }
        }
      },
      "DuplicateDetected": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": false
          },
          "warning": {
            "type": "string",
            "example": "duplicate_detected"
          },
          "requires_confirmation": {
            "type": "boolean",
            "example": true
          },
          "message": {
            "type": "string",
            "example": "Possible duplicate detected. Set confirm_duplicate to true to proceed."
          }
        }
      },
      "Error402InsufficientTokens": {
        "type": "object",
        "description": "Returned when the action's token cost exceeds the org's available balance.\nIdentified by `errors[0].code == \"insufficient_tokens\"`.\n",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "client_error"
            ],
            "example": "client_error"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "insufficient_tokens"
                  ]
                },
                "detail": {
                  "type": "string"
                },
                "attr": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "example": [
              {
                "code": "insufficient_tokens",
                "detail": "You don't have enough tokens to complete this action. Please top up your balance and try again.",
                "attr": null
              }
            ]
          },
          "required": {
            "type": "integer",
            "description": "Token cost the action would have incurred.",
            "example": 3
          },
          "available": {
            "type": "integer",
            "description": "Current token balance at the time of the call.",
            "example": 1
          },
          "is_admin": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Always `null` for API-key callers.",
            "example": null
          }
        }
      },
      "Error402ApiDisabled": {
        "type": "object",
        "description": "Returned when the org's `api_token_limit` is `0`. Identified by\n`errors[0].code == \"api_disabled\"` and `reason_code == \"API_DISABLED\"`.\n",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "client_error"
            ],
            "example": "client_error"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "api_disabled"
                  ]
                },
                "detail": {
                  "type": "string"
                },
                "attr": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "example": [
              {
                "code": "api_disabled",
                "detail": "Public API token consumption is disabled for this organization.",
                "attr": null
              }
            ]
          },
          "reason_code": {
            "type": "string",
            "enum": [
              "API_DISABLED"
            ],
            "example": "API_DISABLED"
          }
        }
      },
      "Error402ApiBudgetExhausted": {
        "type": "object",
        "description": "Returned when the org has hit its lifetime API token cap (no reset). Identified\nby `errors[0].code == \"api_budget_exhausted\"` and `reason_code == \"API_BUDGET_EXHAUSTED\"`.\n",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "client_error"
            ],
            "example": "client_error"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "api_budget_exhausted"
                  ]
                },
                "detail": {
                  "type": "string"
                },
                "attr": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "example": [
              {
                "code": "api_budget_exhausted",
                "detail": "API token budget exhausted.",
                "attr": null
              }
            ]
          },
          "reason_code": {
            "type": "string",
            "enum": [
              "API_BUDGET_EXHAUSTED"
            ],
            "example": "API_BUDGET_EXHAUSTED"
          },
          "limit": {
            "type": "integer",
            "example": 100
          },
          "consumed": {
            "type": "integer",
            "example": 98
          },
          "requested": {
            "type": "integer",
            "example": 3
          }
        }
      },
      "Error400Create": {
        "type": "object",
        "description": "Validation error shape returned by `POST /creators/` (single and bulk). A hand-rolled\ndict-of-lists keyed by field name (or `_` for non-field errors).\n",
        "properties": {
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "example": {
              "scan_type": [
                "Must be one of: ['scan_1y', 'scan_2y', 'scan_full']"
              ]
            }
          }
        }
      },
      "Error400Drf": {
        "type": "object",
        "description": "DRF-standardized validation/client error shape returned by `POST /creators/{id}/rescan/`\nand the search serializers. List-of-objects keyed by `attr`.\n",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "client_error",
              "validation_error"
            ],
            "example": "client_error"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                },
                "attr": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "example": [
              {
                "code": "invalid",
                "detail": "Invalid scan_type: rescan_bogus",
                "attr": "scan_type"
              }
            ]
          }
        }
      },
      "AccountUsage": {
        "type": "object",
        "description": "Token-budget snapshot for the calling org.",
        "properties": {
          "api_token_limit": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Lifetime API token limit. `null` = unlimited; `0` = API disabled.",
            "example": 5000
          },
          "api_tokens_used": {
            "type": "integer",
            "description": "Lifetime API-channel token debits. UI/system usage is not counted.",
            "example": 320
          },
          "api_tokens_remaining": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`null` if unlimited; otherwise `max(limit − used, 0)`.",
            "example": 4680
          },
          "api_disabled": {
            "type": "boolean",
            "description": "`true` if `api_token_limit == 0`.",
            "example": false
          },
          "state": {
            "type": "string",
            "enum": [
              "NORMAL",
              "LOW",
              "CRITICAL",
              "EMPTY"
            ],
            "description": "Budget-state band based on remaining balance vs. configured thresholds:\n`EMPTY` (= 0), `CRITICAL` (≤ critical threshold), `LOW` (≤ low threshold), else `NORMAL`.\n",
            "example": "NORMAL"
          }
        }
      },
      "ScanCatalogItem": {
        "type": "object",
        "properties": {
          "scan_type": {
            "type": "string",
            "description": "Slug to send as the `scan_type` field on create or rescan.",
            "example": "scan_full"
          },
          "display": {
            "type": "string",
            "description": "Human-friendly tier name.",
            "example": "Comprehensive Scan"
          },
          "token_cost": {
            "type": "integer",
            "minimum": 0,
            "example": 3
          },
          "data_coverage_days": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Length of history analyzed, in days. `null` = unbounded/full history.",
            "example": null
          }
        }
      },
      "ScanCatalog": {
        "type": "object",
        "description": "Live list of available scan and re-scan tiers, plus per-action monitoring cost.\nValues are admin-configurable — always read this endpoint instead of hardcoding.\n",
        "properties": {
          "initial_scans": {
            "type": "array",
            "description": "Tiers valid as `scan_type` on `POST /creators/`. Ordered shallow → deep.",
            "items": {
              "$ref": "#/components/schemas/ScanCatalogItem"
            }
          },
          "rescans": {
            "type": "array",
            "description": "Tiers valid as `scan_type` on `POST /creators/{id}/rescan/`.",
            "items": {
              "$ref": "#/components/schemas/ScanCatalogItem"
            }
          },
          "monitoring": {
            "type": "object",
            "properties": {
              "token_cost": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Tokens charged per monitoring cycle. `null` if unconfigured.",
                "example": 1
              }
            }
          }
        }
      },
      "DeepestScan": {
        "type": "object",
        "description": "Deepest scan tier the calling org has purchased for this creator. `null` when the\norg has no scan purchase (e.g., pre-PLG creators).\n",
        "properties": {
          "scan_type": {
            "type": "string",
            "description": "Scan-type slug — may be a current PLG tier (`scan_full`/`rescan_full`/...) or a legacy value (`full_scan`/`one_year_scan`/`partial_scan`).",
            "example": "scan_full"
          },
          "display": {
            "type": "string",
            "enum": [
              "Lite",
              "Medium",
              "Comprehensive",
              "Monitoring"
            ],
            "example": "Comprehensive"
          },
          "purchased_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-05-01T12:34:56.789012Z"
          }
        }
      },
      "ScanStatusItem": {
        "type": "object",
        "description": "Per-scan state row exposed on the creator profile endpoint.",
        "properties": {
          "scan_type": {
            "type": "string",
            "example": "scan_full"
          },
          "scan_type_display": {
            "type": "string",
            "example": "Comprehensive Scan"
          },
          "status": {
            "type": "string",
            "enum": [
              "fresh",
              "outdated",
              "in_progress"
            ],
            "example": "fresh"
          },
          "can_rescan": {
            "type": "boolean",
            "example": true
          },
          "rescan_options": {
            "type": "array",
            "description": "Rescan tiers available for this creator (subset of `GET /scan-catalog/` → `rescans[]`).",
            "items": {
              "$ref": "#/components/schemas/ScanCatalogItem"
            }
          },
          "last_scanned_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": "2026-05-01T12:34:56Z"
          },
          "monitoring_active": {
            "type": "boolean",
            "example": true
          },
          "monitoring_user_disabled": {
            "type": "boolean",
            "example": false
          },
          "monitoring_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": "2026-06-01T00:00:00Z"
          },
          "token_cost": {
            "type": "integer",
            "example": 3
          },
          "pipeline_stage": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pending",
              "scraping",
              "scraping_completed",
              "scraping_failed_no_data",
              "media_processing",
              "media_processing_completed",
              "scoring_started",
              "scoring_completed",
              "completed",
              "failed",
              null
            ],
            "example": "completed"
          }
        }
      },
      "Visibility": {
        "type": "object",
        "description": "Declares the historical-data window visible to the calling org for this creator.\n`is_restricted: false` when the org has no scan purchase (pre-PLG creators stay\nunrestricted). When restricted, the window matches the tier's `data_coverage_days`.\n",
        "properties": {
          "visible_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Earliest date visible (YYYY-MM-DD), or `null` for no lower bound.",
            "example": "2025-05-18"
          },
          "visible_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Latest date visible (YYYY-MM-DD), or `null` for no upper bound.",
            "example": "2026-05-18"
          },
          "is_restricted": {
            "type": "boolean",
            "example": true
          },
          "deeper_scan_available": {
            "type": "boolean",
            "description": "`true` if a deeper initial scan tier is purchasable.",
            "example": true
          },
          "upgrade_scan_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Initial-tier slug (from `scan-catalog.initial_scans`) for the deepest purchasable upgrade. **Not** a rescan slug.",
            "example": "scan_full"
          }
        }
      },
      "DryRunResponse": {
        "type": "object",
        "description": "Cost-and-outcome preview for billable actions. Zero side effects: no creator created,\nno monitoring enabled, no tokens debited.\n",
        "required": [
          "dry_run",
          "token_cost",
          "available",
          "would_succeed"
        ],
        "properties": {
          "dry_run": {
            "type": "boolean",
            "enum": [
              true
            ],
            "example": true
          },
          "token_cost": {
            "type": "integer",
            "description": "Tokens the live call would debit.",
            "example": 3
          },
          "available": {
            "type": "integer",
            "description": "Current token balance.",
            "example": 10
          },
          "would_succeed": {
            "type": "boolean",
            "description": "`true` if `reason is null`.",
            "example": true
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "insufficient_tokens",
              "api_disabled",
              "api_budget_exhausted",
              null
            ],
            "description": "`null` if the call would succeed; otherwise the precedence-ordered failure reason.\nPrecedence on create: insufficient → disabled → exhausted. On monitor: disabled →\nexhausted → insufficient.\n",
            "example": null
          }
        }
      },
      "RescanResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "influencer_id": {
            "type": "integer",
            "example": 84213
          },
          "scan_type": {
            "type": "string",
            "example": "rescan_full"
          },
          "tokens_debited": {
            "type": "integer",
            "description": "Tokens actually charged — equals the tier's `token_cost`, or a smaller amount when a recent prior scan discount applies.",
            "example": 3
          }
        }
      },
      "CreatorProfile": {
        "description": "Creator profile (`GET /creators/{id}/`). Superset of the list-shape `CreatorWithBrands`\nwith two PLG-specific blocks: `scan_statuses[]` (per-scan state) and `visibility{}` (history\nwindow). **Note:** `deepest_scan` is inherited from `CreatorWithBrands` for schema reuse but\nis always `null` on this endpoint — read `scan_statuses[]` for the org's actual scans.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/CreatorWithBrands"
          },
          {
            "type": "object",
            "properties": {
              "scan_statuses": {
                "type": "array",
                "description": "Per-scan state rows. Empty array (`[]`) for pre-PLG creators.",
                "items": {
                  "$ref": "#/components/schemas/ScanStatusItem"
                }
              },
              "visibility": {
                "$ref": "#/components/schemas/Visibility"
              }
            }
          }
        ]
      },
      "CreatorSearchResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of creators matching the query.",
            "example": 42
          },
          "total_pages": {
            "type": "integer",
            "description": "Total number of pages available at the current page_size.",
            "example": 5
          },
          "page": {
            "type": "integer",
            "description": "Current page number (1-based).",
            "example": 1
          },
          "page_size": {
            "type": "integer",
            "description": "Number of results returned per page.",
            "example": 10
          },
          "results": {
            "type": "array",
            "description": "List of creator search results for the current page.",
            "items": {
              "type": "object",
              "properties": {
                "influencer_id": {
                  "type": "integer",
                  "description": "Unique numeric identifier for the creator.",
                  "example": 456
                },
                "name": {
                  "type": "string",
                  "description": "Display name of the creator.",
                  "example": "Jane Fashion"
                },
                "summary": {
                  "type": "string",
                  "description": "Short biography or description of the creator.",
                  "example": "Sustainable fashion creator based in London."
                },
                "region": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Geographic region or country associated with the creator.",
                  "example": "europe"
                },
                "followers_reach": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Total follower count aggregated across all connected platforms.",
                  "example": 150000
                },
                "profile_pic": {
                  "type": "string",
                  "description": "URL of the creator's profile picture.",
                  "example": "https://media.vwd.ai/media/creators-profile-pics/jane.jpg"
                },
                "display_categories": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "object"
                  },
                  "description": "Content categories detected for this creator, keyed by category slug.",
                  "example": {}
                },
                "compliances": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "integer"
                  },
                  "description": "Compliance violation counts keyed by violation type (e.g., {'ad_disclosure': 3}).",
                  "example": {}
                },
                "platforms": {
                  "type": "array",
                  "description": "List of social platforms the creator is active on.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "platform": {
                        "type": "string",
                        "description": "Platform identifier.",
                        "example": "instagram"
                      },
                      "profile_id": {
                        "type": "string",
                        "description": "Platform-specific profile identifier.",
                        "example": "janefashion"
                      },
                      "profile_url": {
                        "type": "string",
                        "description": "Direct URL to the creator's profile on this platform.",
                        "example": "https://instagram.com/janefashion"
                      }
                    }
                  }
                },
                "avg_likes_per_post": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Average number of likes per post across all platforms.",
                  "example": 2500
                },
                "avg_views_per_video": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Average number of views per video across all platforms.",
                  "example": 15000
                },
                "avg_comments_per_post": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Average number of comments per post across all platforms.",
                  "example": 120
                },
                "total_compliance_violations": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Total number of compliance violations detected across all posts.",
                  "example": 2
                },
                "compliance_violations_by_category": {
                  "type": "object",
                  "description": "Total compliance violations for this creator broken down by compliance family.\nSum of values equals `total_compliance_violations`. All four keys are always\npresent (zeros when no violations); values are non-negative integers.\n",
                  "properties": {
                    "FTC": {
                      "type": "integer",
                      "minimum": 0,
                      "example": 2
                    },
                    "FINRA": {
                      "type": "integer",
                      "minimum": 0,
                      "example": 0
                    },
                    "Healthcare": {
                      "type": "integer",
                      "minimum": 0,
                      "example": 0
                    },
                    "TTB": {
                      "type": "integer",
                      "minimum": 0,
                      "example": 0
                    }
                  },
                  "required": [
                    "FTC",
                    "FINRA",
                    "Healthcare",
                    "TTB"
                  ],
                  "example": {
                    "FTC": 2,
                    "FINRA": 0,
                    "Healthcare": 0,
                    "TTB": 0
                  }
                },
                "created_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "Timestamp when the creator record was created (ISO 8601).",
                  "example": "2024-06-15T10:30:00Z"
                },
                "posts_count": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Number of posts matching the current search query for this creator.",
                  "example": 18
                },
                "is_monitored": {
                  "type": "boolean",
                  "description": "Indicates whether the creator is currently being monitored (actively scanned for new content).",
                  "example": true
                },
                "deepest_scan": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DeepestScan"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "description": "Deepest scan tier the calling org has purchased for this creator. `null` when the org has no scan purchase.",
                  "example": {
                    "scan_type": "scan_full",
                    "display": "Comprehensive",
                    "purchased_at": "2026-05-01T12:34:56.789012Z"
                  }
                }
              }
            }
          }
        }
      },
      "PostSearchResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of posts matching the query.",
            "example": 128
          },
          "total_pages": {
            "type": "integer",
            "description": "Total number of pages available at the current page_size.",
            "example": 13
          },
          "page": {
            "type": "integer",
            "description": "Current page number (1-based).",
            "example": 1
          },
          "page_size": {
            "type": "integer",
            "description": "Number of results returned per page.",
            "example": 10
          },
          "results": {
            "type": "array",
            "description": "List of post search results for the current page.",
            "items": {
              "type": "object",
              "properties": {
                "post_id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Platform-specific post identifier.",
                  "example": "3197321792561269271"
                },
                "influencer_id": {
                  "type": "string",
                  "description": "Numeric identifier of the creator who authored this post.",
                  "example": "456"
                },
                "platform": {
                  "type": "string",
                  "description": "Platform the post originated from.",
                  "example": "instagram"
                },
                "post_url": {
                  "type": "string",
                  "description": "Direct URL to view the post on its native platform.",
                  "example": "https://instagram.com/p/ABC123/"
                },
                "posted_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time",
                  "description": "Timestamp when the post was published (ISO 8601).",
                  "example": "2024-08-20T14:30:00Z"
                },
                "likes_count": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Number of likes (or equivalent reactions) on the post.",
                  "example": 1500
                },
                "comments_count": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Number of comments on the post.",
                  "example": 42
                },
                "video_view_count": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Number of video views (null for non-video posts).",
                  "example": null
                },
                "combined_text": {
                  "type": "string",
                  "description": "Full text content of the post (caption, description, transcript, etc.).",
                  "example": "Loving this sustainable fashion brand! #ecofriendly #sustainable"
                },
                "image_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "URL of the post's thumbnail or primary image.",
                  "example": "https://media.vwd.ai/media/post-images/abc123.jpg"
                },
                "influencer_name": {
                  "type": "string",
                  "description": "Display name of the creator who authored this post.",
                  "example": "Jane Fashion"
                },
                "influencer_avatar": {
                  "type": "string",
                  "description": "URL of the creator's profile picture.",
                  "example": "https://media.vwd.ai/media/creators-profile-pics/jane.jpg"
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Article headline (Google News posts only).",
                  "example": null
                },
                "source_name": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Name of the news source (Google News posts only).",
                  "example": null
                },
                "display_categories": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  },
                  "description": "Content categories detected for this post.",
                  "example": []
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "API key authentication. You must include the 'Api-Key ' prefix before your API key in all requests. Format: `Authorization: Api-Key YOUR_API_KEY_HERE`"
      }
    }
  }
}