> ## Documentation Index
> Fetch the complete documentation index at: https://docs.molfex.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a project

> Creates a draft project and returns a presigned `uploadUrl`.
PUT the file to that URL, then call publish.




## OpenAPI

````yaml /openapi.yaml post /projects
openapi: 3.1.0
info:
  title: Molfex API
  version: 1.0.0
  summary: Host a file or static site on a molfex.app URL.
  description: >
    Authenticate with `Authorization: Bearer molfex_...`.

    Create a key at
    [studio.molfex.app/api-keys](https://studio.molfex.app/api-keys).

    There is no guest or email-only upload.


    ### Publish loop


    1. `POST /projects` — get `uploadUrl` and `contentType`

    2. `PUT` the file to `uploadUrl` (expires in one hour)

    3. `POST /projects/{id}/publish`

    4. Poll `GET /projects/{id}` until `active` or `failed`


    `url` values are hostnames without `https://`. Open `https://{url}`.


    Publish uses credits. If you are out, buy more on the billing page.
  contact:
    url: https://studio.molfex.app
  license:
    name: Proprietary
servers:
  - url: https://studio.molfex.app/api/v1
    description: Production
security:
  - apiKey: []
tags:
  - name: Projects
    description: Create, publish, list, replace, and delete hosted projects.
paths:
  /projects:
    post:
      tags:
        - Projects
      summary: Create a project
      description: |
        Creates a draft project and returns a presigned `uploadUrl`.
        PUT the file to that URL, then call publish.
      operationId: createProject
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectRequest'
            examples:
              publicZip:
                summary: Public zip site
                value:
                  slug: my-site
                  fileName: site.zip
              passwordSite:
                summary: Password-protected site
                value:
                  slug: locked-site
                  fileName: site.zip
                  siteSettings:
                    passwordProtected: true
                    password: secret
      responses:
        '200':
          description: Draft created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateProjectResponse'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    CreateProjectRequest:
      type: object
      required:
        - slug
        - fileName
      properties:
        slug:
          type: string
          pattern: ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$
          description: Lowercase letters, numbers, and hyphens. Becomes {slug}.molfex.app.
          example: my-site
        fileName:
          type: string
          minLength: 1
          maxLength: 255
          example: site.zip
        siteSettings:
          $ref: '#/components/schemas/SiteSettings'
    CreateProjectResponse:
      type: object
      required:
        - ok
        - data
      properties:
        ok:
          type: boolean
          enum:
            - true
        data:
          type: object
          required:
            - projectId
            - uploadUrl
            - contentType
            - url
          properties:
            projectId:
              type: integer
            uploadUrl:
              type: string
              format: uri
              description: Presigned PUT URL. Expires in one hour.
            contentType:
              type: string
              description: Send this exact Content-Type on the PUT.
            url:
              type: string
              description: Hostname without scheme.
              example: my-site.molfex.app
    SiteSettings:
      type: object
      required:
        - passwordProtected
      properties:
        passwordProtected:
          type: boolean
        password:
          type: string
          minLength: 4
          maxLength: 200
          description: Required when passwordProtected is true.
    ErrorBody:
      type: object
      required:
        - ok
        - error
      properties:
        ok:
          type: boolean
          enum:
            - false
        error:
          type: string
  responses:
    Error:
      description: Validation or business error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            ok: false
            error: You need an API key
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: molfex
      description: API key from https://studio.molfex.app/api-keys. Starts with `molfex_`.

````