Get started
Guide for agents
Everything a coding agent needs to use pre.dev: interfaces, the API key, plan access, five complete recipes, field names, polling and error rules, and limits.
This page is written for AI agents and the people who set them up. Each recipe runs as written once PREDEV_API_KEY is set.
Interfaces
| Interface | Base URL |
|---|---|
| REST: specifications, browser tasks, and credits | https://api.pre.dev |
| AI Gateway | https://api.pre.dev/v1 |
| Hosted MCP server | https://api.pre.dev/mcp |
Two more ways in: the CLI, predev, runs the coding agent in a local repository, and predev run does one task there without the app, signed in with PREDEV_API_KEY; the docs MCP server, https://docs.pre.dev/mcp, searches and reads this documentation with no key.
| Machine-readable resource | Use it for |
|---|---|
| llms.txt | An index of every page, with agent entry points first |
| llms-full.txt | The whole site as one file; this guide comes first |
Any page URL plus .md | One page as Markdown, for example agents.md |
| REST OpenAPI | Specifications, browser tasks, and credits |
| AI Gateway OpenAPI | Every /v1 operation, with error examples |
MCP tools and /mcp/info | Tool inputs and results; the live list comes from tools/list. The local server, @predotdev/mcp, adds the chrome_* tools |
| skill.md | A short capability summary. Install it with npx skills add https://docs.pre.dev |
Get a key
Copy your pre.dev API key from Integrations → Built-in in the dashboard: pre.dev/projects/integrations for your personal workspace, or the Integrations page of a team workspace. Workspace keys start with pdk_.
| Interface | Send the key as |
|---|---|
| REST and AI Gateway | Authorization: Bearer <key> (recommended) or x-api-key: <key> |
| MCP server | Browser sign-in (OAuth) in interactive clients, or Authorization: Bearer <key>, x-api-key, or predev-api-key |
Projects built on pre.dev already have the key as PREDEV_API_KEY. It spends the workspace’s credits, so keep it on a server.
Plan access
Browser tasks and AI Gateway calls work on every plan, Free included: a Free personal account can spend 2 credits on browser tasks, and a Free workspace 5 credits on AI calls, before it needs a plan. Specifications and the MCP server need Premium, Pro, Team or Enterprise; Plus and team workspaces without a plan get 3 trial specifications. The MCP memory tools work on every plan, Free included, and use no credits. See API and MCP access.
Choose an interface
| Task | REST | MCP |
|---|---|---|
| Run browser tasks | POST /browser-agent | browser_agent |
| Retrieve a browser run | GET /browser-agent/{id} | browser_agent_get |
| Browse browser history | GET /list-browser-agents | browser_agent_list |
| Generate a concise specification | POST /fast-spec | fast_spec |
| Generate a detailed specification | POST /deep-spec | deep_spec |
| Retrieve a specification | GET /spec-status/{specId} | get_spec |
| Read a project’s plan | GET /get-plan | get_plan |
| Browse specification history | GET /list-specs | list_specs |
| Read what the user told pre.dev to remember | Use MCP | memory_list, memory_search |
| Save or remove one of the user’s memories | Use MCP | memory_remember, memory_forget |
| Search specification input | GET /find-specs | Use REST |
| Check available credits | GET /credits-balance | Use REST |
| Call a model | https://api.pre.dev/v1 with an OpenAI or Anthropic SDK | Use REST |
| Change code in a local repository | No endpoint; run the CLI: predev run | Use the CLI |
Both official SDKs are named predev-api: from predev_api import PredevAPI in Python and import { PredevAPI } from 'predev-api' in Node. They cover specifications and browser tasks.
Recipe 1: run a browser task over REST
Submit asynchronously, save the id, and poll until the batch finishes.
ID=$(curl --fail-with-body -s https://api.pre.dev/browser-agent \
-H "Authorization: Bearer $PREDEV_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: heading-example-1" \
-d '{
"async": true,
"tasks": [{
"url": "https://example.com",
"instruction": "Return the page heading",
"output": {
"type": "object",
"properties": { "heading": { "type": "string" } },
"required": ["heading"]
}
}]
}' | jq -r .id)
while :; do
RUN=$(curl --fail-with-body -s "https://api.pre.dev/browser-agent/$ID" \
-H "Authorization: Bearer $PREDEV_API_KEY")
case $(echo "$RUN" | jq -r .status) in completed|failed) break ;; esac
sleep 5
done
echo "$RUN" | jq '.results[] | {status, data, error, creditsUsed}'The batch status is lowercase: processing, completed or failed. Each task has its own uppercase status; read data only when it is SUCCESS, because a completed batch can contain failed tasks. See submit tasks.
Recipe 2: call a model with the OpenAI SDK
// npm install openai
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: 'https://api.pre.dev/v1', apiKey: process.env.PREDEV_API_KEY });
const { data: completion, response } = await client.chat.completions
.create({
model: 'deepseek/deepseek-v4.1-flash-1017',
messages: [{ role: 'user', content: 'Write a one-line welcome message for a todo app.' }],
})
.withResponse();
console.log(completion.choices[0].message.content);
console.log('credits charged:', response.headers.get('x-predev-credits-charged'));# pip install openai
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.pre.dev/v1", api_key=os.environ["PREDEV_API_KEY"])
raw = client.chat.completions.with_raw_response.create(
model="deepseek/deepseek-v4.1-flash-1017",
messages=[{"role": "user", "content": "Write a one-line welcome message for a todo app."}],
)
print(raw.parse().choices[0].message.content)
print("credits charged:", raw.headers.get("x-predev-credits-charged"))Use model ids exactly as GET /v1/models lists them; each row carries its credit prices in a predev object. The same key works with the Anthropic SDK at base URL https://api.pre.dev. See the AI Gateway.
Recipe 3: generate a specification over MCP
Add the pre.dev MCP server with the key in its environment. This works headless, with no browser sign-in, and needs Node.js 22 or later:
claude mcp add --scope user predev -e PREDEV_API_KEY="$PREDEV_API_KEY" -- npx -y @predotdev/mcpThe local server carries every pre.dev tool plus chrome_* tools for the user’s own Chrome. Any MCP client that runs local servers connects the same way: command npx, arguments -y @predotdev/mcp, environment PREDEV_API_KEY. For an interactive install in every agent on a Mac, run npx -y @predotdev/mcp setup with a 10 minute timeout and tell the user what to click.
Without Node.js, add the hosted server with the key in a header:
claude mcp add --transport http predev https://api.pre.dev/mcp \
--header "Authorization: Bearer $PREDEV_API_KEY"Then call fast_spec:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "fast_spec",
"arguments": { "executiveSummary": "A habit tracker with streaks and daily reminders" }
}
}executiveSummary says what to build, in at least 10 characters. Add existingContext (text describing an existing codebase) and docURLs when they help. If the result gives a spec id before the spec is finished, call get_spec with it every few seconds until the status is completed or failed. get_spec and list_specs use no credits. See MCP setup and the tool reference.
Recipe 4: take a payment in an app built on pre.dev
The project’s environment already holds STRIPE_SECRET_KEY (a project-tagged pre.dev key), STRIPE_API_HOST and STRIPE_WEBHOOK_SECRET. Point the Stripe SDK at pre.dev and write ordinary Stripe code in the app’s server:
// npm install stripe express
import express from 'express';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
host: process.env.STRIPE_API_HOST,
protocol: (process.env.STRIPE_API_PROTOCOL as 'https' | 'http') || 'https',
...(process.env.STRIPE_API_PORT ? { port: Number(process.env.STRIPE_API_PORT) } : {}),
});
const app = express();
// The webhook route reads the raw body, so mount it before any JSON parser.
app.post('/api/stripe/webhook', express.raw({ type: 'application/json' }), (req, res) => {
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'] as string, process.env.STRIPE_WEBHOOK_SECRET!);
} catch {
return res.status(400).send('invalid signature');
}
if (event.type === 'checkout.session.completed') {
// mark the order paid
}
res.json({ received: true });
});
app.post('/api/checkout', express.json(), async (req, res) => {
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [{ price: req.body.priceId, quantity: 1 }],
success_url: `${req.headers.origin}/thanks`,
cancel_url: `${req.headers.origin}/cart`,
});
res.json({ url: session.url });
});
app.listen(Number(process.env.PORT) || 3000);Payments run in Stripe test mode while you build; use card 4242 4242 4242 4242. The preview shows the app in a frame, where Checkout will not render, so open url in a new tab when framed. Server routes like these run in the project’s sandbox, including after you publish. See payments and webhooks.
Recipe 5: run the coding agent in a repository
The REST API has no coding-session endpoint. To change code in a local repository, run the CLI without its app:
curl -fsSL https://pre.dev/install | PREDEV_NO_AUTORUN=1 bash
export PREDEV_API_KEY="pdk_..."
cd path/to/repo
~/.predev/bin/predev run "add input validation to the signup form with a test"- Set
PREDEV_API_KEYin the environment, not in a.envfile. Copy the key from Integrations → Built-in in the dashboard. On a machine where someone signed in with the browser, the saved login is used instead; runpredev logoutto use the key. - Read standard output:
[predev]progress lines, then the agent’s final message. Errors are on standard error. - Check the exit code:
0finished,1failed or stopped,2not signed in or key rejected. Do not retry a2with the same key. - If the output ends with a question, answer it with another
predev runin the same directory. - Review the changes with
git statusandgit diff. WithCIset, the checkout stays the source of truth: no files from earlier runs are pulled into it. SetCI=trueyourself on CI services that don’t (Jenkins, Azure Pipelines, AWS CodeBuild). - Run parallel jobs on one checkout path with
predev run --new.
Keep names distinct
| Meaning | REST | MCP | Python SDK |
|---|---|---|---|
| What to specify | input | executiveSummary (at least 10 characters) | input_text |
| Existing codebase context | currentContext | existingContext | current_context |
| Reference documentation | docURLs | docURLs | doc_urls |
| Specification polling ID | specId from submission; _id on retrieval | specId | result["specId"] |
| Browser run ID | id | id | result["id"] |
| Submit browser work asynchronously | async: true | async: true | run_async=True |
Pass existing context as text describing the codebase. It is not an ID that loads another project.
Long-running work
- Save every id as soon as you get it:
idfor browser runs,specIdfor specifications, and the generationid(pdg-…) andx-predev-request-idfor AI calls. - Poll at a bounded interval, such as every 5 seconds, and stop on a terminal status:
completedorfailedfor specifications and browser runs. Do not infer completion from array lengths or thecompletedcount. - A timeout or a dropped stream does not mean the work stopped. Fetch it by id before submitting again, and send one
Idempotency-Keyper logical browser submission; retries within 24 hours return the original run. - Browser runs stream from
GET /browser-agent/{id}/stream; the end of a stream is not a success signal. RequestincludeEvents=trueonly when you need the step timeline, since it can hold large screenshots. - AI Gateway calls stream with
stream: true. Lines that start with:are keep-alives. Streamed responses carry no credits header; read the charge fromGET /v1/generationafterwards.
Errors
REST errors are JSON with an error message and, where one applies, a machine-readable code such as INSUFFICIENT_CREDITS, SUBSCRIPTION_REQUIRED or QUEUE_FULL on browser submissions. Some MCP results are text without isError; confirm a specification’s status with get_spec.
The AI Gateway raises its own errors in the OpenAI error shape, so the OpenAI and Anthropic SDKs raise their usual exceptions:
{
"error": {
"message": "This pre.dev workspace has no credits left for AI calls. Top up at https://pre.dev/billing or enable auto-recharge.",
"type": "insufficient_credits",
"code": "insufficient_credits",
"param": null,
"predev": { "credits_remaining": 0, "estimated_credits": 0.05, "topup_url": "https://pre.dev/billing" }
}
}Branch on error.code: missing_api_key or invalid_api_key (401), insufficient_credits or subscription_required (402, nothing ran), rate_limit_exceeded (429, wait Retry-After seconds), balance_unavailable (503, retry), and upstream_unavailable (502, retry or send models fallbacks). Errors from the model keep their own status and message. See errors and retries.
Limits
| Limit | Value |
|---|---|
| Browser tasks per request | 1,000 |
Browser tasks running at once within a run (concurrency) | 1 to 20, default 5 |
| Browser tasks in flight per account, queued or running | Set by your plan; read cap from GET /browser-agent-status |
| AI Gateway requests per workspace | 600 a minute; 30 a minute on the Free plan. Catalog reads do not count. |
The AI Gateway also refuses more than 30 failed key attempts a minute from one IP address, and accepts request bodies up to 100 MB of JSON or 60 MB for file and audio uploads.
What the API does not do
The public REST API has no general coding-session, deployment, cancellation, webhook-registration, or recurring-schedule endpoint. For coding tasks, use predev run or the Coding Agent, and schedule API calls in your own application when needed. Browser tasks do not expose a reusable login-session or cookie-profile API; for sites behind a login, Browser Agents Local lets a local coding agent use the Chrome the user is already signed in to.