{
  "openapi": "3.0.3",
  "info": {
    "title": "Hajimete Text, Image and 3D API",
    "version": "1.1.0",
    "description": "One wallet across web, iOS, API and MCP. Text images: 1 credit standard, 4 premium. 3D: separate 12 credits. Quote and obtain approval before each generation. Failed jobs refund wallet and key allowance. Keys expire after 90 days; create/revoke them at /developers."
  },
  "servers": [
    {
      "url": "https://hajimete3d.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Hajimete API key"
      }
    }
  },
  "paths": {
    "/api/v1/images": {
      "get": {
        "summary": "List private uploads",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/api/v1/images/upload": {
      "post": {
        "summary": "Upload PNG or JPEG (free; max 5 MB; dimensions 16\u20134096 pixels)",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          },
          "201": {
            "description": "Image saved; response includes id, assetURL, width, height, name. Duplicate content returns existing image with 200."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "X-Content-Rights",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "confirmed"
              ]
            }
          },
          {
            "name": "X-Image-Name",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/images/{id}/asset": {
      "get": {
        "summary": "Read private uploaded image",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/images/{id}/delete": {
      "post": {
        "summary": "Permanently delete uploaded image; completed models remain",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Confirm-Delete",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "DELETE"
              ]
            }
          }
        ]
      }
    },
    "/api/v1/models": {
      "get": {
        "summary": "List models and shared credit balance, cost and remaining API allowance",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/api/v1/models/quote": {
      "post": {
        "summary": "Free cost quote (expires after 5 minutes)",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sourceID": {
                    "type": "string"
                  }
                },
                "required": [
                  "sourceID"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/models/create": {
      "post": {
        "summary": "Create real 3D model; charge shared wallet once",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          },
          "202": {
            "description": "Accepted; id, state and progress. States: submitting, running, saving, succeeded, failed. Replay returns the same job. Keep the same key and quote after network errors."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "quoteID": {
                    "type": "string"
                  }
                },
                "required": [
                  "quoteID"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 100,
              "pattern": "^[A-Za-z0-9-]+$"
            }
          }
        ]
      }
    },
    "/api/v1/models/{id}/status": {
      "get": {
        "summary": "Check progress (15 second polling recommended)",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/models/{id}/asset": {
      "get": {
        "summary": "Download completed GLB with bearer authentication",
        "responses": {
          "200": {
            "description": "Self-contained GLB",
            "content": {
              "model/gltf-binary": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/models/{id}/delete": {
      "post": {
        "summary": "Permanently remove completed model and provider copy",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "enum": [
                      "DELETE"
                    ]
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/artworks/quote": {
      "post": {
        "summary": "Quote a text-to-image creation",
        "description": "Free. Quote binds prompt, style and quality for five minutes. Show returned cost before creating.",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 1000
                  },
                  "style": {
                    "type": "string",
                    "enum": [
                      "anime",
                      "clay",
                      "plush",
                      "painted",
                      "asset"
                    ],
                    "default": "clay"
                  },
                  "quality": {
                    "type": "string",
                    "enum": [
                      "standard",
                      "premium"
                    ],
                    "default": "standard"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/artworks/create": {
      "post": {
        "summary": "Create quoted 2D artwork",
        "description": "Obtain approval first. Allow 120 seconds. Reuse quoteID and UUID on all retries, including timeout. A succeeded job returns sourceID for a separate 3D quote. Failed jobs refund wallet and API allowance. Unfinished jobs reconcile on read/retry after three minutes.",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "quoteID"
                ],
                "properties": {
                  "quoteID": {
                    "type": "string",
                    "description": "The approved text quote"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/api/v1/artworks": {
      "get": {
        "summary": "List shared 2D artwork",
        "description": "Includes web, iOS and API artwork, newest first. Pass nextCursor as before for the next page.",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "in": "query",
            "name": "before",
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,15}$"
            }
          }
        ]
      }
    },
    "/api/v1/artworks/{id}/status": {
      "get": {
        "summary": "Read artwork status",
        "description": "Account ownership and valid authentication are required. Poll every 15 seconds or slower.",
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/artworks/{id}/asset": {
      "get": {
        "summary": "Read artwork asset",
        "description": "Account ownership and valid authentication are required. Returns private PNG/JPEG bytes.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request"
          },
          "401": {
            "description": "Sign in or provide a valid key"
          },
          "402": {
            "description": "Insufficient wallet balance or API allowance"
          },
          "403": {
            "description": "Origin rejected or payment review required"
          },
          "404": {
            "description": "Resource not found in this account"
          },
          "409": {
            "description": "Quote conflict, active job, changed balance or key allowance"
          },
          "429": {
            "description": "Rate limited; wait before retrying"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    }
  }
}
