{
  "openapi": "3.1.0",
  "info": {
    "title": "Genvizu Read-only API",
    "version": "1.0.0",
    "description": "Read-only access to the Genvizu prompt library and Skills catalog, available on the Pro and Ultimate plans. It never generates media and never spends credits. Data is provided for search and reference only, carries no model-training rights, and must keep its attribution. Docs: https://genvizu.com/docs/api"
  },
  "servers": [
    {
      "url": "https://genvizu.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "prompts"
    },
    {
      "name": "skills"
    },
    {
      "name": "account"
    }
  ],
  "paths": {
    "/api/v1/prompts/search": {
      "get": {
        "tags": [
          "prompts"
        ],
        "operationId": "searchPrompts",
        "summary": "Search the prompt library",
        "description": "Same filters and visibility rules as the public gallery search. List items carry thumbnail_url only; fetch /api/v1/prompts/{id} for full media_urls. Pro and Ultimate get full prompt text, except individually paid posts, which stay truncated (prompt_locked=true).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "description": "Keywords; every word must match the prompt or title."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Model slug, e.g. gpt-image-2."
          },
          {
            "name": "mediaType",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "workflow"
              ]
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Tag id."
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "latest",
                "hot",
                "random"
              ]
            },
            "description": "Omit for the default featured order."
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 1
            },
            "description": "Values outside 1–10 return 400 invalid_params."
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 20
            },
            "description": "Values outside 1–20 return 400 invalid_params."
          },
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "zh"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Daily request limit for this account."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left today."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PromptListItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/SearchMeta"
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "0f8c6b1e-2d7a-4b8e-9d52-7a1c3f5e9b10",
                      "slug": "neon-rain-city",
                      "title": "Neon rain city",
                      "prompt": "A rain-soaked cyberpunk street at night, neon signs reflected in puddles...",
                      "prompt_locked": false,
                      "media_type": "image",
                      "model": "gpt-image-2",
                      "thumbnail_url": "https://media.genvizu.com/thumbs/neon.webp",
                      "image_width": 1024,
                      "image_height": 1536,
                      "likes": 12,
                      "views": 340,
                      "favorites_count": 5,
                      "published_at": "2026-09-01T08:00:00.000Z",
                      "attribution": {
                        "author": "Jane Doe",
                        "author_url": "https://x.com/janedoe",
                        "source_url": "https://x.com/janedoe/status/1",
                        "platform": "X",
                        "page_url": "https://genvizu.com/gallery/neon-rain-city"
                      }
                    }
                  ],
                  "meta": {
                    "page": 1,
                    "page_size": 20,
                    "has_more": true,
                    "locale": "en",
                    "tier": "pro",
                    "quota": {
                      "limit": 1000,
                      "used": 12,
                      "remaining": 988
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          },
          "400": {
            "$ref": "#/components/responses/InvalidParams"
          }
        }
      }
    },
    "/api/v1/prompts/{id}": {
      "get": {
        "tags": [
          "prompts"
        ],
        "operationId": "getPrompt",
        "summary": "Get one prompt with all segments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64
            }
          },
          {
            "name": "locale",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "zh"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Daily request limit for this account."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left today."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PromptDetail"
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "locale": {
                          "type": "string"
                        },
                        "tier": {
                          "$ref": "#/components/schemas/QuotaTier"
                        },
                        "quota": {
                          "$ref": "#/components/schemas/QuotaMeta"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/skills": {
      "get": {
        "tags": [
          "skills"
        ],
        "operationId": "listSkills",
        "summary": "List published Skills",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Daily request limit for this account."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left today."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Skill"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "tier": {
                          "$ref": "#/components/schemas/QuotaTier"
                        },
                        "quota": {
                          "$ref": "#/components/schemas/QuotaMeta"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/skills/{id}/compose": {
      "post": {
        "tags": [
          "skills"
        ],
        "operationId": "composeSkill",
        "summary": "Compose a prompt from Skill parameters",
        "description": "Assembles a ready-to-use prompt. Nothing is generated and no credits are spent.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ComposeRequest"
              },
              "example": {
                "prompt": "a matte black water bottle",
                "params": {
                  "scene": "studio"
                },
                "strength": "mid"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Daily request limit for this account."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left today."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ComposeResult"
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "tier": {
                          "$ref": "#/components/schemas/QuotaTier"
                        },
                        "quota": {
                          "$ref": "#/components/schemas/QuotaMeta"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParams"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "tags": [
          "account"
        ],
        "operationId": "getMe",
        "summary": "Credit balance, plan and today's quota",
        "description": "Does not count toward the daily quota.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Me"
                    },
                    "meta": {
                      "type": "object"
                    }
                  }
                },
                "example": {
                  "data": {
                    "credits_balance": 1850,
                    "tier": "pro",
                    "access_mode": "subscription",
                    "quota": {
                      "tier": "pro",
                      "limit": 1000,
                      "used": 42,
                      "remaining": 958,
                      "resets_at": "2026-09-25T00:00:00.000Z"
                    }
                  },
                  "meta": {}
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key created in Settings → API Keys (starts with sk_)."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, malformed, deleted or unknown API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Account suspended or email not verified (code forbidden), the plan has no API access (code plan_required), or the Skill needs a higher plan (code forbidden).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "plan_required",
                "message": "API access requires the Pro plan or higher."
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found or not public.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InvalidParams": {
        "description": "Malformed request or input rejected by the content policy.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Daily quota used up, or requests on the same key less than 1 second apart.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Daily API quota exceeded (1000 requests/day). Resets at 00:00 UTC."
              }
            }
          }
        }
      },
      "Unavailable": {
        "description": "The API has been temporarily switched off by the operator.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "unavailable",
                "message": "The Genvizu API is temporarily unavailable."
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "unauthorized",
                  "forbidden",
                  "plan_required",
                  "rate_limited",
                  "not_found",
                  "invalid_params",
                  "unavailable",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "QuotaTier": {
        "type": "string",
        "enum": [
          "free",
          "payg",
          "starter",
          "pro",
          "ultimate"
        ]
      },
      "Attribution": {
        "type": "object",
        "properties": {
          "author": {
            "type": [
              "string",
              "null"
            ]
          },
          "author_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "page_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SearchMeta": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer"
          },
          "page_size": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "locale": {
            "type": "string"
          },
          "tier": {
            "$ref": "#/components/schemas/QuotaTier"
          },
          "quota": {
            "$ref": "#/components/schemas/QuotaMeta"
          }
        }
      },
      "PromptListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "prompt": {
            "type": "string"
          },
          "prompt_locked": {
            "type": "boolean",
            "description": "True when the prompt was truncated for your plan."
          },
          "media_type": {
            "type": "string"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "image_width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "image_height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "likes": {
            "type": "integer"
          },
          "views": {
            "type": "integer"
          },
          "favorites_count": {
            "type": "integer"
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        }
      },
      "PromptSegment": {
        "type": "object",
        "properties": {
          "media_type": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "prompt": {
            "type": "string"
          },
          "prompt_locked": {
            "type": "boolean"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "thumbnail_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "image_width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "image_height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "duration_sec": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "PromptDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "media_type": {
            "type": "string"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "thumbnail_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "likes": {
            "type": "integer"
          },
          "views": {
            "type": "integer"
          },
          "favorites_count": {
            "type": "integer"
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PromptSegment"
            }
          },
          "attribution": {
            "$ref": "#/components/schemas/Attribution"
          }
        }
      },
      "LocalizedText": {
        "type": "object",
        "properties": {
          "en": {
            "type": "string"
          },
          "zh": {
            "type": "string"
          }
        }
      },
      "SkillParam": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "label": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "control": {
            "type": "string",
            "enum": [
              "select",
              "multiselect",
              "slider",
              "toggle",
              "text",
              "camera"
            ]
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "$ref": "#/components/schemas/LocalizedText"
                },
                "ratio": {
                  "type": "string"
                },
                "img": {
                  "type": "string"
                }
              }
            }
          },
          "range": {
            "type": "array",
            "items": {
              "type": "number"
            },
            "minItems": 3,
            "maxItems": 3
          },
          "max_length": {
            "type": "integer"
          },
          "default": {},
          "required": {
            "type": "boolean"
          }
        }
      },
      "Skill": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "status": {
            "type": "string"
          },
          "execution_mode": {
            "type": "string",
            "enum": [
              "planner",
              "direct"
            ]
          },
          "params": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillParam"
            }
          },
          "input_spec": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "min_images": {
                "type": "integer"
              },
              "max_images": {
                "type": "integer"
              },
              "image_role": {
                "type": "object",
                "properties": {
                  "en": {
                    "type": "string"
                  },
                  "zh": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "defaults": {
            "type": "object",
            "properties": {
              "model": {
                "type": "string"
              },
              "ratio": {
                "type": "string"
              },
              "resolution": {
                "type": "string"
              },
              "quality": {
                "type": "string"
              },
              "count": {
                "type": "integer"
              }
            }
          },
          "cover": {
            "type": [
              "string",
              "null"
            ]
          },
          "min_plan": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "starter",
              "pro",
              "ultimate",
              null
            ]
          }
        }
      },
      "ComposeRequest": {
        "type": "object",
        "properties": {
          "prompt": {
            "type": "string",
            "maxLength": 3000,
            "description": "Your brief."
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "description": "Parameter values keyed by Skill param key."
          },
          "strength": {
            "type": "string",
            "enum": [
              "low",
              "mid",
              "high"
            ],
            "default": "mid"
          }
        }
      },
      "ComposeResult": {
        "type": "object",
        "properties": {
          "skill_id": {
            "type": "string"
          },
          "prompt": {
            "type": "string"
          },
          "recommended": {
            "type": "object",
            "properties": {
              "model": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ratio": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "resolution": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          },
          "strength": {
            "type": "string"
          },
          "requires_images": {
            "type": "object",
            "properties": {
              "min": {
                "type": "integer"
              },
              "max": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "execution_mode": {
            "type": "string"
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "credits_balance": {
            "type": "integer"
          },
          "tier": {
            "type": "string",
            "enum": [
              "free",
              "starter",
              "pro",
              "ultimate"
            ]
          },
          "access_mode": {
            "type": "string"
          },
          "quota": {
            "type": "object",
            "properties": {
              "tier": {
                "$ref": "#/components/schemas/QuotaTier"
              },
              "limit": {
                "type": "integer"
              },
              "used": {
                "type": "integer"
              },
              "remaining": {
                "type": "integer"
              },
              "resets_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "QuotaMeta": {
        "type": "object",
        "description": "Quota after this request.",
        "properties": {
          "limit": {
            "type": "integer"
          },
          "used": {
            "type": "integer"
          },
          "remaining": {
            "type": "integer"
          }
        }
      }
    }
  }
}
