Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/vulk-dev:vulk-dev-projects-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: VULK REST Projects API
summary: Build, continue and read VULK projects from any program or AI agent.
description: 'The VULK REST API drives the VULK generation engine with the same plan and
credits as the editor: start a project from a brief, send it the next
instruction, follow the operation, read the delivered files, the models
your account may use and your usage.
The API is included in every VULK plan. Keys are created in Settings › API
keys at https://app.vulk.dev/settings?tab=ApiKeys and sent as
`Authorization: Bearer vk_sk_`. Each key belongs to one account, carries
the scopes chosen when it was created (projects.read, projects.write,
export.read, usage.read), may make 60 requests per minute and can be revoked
at any time.
Reads never start a generation and never spend credits. POST /projects and
POST /projects/{id}/messages spend the credits of your plan, as the same brief
typed into the editor would. Request bodies are JSON of at most 64 KB;
answers are JSON in camelCase with ISO 8601 dates in UTC. GET /api/v1 answers
without a key with the list of endpoints.
Reference: https://support.vulk.dev/docs/api. Quickstart and MCP setup:
https://vulk.dev/developers.'
version: 2.0.0
contact:
name: VULK Support
url: https://vulk.dev/contact
email: support@vulk.dev
termsOfService: https://vulk.dev/terms-conditions
license:
name: Proprietary
url: https://vulk.dev/terms-conditions
servers:
- url: https://app.vulk.dev/api/v1
description: Production
security:
- ApiKeyAuth: []
tags:
- name: Projects
description: Start, continue, list, read and delete projects; read their delivered files.
paths:
/projects:
get:
tags:
- Projects
operationId: listProjects
summary: List projects
description: Scope `projects.read`. Newest first.
parameters:
- name: limit
in: query
description: How many to return, 1 to 100.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: offset
in: query
description: How many to skip, 0 to 1000.
schema:
type: integer
minimum: 0
maximum: 1000
default: 0
responses:
'200':
description: The account's projects.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectList'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/RateLimited'
post:
tags:
- Projects
operationId: createProject
summary: Create a project from a brief
description: Scope `projects.write`. Starts a build and answers an admission receipt; the build runs after the answer and spends the credits of your plan, as the same brief typed into the editor would. Follow it with GET /operations/{requestId}.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Instruction'
example:
prompt: 'A landing page for a bakery in Porto: hero with the shop, the week''s bread, opening hours, a map and a contact form.'
model: auto
requestId: 7a1c0b7e-6a0f-4b0e-9a63-0f5c1b2d3e4f
responses:
'202':
description: 'Admission receipt. The build runs after this answer; follow it with GET /operations/{requestId}. `accepted: false` with `operationStatus: "unconfirmed"` means VULK had not recorded the operation within the wait: read the operation, then retry with exactly the same requestId and body.'
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/AdmissionReceipt'
example:
requestId: 7a1c0b7e-6a0f-4b0e-9a63-0f5c1b2d3e4f
accepted: true
operationStatus: running
projectId: cmgp3x8d7000a0wz4h2k1qv9r
editorUrl: https://app.vulk.dev/chat/cmgp3x8d7000a0wz4h2k1qv9r
nextAction: Read GET /operations/7a1c0b7e-… until operationStatus is done, waiting or failed.
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'429':
$ref: '#/components/responses/RateLimited'
'503':
$ref: '#/components/responses/ServiceUnavailable'
/projects/{id}:
parameters:
- name: id
in: path
required: true
description: A project id as returned by GET /projects. A project on another account answers 404, never 403.
schema:
type: string
get:
tags:
- Projects
operationId: getProject
summary: Read a project
description: Scope `projects.read`.
responses:
'200':
description: The project, its versions and its addresses.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
delete:
tags:
- Projects
operationId: deleteProject
summary: Delete a project
description: Scope `projects.write`. Deletes the project; the action is recorded against the key.
responses:
'200':
description: Deleted.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/Deleted'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
/projects/{id}/files:
parameters:
- name: id
in: path
required: true
description: A project id as returned by GET /projects. A project on another account answers 404, never 403.
schema:
type: string
get:
tags:
- Projects
operationId: getProjectFiles
summary: Read the delivered files
description: Scope `export.read`, on a plan that includes export. Without `path`, lists the files of the project's delivered version; with `path`, returns one file.
parameters:
- name: path
in: query
description: A path from the file list, e.g. `src/App.tsx`.
schema:
type: string
responses:
'200':
description: The file list, or one file when `path` is given.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/FileList'
- $ref: '#/components/schemas/FileContent'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/RateLimited'
/projects/{id}/messages:
parameters:
- name: id
in: path
required: true
description: A project id as returned by GET /projects. A project on another account answers 404, never 403.
schema:
type: string
post:
tags:
- Projects
operationId: sendInstruction
summary: Send the next instruction
description: 'Scope `projects.write`. The same body and the same receipt as POST /projects, applied to an existing project: `prompt` is the next instruction — or the answer to a question the operation is waiting for.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Instruction'
example:
prompt: 'A landing page for a bakery in Porto: hero with the shop, the week''s bread, opening hours, a map and a contact form.'
model: auto
requestId: 7a1c0b7e-6a0f-4b0e-9a63-0f5c1b2d3e4f
responses:
'202':
description: 'Admission receipt. The build runs after this answer; follow it with GET /operations/{requestId}. `accepted: false` with `operationStatus: "unconfirmed"` means VULK had not recorded the operation within the wait: read the operation, then retry with exactly the same requestId and body.'
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
content:
application/json:
schema:
$ref: '#/components/schemas/AdmissionReceipt'
example:
requestId: 7a1c0b7e-6a0f-4b0e-9a63-0f5c1b2d3e4f
accepted: true
operationStatus: running
projectId: cmgp3x8d7000a0wz4h2k1qv9r
editorUrl: https://app.vulk.dev/chat/cmgp3x8d7000a0wz4h2k1qv9r
nextAction: Read GET /operations/7a1c0b7e-… until operationStatus is done, waiting or failed.
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'429':
$ref: '#/components/responses/RateLimited'
'503':
$ref: '#/components/responses/ServiceUnavailable'
components:
schemas:
Deleted:
type: object
properties:
success:
type: boolean
id:
type: string
deletedAt:
type: string
format: date-time
required:
- success
- id
- deletedAt
Instruction:
type: object
properties:
prompt:
type: string
minLength: 1
maxLength: 8000
description: The brief, or the next instruction, in any language. It is handed to VULK unchanged.
model:
type: string
description: A model id from GET /models, or `auto`. Omit it to let VULK choose. A model your plan does not include answers 402.
example: auto
requestId:
type: string
format: uuid
description: 'A UUID v4 you make. Send the same requestId to retry a submit whose answer was lost: the API returns the operation it already created instead of starting a second one. Omitted, VULK makes one.'
required:
- prompt
AdmissionReceipt:
type: object
properties:
requestId:
type: string
format: uuid
accepted:
type: boolean
description: True when VULK recorded the operation.
operationStatus:
type:
- string
- 'null'
enum:
- running
- waiting
- done
- failed
- orphan
- unconfirmed
- null
description: '`unconfirmed` when `accepted` is false.'
projectId:
type: string
editorUrl:
type: string
format: uri
nextAction:
type: string
description: What to do next, in a sentence written for the caller.
required:
- requestId
- accepted
- operationStatus
- nextAction
FileContent:
type: object
properties:
projectId:
type: string
path:
type: string
bytes:
type: integer
content:
type: string
description: The file as UTF-8 text; cut after 200,000 characters, with `truncated` true.
truncated:
type: boolean
required:
- projectId
- path
- bytes
- content
- truncated
Error:
type: object
description: Every error has the same three fields; `code` is the value to branch on. A 429 also carries `retryAfter`.
properties:
error:
type: string
description: A sentence for the developer reading a log.
code:
type: string
enum:
- VALIDATION_ERROR
- UNAUTHORIZED
- PAYMENT_REQUIRED
- FORBIDDEN
- NOT_FOUND
- METHOD_NOT_ALLOWED
- CONFLICT
- PAYLOAD_TOO_LARGE
- RATE_LIMITED
- SERVER_ERROR
- SERVICE_UNAVAILABLE
status:
type: integer
retryAfter:
type: integer
description: Seconds to wait; only on 429.
required:
- error
- code
- status
example:
error: 'Missing API key. Send it as "Authorization: Bearer vk_sk_…". Keys are created in Settings › API keys.'
code: UNAUTHORIZED
status: 401
ProjectSummary:
type: object
properties:
id:
type: string
example: cmgp3x8d7000a0wz4h2k1qv9r
title:
type: string
kind:
type: string
enum:
- app
- image
- video
- mesh
description: '`app` for a website or app; `image`, `video` or `mesh` for a standalone design asset.'
createdAt:
type: string
format: date-time
url:
type: string
format: uri
description: The project's page in the editor.
required:
- id
- title
- kind
- createdAt
- url
ProjectList:
type: object
properties:
projects:
type: array
items:
$ref: '#/components/schemas/ProjectSummary'
count:
type: integer
pagination:
type: object
properties:
limit:
type: integer
offset:
type: integer
count:
type: integer
hasMore:
type: boolean
required:
- limit
- offset
- count
- hasMore
required:
- projects
- count
- pagination
Project:
type: object
description: '`versions` counts the builds; `files` and `bytes` describe the latest one. `siteName` and `liveUrl` are set once the project is published.'
properties:
id:
type: string
title:
type: string
folder:
type: string
versions:
type: integer
versionsWithFiles:
type: integer
files:
type: integer
bytes:
type: integer
lastVersionStatus:
type: string
description: A word such as `delivered` or `failed`.
lastVersionError:
type:
- string
- 'null'
description: An error code when the last version failed.
siteName:
type:
- string
- 'null'
previewUrl:
type:
- string
- 'null'
format: uri
liveUrl:
type:
- string
- 'null'
format: uri
url:
type: string
format: uri
description: The project's page in the editor.
required:
- id
- title
- folder
- versions
- versionsWithFiles
- files
- bytes
- lastVersionStatus
- url
FileList:
type: object
properties:
projectId:
type: string
version:
type: integer
description: The delivered version the files belong to.
files:
type: array
items:
type: object
properties:
path:
type: string
example: src/App.tsx
bytes:
type: integer
required:
- path
- bytes
totalFiles:
type: integer
totalBytes:
type: integer
truncated:
type: boolean
required:
- projectId
- version
- files
- totalFiles
- totalBytes
- truncated
responses:
RateLimited:
description: Over 60 requests in a minute; wait `retryAfter` seconds (code RATE_LIMITED).
headers:
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: No such endpoint, project, operation or file on this account (code NOT_FOUND).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: The key lacks the scope the endpoint needs (code FORBIDDEN).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ValidationError:
description: A parameter or body field is wrong; the sentence names it (code VALIDATION_ERROR).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
PaymentRequired:
description: The plan or credit balance does not cover the request (code PAYMENT_REQUIRED).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: No key, a malformed key, or a revoked or expired one (code UNAUTHORIZED).
headers:
WWW-Authenticate:
$ref: '#/components/headers/WWW-Authenticate'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ServiceUnavailable:
description: Generation or a dependency is temporarily unavailable; nothing was submitted (code SERVICE_UNAVAILABLE).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
PayloadTooLarge:
description: The body is over 64 KB (code PAYLOAD_TOO_LARGE).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Conflict:
description: The project has no delivered version with files yet (code CONFLICT).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
Retry-After:
description: Seconds to wait before the next request.
schema:
type: integer
example: 23
X-RateLimit-Remaining:
description: Requests left in the current minute.
schema:
type: integer
example: 42
X-RateLimit-Reset:
description: When the window resets, in Unix seconds.
schema:
type: integer
example: 1760360400
X-RateLimit-Limit:
description: Requests the key may make per minute.
schema:
type: integer
example: 60
WWW-Authenticate:
description: Always `Bearer realm="VULK API"`.
schema:
type: string
example: Bearer realm="VULK API"
securitySchemes:
ApiKeyAuth:
type: http
scheme: bearer
bearerFormat: vk_sk_*
description: 'Create a key in Settings › API keys (https://app.vulk.dev/settings?tab=ApiKeys) and send it as `Authorization: Bearer vk_sk_<key>`. Each endpoint names the scope the key needs; a key without it is answered 403.'
externalDocs:
description: API reference — every endpoint, scopes, errors and rate limits
url: https://support.vulk.dev/docs/api