{
  "openapi": "3.1.0",
  "info": {
    "title": "Craftwork Author API",
    "version": "1.0.0",
    "description": "For Craftwork authors: upload pack files, create packs and send them to review, follow review status and read stats. Authenticate with an author API key from https://craftwork.design/dashboard/api as `Authorization: Bearer cw_live_…`. Packs never go live without moderator review."
  },
  "servers": [
    {
      "url": "https://craftwork.design"
    }
  ],
  "externalDocs": {
    "description": "Author API documentation",
    "url": "https://craftwork.design/.well-known/api-docs/vendor.md"
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/api/v2/vendor/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Author shop behind the key",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Shop, key scopes and today's upload allowance.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Me"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v2/vendor/categories": {
      "get": {
        "operationId": "listCategories",
        "summary": "Categories an author can choose",
        "tags": [
          "Packs"
        ],
        "x-scope": "packs:read",
        "responses": {
          "200": {
            "description": "Sections with category slugs and subcategory ids.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Categories"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v2/vendor/packs": {
      "get": {
        "operationId": "listPacks",
        "summary": "List your packs and drafts",
        "tags": [
          "Packs"
        ],
        "x-scope": "packs:read",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "review",
                "published",
                "changes_required",
                "declined",
                "draft"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Packs newest first, with drafts on the first unfiltered page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PackList"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      },
      "post": {
        "operationId": "createPack",
        "summary": "Create a draft or send a pack to review",
        "tags": [
          "Packs"
        ],
        "x-scope": "packs:write",
        "description": "Without `submit` the pack is saved as a draft the author can finish in the dashboard. With `submit: true` it goes to moderator review and needs fileUrl, previews, shortDescription, description and categories. fileUrl and previews must be files uploaded with /api/v2/vendor/uploads.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PackCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PackCreated"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/api/v2/vendor/packs/{id}": {
      "get": {
        "operationId": "getPack",
        "summary": "One of your packs",
        "tags": [
          "Packs"
        ],
        "x-scope": "packs:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "`draft` reads a draft by its id",
            "schema": {
              "type": "string",
              "enum": [
                "pack",
                "draft"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pack with previews, variants and categories, or the raw draft.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PackDetail"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v2/vendor/uploads": {
      "post": {
        "operationId": "startUpload",
        "summary": "Start a file upload",
        "tags": [
          "Uploads"
        ],
        "x-scope": "packs:write",
        "description": "Returns presigned URLs for every part. PUT bytes `[(n-1)*partSize, n*partSize)` of the file to `parts[n-1].url` (no auth header), then call `completePath`. Up to 100 files a day; packs up to 10 GB, previews up to 50 MB.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadStart"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Upload started.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Upload"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/api/v2/vendor/uploads/{id}/complete": {
      "post": {
        "operationId": "completeUpload",
        "summary": "Finish an upload",
        "tags": [
          "Uploads"
        ],
        "x-scope": "packs:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`id` from startUpload"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadComplete"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The file's URL on the Craftwork CDN.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UploadedFile"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/api/v2/vendor/imports": {
      "post": {
        "operationId": "createImport",
        "summary": "Import a pack from an uploaded zip",
        "tags": [
          "Imports"
        ],
        "x-scope": "packs:write",
        "description": "Craftwork reads the uploaded zip (formats, asset groups, compatibility) and the optional pack page, copies its images and suggests name, short description, description, categories, tags and previews. Runs 5-60 s in the background: poll getImport until `status` is `ready`, then submitImport. 20 imports an hour per author.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportCreate"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Import queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Import"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/api/v2/vendor/imports/{id}": {
      "get": {
        "operationId": "getImport",
        "summary": "Import status and suggestion",
        "tags": [
          "Imports"
        ],
        "x-scope": "packs:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Import.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Import"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "description": "Statuses: queued, inspecting, fetching_link (only with sourceUrl), generating, then ready or failed; applied after submitImport sent it to review. A stuck import is restarted on read."
      }
    },
    "/api/v2/vendor/imports/{id}/submit": {
      "post": {
        "operationId": "submitImport",
        "summary": "Send an import to review",
        "tags": [
          "Imports"
        ],
        "x-scope": "packs:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportSubmit"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The import with `submitted` = draft or review and the productId or draftId.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Import"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          }
        },
        "description": "Turns a ready import into a pack: the suggestion plus the fields in the body. By default it goes to moderator review (price required); `submit: false` saves a draft the author can open in the dashboard upload wizard (dashboardUrl). After review submission the asset groups inside the zip become assets of the pack in the background (progress in `assets`)."
      }
    },
    "/api/v2/vendor/stats": {
      "get": {
        "operationId": "getStats",
        "summary": "Totals for 7, 30 or 90 days",
        "tags": [
          "Stats"
        ],
        "x-scope": "stats:read",
        "parameters": [
          {
            "name": "range",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "7d",
                "30d",
                "90d"
              ],
              "default": "30d"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Each metric with the previous period of the same length, and pack counts by status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Stats"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "cw_live_ + 40 characters",
        "description": "Author API key from https://craftwork.design/dashboard/api. Scopes: packs:read, packs:write, stats:read."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A query or path parameter is invalid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid or revoked API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key lacks the scope this endpoint needs (INSUFFICIENT_SCOPE).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found or not yours.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "Upload parts are missing (PARTS_MISSING), or the import is not ready (IMPORT_NOT_READY, IMPORT_FAILED) or already submitted (ALREADY_SUBMITTED).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooLarge": {
        "description": "File too large.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Send the body as application/json.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "The body failed validation; details lists each problem.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "120 requests a minute per key, or the daily upload limit (DAILY_UPLOAD_LIMIT). See Retry-After.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "examples": [
                  "INVALID_API_KEY",
                  "INSUFFICIENT_SCOPE",
                  "VALIDATION_FAILED",
                  "RATE_LIMITED"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "vendor": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "avatarUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "url": {
                "type": "string"
              }
            }
          },
          "auth": {
            "type": "object",
            "properties": {
              "via": {
                "type": "string",
                "enum": [
                  "api_key",
                  "session"
                ]
              },
              "keyId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "uploads": {
            "type": "object",
            "properties": {
              "dailyFileLimit": {
                "type": "integer"
              },
              "remainingToday": {
                "type": "integer"
              },
              "resetsAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "dashboardUrl": {
            "type": "string"
          }
        }
      },
      "Categories": {
        "type": "object",
        "properties": {
          "maxCategories": {
            "type": "integer"
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "categories": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer"
                            },
                            "slug": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "subcategories": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer"
                                  },
                                  "slug": {
                                    "type": "string"
                                  },
                                  "name": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "PackStatus": {
        "type": "string",
        "enum": [
          "review",
          "published",
          "changes_required",
          "declined",
          "draft"
        ]
      },
      "PackSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/PackStatus"
          },
          "coverUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "publishedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PackList": {
        "type": "object",
        "properties": {
          "packs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PackSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "drafts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                },
                "coverUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "PackDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PackSummary"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "pack",
                  "draft"
                ]
              },
              "shortDescription": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "website": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "previews": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string"
                    },
                    "isThumbnail": {
                      "type": "boolean"
                    },
                    "sortIndex": {
                      "type": "integer"
                    }
                  }
                }
              },
              "variants": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "name": {
                      "type": "string"
                    },
                    "fileName": {
                      "type": "string"
                    },
                    "commercialPrice": {
                      "type": "integer"
                    },
                    "extendedPrice": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  }
                }
              },
              "categories": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "slug": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "PackCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "shortDescription": {
            "type": "string",
            "maxLength": 300
          },
          "description": {
            "type": "string",
            "maxLength": 20000
          },
          "fileUrl": {
            "type": "string",
            "format": "uri",
            "description": "fileUrl of a completed pack upload"
          },
          "fileName": {
            "type": "string"
          },
          "previews": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Completed preview uploads; the first is the cover"
          },
          "price": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "description": "Commercial license, whole US dollars, 0 = free"
          },
          "extendedPrice": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Defaults to price x 3"
          },
          "categories": {
            "type": "array",
            "maxItems": 2,
            "items": {
              "type": "string"
            },
            "description": "Category slugs from listCategories"
          },
          "subcategories": {
            "type": "array",
            "maxItems": 6,
            "items": {
              "type": "integer"
            }
          },
          "tags": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string"
            }
          },
          "compatibility": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "figma",
                "sketch",
                "illustrator",
                "cinema4d",
                "blender",
                "photoshop",
                "adobeXd",
                "framer",
                "jitter",
                "html",
                "react",
                "notion",
                "powerpoint",
                "keynote",
                "googleSlides",
                "png",
                "jpg",
                "canva",
                "spline",
                "procreate",
                "code",
                "lottie",
                "svg",
                "eps",
                "gif",
                "pdf",
                "mp4",
                "json",
                "ttfOtf",
                "wordpress",
                "webflow"
              ]
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "website": {
                "type": "string",
                "format": "uri"
              },
              "figmaPreviewLink": {
                "type": "string",
                "format": "uri"
              },
              "framerPreviewLink": {
                "type": "string",
                "format": "uri"
              },
              "framerRemixLink": {
                "type": "string",
                "format": "uri"
              },
              "figmaDuplicateLink": {
                "type": "string",
                "format": "uri"
              },
              "webflowPreviewLink": {
                "type": "string",
                "format": "uri"
              },
              "notionPreviewLink": {
                "type": "string",
                "format": "uri"
              },
              "jitterDuplicateLink": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "message": {
            "type": "string",
            "maxLength": 2000,
            "description": "Note for moderators"
          },
          "submit": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "PackCreated": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "draft",
              "pack"
            ]
          },
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "review"
            ]
          },
          "dashboardUrl": {
            "type": "string"
          }
        }
      },
      "UploadStart": {
        "type": "object",
        "required": [
          "fileName",
          "size"
        ],
        "properties": {
          "fileName": {
            "type": "string",
            "maxLength": 200
          },
          "size": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact size in bytes"
          },
          "contentType": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "pack",
              "preview"
            ],
            "default": "pack"
          }
        }
      },
      "Upload": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "partSize": {
            "type": "integer"
          },
          "partCount": {
            "type": "integer"
          },
          "parts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "partNumber": {
                  "type": "integer"
                },
                "url": {
                  "type": "string"
                }
              }
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "completePath": {
            "type": "string"
          }
        }
      },
      "UploadComplete": {
        "type": "object",
        "properties": {
          "parts": {
            "type": "array",
            "description": "Optional ETag of each part; when omitted the server lists them",
            "items": {
              "type": "object",
              "required": [
                "partNumber",
                "etag"
              ],
              "properties": {
                "partNumber": {
                  "type": "integer"
                },
                "etag": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "UploadedFile": {
        "type": "object",
        "properties": {
          "fileUrl": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          }
        }
      },
      "ImportCreate": {
        "type": "object",
        "required": [
          "fileUrl"
        ],
        "properties": {
          "fileUrl": {
            "type": "string",
            "format": "uri"
          },
          "fileName": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer"
          },
          "sourceUrl": {
            "type": "string",
            "description": "Pack page elsewhere (Gumroad, UI8, own site)"
          }
        }
      },
      "ImportSubmit": {
        "type": "object",
        "properties": {
          "price": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "description": "Commercial license, whole US dollars, 0 = free. Required unless submit is false"
          },
          "extendedPrice": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Defaults to price x 3"
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "shortDescription": {
            "type": "string",
            "maxLength": 300
          },
          "description": {
            "type": "string",
            "maxLength": 20000
          },
          "categories": {
            "type": "array",
            "maxItems": 2,
            "items": {
              "type": "string"
            },
            "description": "Category slugs; default = suggestion"
          },
          "subcategories": {
            "type": "array",
            "maxItems": 6,
            "items": {
              "type": "integer"
            }
          },
          "tags": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string"
            }
          },
          "compatibility": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "figma",
                "sketch",
                "illustrator",
                "cinema4d",
                "blender",
                "photoshop",
                "adobeXd",
                "framer",
                "jitter",
                "html",
                "react",
                "notion",
                "powerpoint",
                "keynote",
                "googleSlides",
                "png",
                "jpg",
                "canva",
                "spline",
                "procreate",
                "code",
                "lottie",
                "svg",
                "eps",
                "gif",
                "pdf",
                "mp4",
                "json",
                "ttfOtf",
                "wordpress",
                "webflow"
              ]
            }
          },
          "previews": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Suggested preview URLs to keep in order (first = cover) or your own uploads"
          },
          "excludedGroups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "inventory.groups[].key that should not become separate assets"
          },
          "message": {
            "type": "string",
            "maxLength": 2000,
            "description": "Note for moderators"
          },
          "submit": {
            "type": "boolean",
            "default": true,
            "description": "false = save as a draft"
          }
        },
        "additionalProperties": false
      },
      "Import": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "inspecting",
              "fetching_link",
              "generating",
              "ready",
              "failed",
              "applied"
            ]
          },
          "ready": {
            "type": "boolean"
          },
          "fileName": {
            "type": "string"
          },
          "fileUrl": {
            "type": "string"
          },
          "sourceUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "enum": [
                    "inspect",
                    "link",
                    "generate"
                  ]
                },
                "state": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "running",
                    "done",
                    "skipped",
                    "failed"
                  ]
                },
                "message": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "assets": {
            "type": [
              "object",
              "null"
            ],
            "description": "After review submission: { state, requested, created, failed, skipped }"
          },
          "inventory": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "known",
                  "unknown"
                ]
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "files": {
                "type": "integer"
              },
              "formats": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "assetGroups": {
                "type": "integer"
              },
              "groups": {
                "type": "array",
                "description": "First 200 asset groups",
                "items": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "svg",
                        "raster",
                        "design"
                      ]
                    },
                    "thumbUrl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "link": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "siteName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "price": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "images": {
                "type": "integer"
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "suggestion": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "shortDescription": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "categories": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "subcategories": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "compatibility": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "previews": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "ai": {
                "type": "boolean"
              }
            }
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "draftId": {
            "type": [
              "integer",
              "null"
            ]
          },
          "productId": {
            "type": [
              "integer",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          },
          "dashboardUrl": {
            "type": "string",
            "description": "The upload wizard for a draft, else the products list"
          },
          "submitted": {
            "type": "string",
            "enum": [
              "draft",
              "review"
            ],
            "description": "Only in the submitImport response"
          }
        }
      },
      "Stats": {
        "type": "object",
        "properties": {
          "range": {
            "type": "string"
          },
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "type": "string"
          },
          "totals": {
            "type": "object",
            "additionalProperties": true,
            "description": "views, packDownloads, assetDownloads, sales, saves, earnings, pendingEarnings: each { current, previous }; plus earningsBySource"
          },
          "packs": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Pack count by status"
          }
        }
      }
    }
  }
}
