{"openapi":"3.1.0","info":{"title":"vmotif Public API","version":"1.0.0","description":"REST API for vmotif's AI generation and workflow engine. Authenticate with an API key (`vmk_live_*`) created in Settings → API. All requests require a `Bearer` token; generation endpoints additionally require a key with the `write` scope.","contact":{"name":"vmotif","url":"https://vmotif.com"}},"servers":[{"url":"https://www.vmotif.com/api/v1","description":"Production"}],"security":[{"BearerAuth":[]}],"tags":[{"name":"Generations","description":"Single image or code generations."},{"name":"Workflows","description":"List workflows and run them server-side."},{"name":"Catalog","description":"Models and account usage."}],"paths":{"/generations":{"post":{"operationId":"createGeneration","summary":"Create a generation","description":"Enqueue an image or code generation. Returns immediately with a job id; poll `GET /generations/{id}` for the result. Requires the `write` scope.","tags":["Generations"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationRequest"}}}},"responses":{"202":{"description":"Job accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationAccepted"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/InsufficientScope"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/generations/{id}":{"get":{"operationId":"getGeneration","summary":"Get a generation","description":"Poll the status and result of a generation job. Requires the `read` scope.","tags":["Generations"],"parameters":[{"$ref":"#/components/parameters/GenerationId"}],"responses":{"200":{"description":"Current job state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationStatus"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/models":{"get":{"operationId":"listModels","summary":"List available models","description":"The curated model catalog with live, marked-up pricing. Cached for 5 minutes. Requires the `read` scope.","tags":["Catalog"],"responses":{"200":{"description":"Model catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelsResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/usage":{"get":{"operationId":"getUsage","summary":"Get account usage","description":"The caller's current tier, token budget, and usage for the period. `null` budgets mean unlimited (Enterprise). Requires the `read` scope.","tags":["Catalog"],"responses":{"200":{"description":"Usage snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/workflows":{"get":{"operationId":"listWorkflows","summary":"List workflows","description":"The caller's workflows, most recently updated first. Requires the `read` scope.","tags":["Workflows"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Max results to return (1–100).","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","required":false,"description":"Number of results to skip.","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Workflow summaries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowsResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/workflows/{id}/runs":{"post":{"operationId":"runWorkflow","summary":"Run a workflow","description":"Execute all generatable nodes of a workflow server-side. Returns a run id; poll `GET /workflows/{id}/runs/{runId}`. Requires the `write` scope.","tags":["Workflows"],"parameters":[{"$ref":"#/components/parameters/WorkflowId"}],"responses":{"202":{"description":"Run accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunAccepted"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InsufficientScope"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/workflows/{id}/runs/{runId}":{"get":{"operationId":"getWorkflowRun","summary":"Get a workflow run","description":"Poll the status, progress, and per-node results of a workflow run. Requires the `read` scope.","tags":["Workflows"],"parameters":[{"$ref":"#/components/parameters/WorkflowId"},{"name":"runId","in":"path","required":true,"description":"Run id returned by `POST /workflows/{id}/runs`.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Current run state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowRun"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"An API key created in Settings → API, sent as `Authorization: Bearer vmk_live_...`."}},"parameters":{"GenerationId":{"name":"id","in":"path","required":true,"description":"Generation job id returned by `POST /generations`.","schema":{"type":"string","format":"uuid"}},"WorkflowId":{"name":"id","in":"path","required":true,"description":"Workflow id.","schema":{"type":"string","format":"uuid"}}},"schemas":{"ApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","enum":["invalid_request","unauthorized","insufficient_scope","rate_limited","insufficient_quota","payment_required","not_found","server_error"],"description":"Stable, machine-readable error category."},"message":{"type":"string","description":"Human-readable description."}}}}},"ImageInput":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"Reference image as an `https://` URL or a `data:` URI."},"mediaType":{"type":"string","default":"image/png","description":"MIME type of the image."}}},"TextInput":{"type":"object","required":["content"],"properties":{"content":{"type":"string","maxLength":50000,"description":"Text passed to the model."},"label":{"type":"string","description":"Optional label; defaults to `Input N`."},"language":{"type":"string","description":"Optional language hint for code inputs."}}},"AspectRatio":{"type":"string","enum":["1:1","16:9","9:16","4:3","3:4","3:2","2:3"],"description":"Output aspect ratio (image generations)."},"CodeLanguage":{"type":"string","enum":["text","tsx","jsx","css","svg","json","typescript","javascript","mdx","markdown"],"description":"Target language for code generations."},"GenerationRequest":{"type":"object","required":["type","prompt"],"properties":{"type":{"type":"string","enum":["image","code"],"description":"Kind of output. Must be compatible with `model`."},"prompt":{"type":"string","minLength":1,"maxLength":50000,"description":"Generation prompt."},"model":{"type":"string","description":"Model id from `GET /models`. Defaults to `openai/gpt-image-2` for images and `anthropic/claude-sonnet-4.6` for code."},"images":{"type":"array","maxItems":10,"items":{"$ref":"#/components/schemas/ImageInput"},"description":"Reference images (image generations)."},"textInputs":{"type":"array","maxItems":10,"items":{"$ref":"#/components/schemas/TextInput"},"description":"Additional text inputs."},"aspectRatio":{"$ref":"#/components/schemas/AspectRatio"},"targetLanguage":{"$ref":"#/components/schemas/CodeLanguage"},"screenHtml":{"type":"boolean","default":false,"description":"Render the code output as a full HTML screen."}}},"JobStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"GenerationAccepted":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]}}},"ImageResult":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["image"]},"url":{"type":["string","null"],"description":"Signed URL to the generated image."},"mediaType":{"type":["string","null"]},"aspectRatio":{"type":"string"},"costMicros":{"type":"number","description":"Billed cost in micro-dollars."}}},"CodeResult":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["code"]},"code":{"type":["string","null"]},"structuredOutput":{"description":"Parsed structured output when the model returns JSON."},"costMicros":{"type":"number","description":"Billed cost in micro-dollars."}}},"GenerationStatus":{"type":"object","required":["id","status","result","error"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/JobStatus"},"result":{"oneOf":[{"$ref":"#/components/schemas/ImageResult"},{"$ref":"#/components/schemas/CodeResult"},{"type":"null"}],"description":"Present once `status` is `completed`."},"error":{"type":["string","null"],"description":"Failure reason when `status` is `failed`."}}},"Model":{"type":"object","required":["id","name","category","provider","supports_image_input","input_modalities","output_modalities","pricing"],"properties":{"id":{"type":"string","description":"Model id to pass as `model` in a generation."},"name":{"type":"string"},"category":{"type":"string","enum":["image","text","svg"]},"provider":{"type":"string"},"supports_image_input":{"type":"boolean"},"input_modalities":{"type":"array","items":{"type":"string"}},"output_modalities":{"type":"array","items":{"type":"string"}},"pricing":{"type":["object","null"],"description":"Marked-up display pricing. Shape varies by model; null when unknown.","additionalProperties":true}}},"ModelsResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Model"}}}},"Usage":{"type":"object","required":["tier","token_budget_micros","used_micros","remaining_micros","resets_at"],"properties":{"tier":{"type":"string","enum":["legacy_free","pro","enterprise","blocked"]},"token_budget_micros":{"type":["integer","null"],"description":"Period budget in micro-dollars; null = unlimited."},"used_micros":{"type":"integer","description":"Micro-dollars used this period."},"remaining_micros":{"type":["integer","null"],"description":"Micro-dollars remaining; null = unlimited."},"resets_at":{"type":["string","null"],"format":"date-time","description":"When the budget resets; null if not applicable."}}},"WorkflowSummary":{"type":"object","required":["id","name","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"WorkflowsResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowSummary"}}}},"RunAccepted":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]}}},"WorkflowRunResult":{"type":"object","required":["promptNodeId","outputNodeId","type","status"],"properties":{"promptNodeId":{"type":"string"},"outputNodeId":{"type":"string"},"type":{"type":"string","enum":["image","code","screen","design"]},"status":{"type":"string","enum":["completed","failed","skipped"]},"url":{"type":"string","description":"Signed URL (image outputs)."},"mediaType":{"type":"string","description":"Image outputs."},"code":{"type":"string","description":"Code/screen/design outputs."},"error":{"type":"string","description":"Set when `status` is `failed`."},"costMicros":{"type":"number"}}},"WorkflowRun":{"type":"object","required":["id","workflowId","status","progress","results","error","createdAt","completedAt"],"properties":{"id":{"type":"string","format":"uuid"},"workflowId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed"]},"progress":{"type":"object","required":["total","completed"],"properties":{"total":{"type":"integer"},"completed":{"type":"integer"}}},"results":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowRunResult"}},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}}}},"responses":{"InvalidRequest":{"description":"The request was malformed or failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"Unauthorized":{"description":"Missing, malformed, revoked, or unknown API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"InsufficientScope":{"description":"The key lacks the scope required for this endpoint (write).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"PaymentRequired":{"description":"The key bills to a workspace without an active Team plan, or the owner no longer administers it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"RateLimited":{"description":"Rate limit or budget exceeded. `insufficient_quota` and `rate_limited` both use 429; a `retry-after` header is set on rate limits.","headers":{"retry-after":{"schema":{"type":"integer"},"description":"Seconds until the limit resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"NotFound":{"description":"The resource does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"ServerError":{"description":"An unexpected error, or the rate limiter is unavailable (503).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}