API Reference

Builder API

Power your own AI website builder using AICODESIT as the backend engine. Create projects, run AI builds, and stream results in real time — from any domain, with a single key.

Authentication

All Builder API requests require a Builder API key passed as a Bearer token:

Authorization: Bearer wlk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Keys start with wlk_ and are generated in your dashboard under Builder API. Each key is tied to your account — builds and AI credits run against your plan.

Get a key: Dashboard → Builder API → Create key → copy the full key (shown once) → optionally download a pre-configured index.html.

Security scope: Builder keys are hard-limited to the 7 endpoints on this page. A key cannot list your projects, read files, access secrets, or delete anything. Revoke anytime from the dashboard.

Base URL & CORS

https://api.aicodesit.com

All 7 builder endpoints return Access-Control-Allow-Origin: *, so your page can be hosted on any domain — static hosting, file://, or localhost. No proxy or server needed.

The build flow

Every build follows three steps:

1. POST /projects              → create a workspace   (do this once, persist the ID)
2. POST /pipeline/:id/run      → start an AI build    → returns { runId }
3. GET  /pipeline/:id/run/:runId/stream  → stream live events until "complete"

After the stream completes, poll GET /projects/:id/preview every 2–3 seconds until the preview is live, then render the URL in an <iframe>.

1. Create a project

POST /projects

Creates a new isolated project workspace. Call this once per user session and store the returned id in localStorage.

Request body

FieldTypeDescription
name string required Human-readable project name.
subdomain string required Globally unique subdomain for the preview URL. Lowercase alphanumeric and hyphens only. Safe pattern: yourprefix- + 6 random digits.
template_repo string optional Starter template id from GET /projects/templates. The project is created with the template's files — a working site before any prompt is sent. Omit for the minimal default. Unknown ids return 400.
POST /projects
Authorization: Bearer wlk_...
Content-Type: application/json

{
  "name": "my-app-123456",
  "subdomain": "my-app-123456"
}

Response 200

{
  "id": "3af2cfcb-7127-4aff-ab63-257372d810d9",
  "subdomain": "my-app-123456",
  "status": "pending",
  ...
}

Persist the id — it is required by all subsequent calls.

2. Start an AI build run

POST /pipeline/:projectId/run

Starts an AI build in the background and immediately returns a runId. Connect to the stream endpoint to receive live events.

Request body

FieldTypeDescription
userMessage string required The current user prompt.
conversationHistory array required Full conversation array including the current message. Each item: { role: "user"|"assistant", content: "..." }. Must include the current message — see note below.
model string optional Model id from GET /pipeline/models. Overrides the AI model for the whole run. Omit to use the platform default. Unknown ids return 400.
Important: The current prompt must appear in both userMessage and inside conversationHistory. The AI engine reads the task from conversation history. Omitting it from history causes the model to respond as if no task was given.

First turn

{
  "userMessage": "Build me a landing page for a coffee shop",
  "conversationHistory": [
    { "role": "user", "content": "Build me a landing page for a coffee shop" }
  ]
}

Follow-up turn (include previous turns)

{
  "userMessage": "Now make the header dark",
  "conversationHistory": [
    { "role": "user",      "content": "Build me a landing page for a coffee shop" },
    { "role": "assistant", "content": "I've created a landing page with a warm color scheme..." },
    { "role": "user",      "content": "Now make the header dark" }
  ]
}

Include the last 6–8 turns max. Older history can be trimmed without affecting quality.

Response 200

{ "runId": "c284d4a9-2708-4f7e-956c-35e49da0d834" }

3. Stream build events (SSE)

GET /pipeline/:projectId/run/:runId/stream

Returns a Server-Sent Events stream. Each line is:

data: { ...event object... }

Event types

eventDescriptionKey fields
startA pipeline step startedstepId
logActivity line — file ops, statusdata (string)
chunkFragment of the AI text responsedata (string)
messagesInternal message array snapshot
doneA step completedstepId, output
errorA step errorerror (string)
loop_iterLoop iteration counter
completeRun finished — close the stream

Log event markers

log events contain human-readable status and file markers you can parse:

[wrote: src/index.html]        → file created
[edited: src/pages/Home.tsx]   → file modified
[deleted: src/old.js]          → file removed

Chunk events

Strip internal AI working tags before displaying chunk text: <think>, <file>, <edit>, <gather>, <cmd>.

Stream parsing (JavaScript)

const stream = await fetch(
  `https://api.aicodesit.com/pipeline/${projectId}/run/${runId}/stream`,
  { headers: { Authorization: 'Bearer ' + KEY } }
);
const reader  = stream.body.getReader();
const decoder = new TextDecoder();
let buffer = '';

outer: while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop() || '';

  for (const line of lines) {
    if (!line.startsWith('data: ')) continue;
    const evt = JSON.parse(line.slice(6));
    if (evt.event === 'complete') { reader.cancel(); break outer; }
    if (evt.event === 'log')      console.log('[log]', evt.data?.trim());
    if (evt.event === 'chunk')    appendToChat(evt.data || '');
    if (evt.event === 'error')    console.error('[error]', evt.error);
  }
}

4. Stop a running build

DELETE /pipeline/:projectId/run/:runId

Aborts the AI run immediately. File changes made before the stop are kept.

Response 200: { "ok": true }

5. Get preview status

GET /projects/:projectId/preview

Starts the live preview server on first call. Poll every 2–3 seconds until status === "ready", then load the previewUrl in an <iframe>.

Response 200

{
  "status": "ready",
  "previewUrl": "https://my-app-123456.aicodesit.app/"
}
statusMeaning
buildingPreview server is starting up — keep polling
readyPreview is live — render the previewUrl in an iframe
errorServer error — retry or call POST /projects/:id/rebuild
async function waitForPreview(projectId) {
  const API = 'https://api.aicodesit.com';
  const headers = { Authorization: 'Bearer ' + KEY };
  while (true) {
    const { status, previewUrl } = await fetch(
      `${API}/projects/${projectId}/preview`, { headers }
    ).then(r => r.json());
    if (status === 'ready')  return previewUrl;
    if (status === 'error')  throw new Error('Preview failed');
    await new Promise(r => setTimeout(r, 2500));
  }
}

const url = await waitForPreview(projectId);
document.querySelector('#preview').src = url;

6. List selectable models

GET /pipeline/models

Returns the AI models a build run can use — pass one of the ids as the optional model field when starting a run. The list only contains models the platform has enabled for building (image/video models are excluded).

Response 200

{
  "models": [
    { "id": "qwen/qwen3.7-plus",         "label": "Aicodesit",   "free": false },
    { "id": "deepseek/deepseek-v4-flash", "label": "DeepSeek V4", "free": false }
  ]
}

Model picker (JavaScript)

const { models } = await fetch('https://api.aicodesit.com/pipeline/models', {
  headers: { Authorization: 'Bearer ' + KEY },
}).then(r => r.json());

// render a <select> and send the chosen id with the run:
await fetch(`${API}/pipeline/${projectId}/run`, {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    userMessage: msg,
    conversationHistory: [{ role: 'user', content: msg }],
    model: select.value || undefined,   // omit for the default model
  }),
});

7. List starter templates

GET /projects/templates

Returns the platform's starter templates. Pass an id as template_repo when creating a project — the project starts as a complete working site built from the template, no first prompt required. Call GET /projects/:id/preview right after creation to show it live.

Response 200

{
  "templates": [
    { "id": "starter-template", "label": "Starter Template", "description": "Simple starter template" },
    { "id": "template-2",       "label": "Template 2",       "description": "Modern landing page template" },
    { "id": "react-starter",    "label": "React Starter",    "description": "Vite + React + Tailwind starter" },
    { "id": "nextjs-starter",   "label": "Nextjs Starter",   "description": "Next.js full-stack starter" }
  ]
}

Create a project from a template (JavaScript)

const { templates } = await fetch(API + '/projects/templates', { headers }).then(r => r.json());

// let the visitor pick, then:
const project = await fetch(API + '/projects', {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'my-app-123456',
    subdomain: 'my-app-123456',
    template_repo: picked.id,      // e.g. "react-starter"
  }),
}).then(r => r.json());

// the template is already a working site — show it immediately:
const previewUrl = await waitForPreview(project.id);

The list is fully dynamic — templates added to the platform appear here automatically.

Key management

These endpoints require a regular user session token (not a builder key) — they are for dashboard use, not embedded in a public page.

MethodPathDescription
GET/builder-keysList your active keys
POST/builder-keysCreate a new key
DELETE/builder-keys/:idRevoke a key

Create a key

POST /builder-keys
Authorization: Bearer <supabase_session_token>
Content-Type: application/json

{ "name": "My builder" }

The response includes the full key string exactly once — store it securely. It is never returned again.

{
  "key":        "wlk_4c10b5aba81f868a64949b3a894cbbe1726324be",
  "id":         "...",
  "name":       "My builder",
  "key_prefix": "wlk_4c10b5ab",
  "created_at": "2026-07-10T..."
}

Error responses

StatusMeaning
401Invalid or revoked builder key
403Endpoint not available to builder keys, or project belongs to a different account
404Project or run not found
400Missing required fields (e.g. conversationHistory omitted)
402AI credit limit reached for the billing cycle — the key owner must upgrade or top up credits before new runs can start
429Rate limit reached — slow down requests

Limits

  • 10 active keys per account — revoke old ones to create new ones.
  • Projects and AI credits run on the key owner's account — bill your customers separately if needed.
  • Each build run consumes your plan's AI credit allowance.
  • Concurrent builds share your plan's limits.

Full working example

A complete single-file AI website builder in plain JavaScript — no dependencies, no build step, no server. Paste your key, host the file anywhere.

<!DOCTYPE html>
<html>
<head>
  <title>My AI Builder</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<script>
// ─── CONFIG ──────────────────────────────────────────
var KEY     = 'wlk_your_key_here';
var API     = 'https://api.aicodesit.com';
var history = [];       // conversation history
var projectId = localStorage.getItem('projectId');

// ─── HELPERS ─────────────────────────────────────────
var call = (path, opts) => fetch(API + path, {
  ...opts,
  headers: { Authorization: 'Bearer ' + KEY, ...(opts?.headers || {}) }
});

// ─── STEP 1: ensure we have a project ────────────────
async function ensureProject() {
  if (projectId) return;
  var sub = 'builder-' + Math.random().toString(36).slice(2, 8);
  var res = await call('/projects', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: sub, subdomain: sub }),
  }).then(r => r.json());
  projectId = res.id;
  localStorage.setItem('projectId', projectId);
}

// ─── STEP 2 + 3: send a message and stream ───────────
async function send(msg) {
  await ensureProject();
  history = [...history.slice(-7), { role: 'user', content: msg }];

  // Start run
  var { runId } = await call(`/pipeline/${projectId}/run`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ userMessage: msg, conversationHistory: history }),
  }).then(r => r.json());

  // Stream events
  var stream = await call(`/pipeline/${projectId}/run/${runId}/stream`);
  var reader  = stream.body.getReader();
  var decoder = new TextDecoder();
  var buf = '', aiText = '';

  outer: while (true) {
    var { done, value } = await reader.read();
    if (done) break;
    buf += decoder.decode(value, { stream: true });
    var lines = buf.split('\n'); buf = lines.pop() || '';

    for (var line of lines) {
      if (!line.startsWith('data: ')) continue;
      var evt = JSON.parse(line.slice(6));
      if (evt.event === 'complete') { reader.cancel(); break outer; }
      if (evt.event === 'chunk')    aiText += evt.data || '';
    }
  }

  history.push({ role: 'assistant', content: aiText });

  // Step 4: wait for preview
  while (true) {
    var { status, previewUrl } = await call(`/projects/${projectId}/preview`).then(r => r.json());
    if (status === 'ready') { document.querySelector('iframe').src = previewUrl; break; }
    if (status === 'error') break;
    await new Promise(r => setTimeout(r, 2500));
  }
}

// ─── MINIMAL UI ──────────────────────────────────────
document.write(`
  <style>
    body { margin:0; font-family:sans-serif; display:flex; flex-direction:column; height:100vh }
    textarea { flex:none; padding:10px; border:1px solid #ddd; border-top:none;
               resize:none; font:14px sans-serif; outline:none }
    button { padding:8px 18px; background:#000; color:#fff; border:none;
             font-size:14px; cursor:pointer }
    iframe { flex:1; border:none }
    .bar { display:flex; gap:6px; padding:8px; border-bottom:1px solid #eee }
  </style>
  <div class="bar">
    <textarea id="q" rows="2" style="flex:1" placeholder="Describe a website..."></textarea>
    <button onclick="send(document.getElementById('q').value)">Build</button>
  </div>
  <iframe id="p"></iframe>
`);
</script>
</body>
</html>

The quickest way to ship without writing any UI is to download a pre-configured index.html from the dashboard — Dashboard → Builder API → Create key → Download index.html. It includes a full chat panel, live preview, aurora build animation, device-frame switching, and your brand and key already baked in. Host it on GitHub Pages, Netlify, Cloudflare Pages, or just email the file to a partner — no server required.


Related: Edge Functions · Getting Started · How to automate your workflow with Pipeline Builder