Para sitios y cuentas a los que estés autorizado a acceder.
Cualquier sitio. Detrás de cualquier login. Invocable.
La mayor parte de la web no tiene API — y lo que le importa a tu empresa no tiene API ni acceso libre. Graba la tarea una vez. Writ te devuelve un endpoint.
Mira a Writ grabar un workflow — y luego toma el control.
Inicio de sesión, 2FA, extracción, descarga — en un portal de demo. Haz clic en cualquier punto de la página para tomar el control.
Acabas de hacer un sitio invocable. Ahora hazlo con el tuyo.
- 9 acciones grabadas
- 4 pasos tras la optimización
- 1 endpoint invocable
El workflow de esta demo no se guarda: vive en esta página. Sin tarjeta.
Nuevo workflow
Configura qué se graba
Tipo de ejecuciónEditarEjecútalo, obtén un resultado y para. Ideal para una extracción, un envío de formulario o una recogida de datos — que es lo que necesitan la mayoría de los workflows.
URL de entradaLa página donde empezará la grabación.
Ejecutar enElige dónde se ejecuta el navegador. Los agentes locales usan el navegador y la red de tu máquina.
Acceso al portal
Área de cliente · facturación
Verificación en dos pasos
Introduce el código de 6 dígitos de tu aplicación
Facturas
Área de cliente · Acme Supply
/ INV-2291
INV-2291
Vence el 12 jul 2026 · Vencida
Pagos
Liquidaciones de los últimos 12 meses
Ajustes
Preferencias de facturación
Las peticiones aparecen mientras navegas.
Cambios propuestos (3) — revísalos antes de aplicar
El formulario hace POST a /api/client/session — una sola llamada autentica, sin conducir el DOM.
La página lee /api/client/invoices; llamar al JSON es más rápido y no se rompe si cambia el diseño.
La llamada a la API no necesita la página intermedia.
Este login usa 2FA. Una persona inicia sesión e introduce los códigos automáticamente en cada ejecución.
Pide a la IA lo que quieras — extraer datos, encontrar un elemento, crear un extractor. Ella conduce el navegador y añade el paso por ti.
Para grabar tu sitio, necesitas Writ.
Esta demo reproduce una sesión ya grabada. Para grabar tu propio sitio — incluso detrás de un login — abre un navegador Writ real.
Ejecuciones ilimitadas en tu máquina · sin tarjeta
Ningún tipo de paso coincide.
Endpoint
POST https://api.usewrit.app/api/v1/workflows/353/runs curl -X POST "https://api.usewrit.app/api/v1/workflows/353/runs" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
# → 200 {"success": true, "data": {...}} — bloquea hasta 120 s esperando el resultado.
# Añade ?wait=false para {"task_id": ...} de inmediato, y luego GET a la misma URL + /{task_id}. Ediciones rápidas — reordenar, renombrar o eliminar. Para todo lo visual, edita en el grabador.
Ejecutar en
Este workflow inicia sesión / usa credenciales, así que en Writ Cloud se ejecuta AISLADO — un proceso de navegador nuevo en sandbox, destruido tras cada ejecución. Aislamiento reforzado; un pequeño suplemento. (Las ejecuciones en tu propio agente no se ven afectadas.)
Ejecútalo una vez para confirmar que todo funciona.
Lanzar una pruebaEmpieza por lo que necesitas
Empieza en una línea.
Elige qué quieres empezar — grabar y llamar, vigilar una página, o rastrear un sitio — y luego elige tu lenguaje. Cada uno cabe en una sola llamada, por la misma puerta: HTTP simple, una línea para tu asistente, o un SDK publicado.
Una sola llamada convierte un sitio en API. Writ revisa primero tus propios workflows y las opciones ya hechas — ambos gratis — y luego su agente conduce un navegador real y guarda el workflow. Consulta el id del build; lo que obtienes tiene su propio endpoint.
# One call. Writ's agent drives the browser and saves the workflow.
curl -X POST https://api.usewrit.app/api/v1/website-to-api \
-H "Authorization: Bearer $WRIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://acme.example",
"goal": "return a SKU'"'"'s price and stock"}' { "build_id": 2291,
"status": "queued",
"goal": "return a SKU's price and stock" }El slug existe porque publicaste ese workflow, y la clave es una clave de consumidor creada con él — no la clave de tu cuenta.
Una línea y el sitio se vuelve una API: di qué debe devolver y Writ abre un navegador real, descubre las llamadas detrás de la página y guarda el resultado como workflow.
claude mcp add writ-cloud \
-e WRIT_API_KEY=wt_your_api_key \
-- npx -y writ-mcp
# then, one line in the session:
writ_website_to_api({
url: "https://acme.example",
goal: "return a SKU's price and stock",
}) Clientes con archivo de config — Claude Desktop · Cursor · Windsurf
El workflow guardado se convierte en su propia herramienta run_<name>, se repite sin coste de IA y puede programarse. ¿Prefieres REST? La pestaña cURL muestra el mismo inicio: POST /api/v1/website-to-api.
npm install github:usewrit/writ-sdks --workspace typescript
import { WritAgent, runRowId } from "@usewrit/agent-sdk";
const client = new WritAgent(); // discovers the running agent + token
const { data: workflows } = await client.workflows.list();
const run = await client.workflows.runAndWait(workflows[0].id, {
inputs: { city: "Paris" },
});
const { data: rows } = await client.runs.data(runRowId(run));
console.log(run.status, rows); Estos conducen el daemon LOCAL en tu máquina, donde las ejecuciones son gratuitas y no medidas. La pestaña cURL de arriba es el endpoint cloud publicado.
pip install "git+https://github.com/usewrit/writ-sdks#subdirectory=python"
from writ_agent import WritAgent, run_row_id
with WritAgent() as client: # discovers the local daemon
run = client.workflows.run_and_wait(3, inputs={"city": "Paris"})
print(run["status"], run["rows_extracted"])
print(client.runs.data(run_row_id(run))["data"]) # extracted rows Estos conducen el daemon LOCAL en tu máquina, donde las ejecuciones son gratuitas y no medidas. La pestaña cURL de arriba es el endpoint cloud publicado.
go get github.com/usewrit/writ-sdks/go
client, err := writ.Discover(ctx) // find the running agent
page, _ := client.Workflows.List(ctx, nil)
item, _ := client.Workflows.RunAndWait(ctx, page.Data[0].ID, nil)
rowID, _ := item.RowID()
csv, _ := client.Runs.DataCSV(ctx, rowID) // extracted rows as CSV
fmt.Println(item.Status, "
", csv) Estos conducen el daemon LOCAL en tu máquina, donde las ejecuciones son gratuitas y no medidas. La pestaña cURL de arriba es el endpoint cloud publicado.
cargo add writ-client --git https://github.com/usewrit/writ-sdks
use writ_client::{RunOptions, WritAgent};
let agent = WritAgent::discover().await?; // find the running daemon
let workflows = agent.workflows().list().await?;
let wf = &workflows.data[0];
let outcome = agent.workflows().run_and_wait(wf.id, &RunOptions::default()).await?;
let rows = agent.runs().data(outcome.run.row_id().unwrap()).await?;
println!("{} → {}: {}", wf.name, outcome.run.status, rows.data); Estos conducen el daemon LOCAL en tu máquina, donde las ejecuciones son gratuitas y no medidas. La pestaña cURL de arriba es el endpoint cloud publicado.
Un monitor es un solo POST con una clave. Sin instalación, sin agente que arrancar — Writ revisa la página a tu cadencia y registra cada cambio.
# Watch a page on Writ Cloud — no install, just the key.
curl -X POST https://api.usewrit.app/api/targets \
-H "Authorization: Bearer $WRIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com",
"check_type": "content",
"selector": "h1",
"check_period_ms": 300000}' Un intervalo por debajo del mínimo de tu plan se rechaza sin más, nombrando el límite — nunca se ralentiza en silencio.
Apunta tu asistente a Writ y podrá crear y cablear monitores por su cuenta — vigilar una página y ejecutar algo cuando cambie.
claude mcp add writ-cloud \
-e WRIT_API_KEY=wt_your_api_key \
-- npx -y writ-mcp
# then, one line in the session:
writ_create_monitor({ url: "https://example.com",
selector: "h1", interval_minutes: 5 })
writ_wire_monitor({ monitor_id: 47, action: "notify",
channels: ["email"] }) Clientes con archivo de config — Claude Desktop · Cursor · Windsurf
Los mismos monitores aparecen en la app, la API y los SDK; cambia dónde corre, no el monitor.
npm install github:usewrit/writ-sdks --workspace typescript
import { CloudApi } from "@usewrit/agent-sdk";
const cloud = new CloudApi({ apiKey: process.env.WRIT_API_KEY }); // wt_…
const mon = await cloud.monitors.create({
url: "https://example.com",
selector: "h1",
check_period_ms: 300_000,
});
const changes = await cloud.monitors.changes(mon.id, { limit: 50 }); pip install "git+https://github.com/usewrit/writ-sdks#subdirectory=python"
from writ_agent import Cloud
cloud = Cloud(api_key=os.environ["WRIT_API_KEY"]) # wt_… — no daemon needed
mon = cloud.monitors.create({
"url": "https://example.com",
"selector": "h1",
"check_period_ms": 300_000,
})
changes = cloud.monitors.changes(mon["id"], limit=50) go get github.com/usewrit/writ-sdks/go
client := writ.New(writ.WithAPIKey(os.Getenv("WRIT_API_KEY")))
mon, err := client.Cloud.Monitors.Create(ctx, writ.CloudMonitorParams{
URL: "https://example.com",
Selector: writ.Ptr("h1"),
CheckPeriodMs: writ.Ptr(int64(300_000)),
})
changes, _ := client.Cloud.Monitors.Changes(ctx, mon.ID, writ.Ptr(50)) cargo add writ-client --git https://github.com/usewrit/writ-sdks
use serde_json::json;
use writ_client::CloudClient;
let cloud = CloudClient::from_env()?; // reads WRIT_API_KEY
let mon = cloud.monitors().create(json!({
"url": "https://example.com",
"selector": "h1",
"check_period_ms": 300_000
})).await?;
let changes = cloud.monitors().changes(mon.id, Some(50)).await?; Un rastreo de sitio completo es un solo POST con una clave. Writ reparte la semilla por la flota y entrega el resultado como un dataset invocable.
# No account, no key — a few same-domain pages, one level deep.
curl -X POST https://api.usewrit.app/v1/keyless/crawl \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "limit": 3}'
# With a key: the whole site, as a job you poll.
curl -X POST https://api.usewrit.app/api/crawl \
-H "Authorization: Bearer $WRIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "max_depth": 3, "page_budget": 500}'
curl https://api.usewrit.app/api/crawl/8125 -H "Authorization: Bearer $WRIT_API_KEY" Sin cuenta para probarlo: el nivel sin clave rastrea unas pocas páginas del mismo dominio, un nivel de profundidad, con una asignación diaria. El alcance completo, los logins y un dataset invocable necesitan clave.
Apunta tu asistente a Writ y podrá rastrear un sitio directamente y luego leer las filas sin que escribas un parser.
claude mcp add writ-cloud \
-e WRIT_API_KEY=wt_your_api_key \
-- npx -y writ-mcp
# then, one line in the session:
writ_crawl_site({ url: "https://example.com",
intent: "product pages with specs",
page_budget: 500, save_as: "example-catalog" })
writ_crawl_status({ crawl_id: 8125 }) Clientes con archivo de config — Claude Desktop · Cursor · Windsurf
Con save_as el rastreo queda re-ejecutable e invocable: las siguientes ejecuciones reutilizan datos recientes en vez de volver a rastrear.
npm install github:usewrit/writ-sdks --workspace typescript
import { CloudApi } from "@usewrit/agent-sdk";
const cloud = new CloudApi({ apiKey: process.env.WRIT_API_KEY });
const job = await cloud.crawl({ url: "https://example.com", max_depth: 3, page_budget: 500 });
const status = await cloud.crawlStatus(job.id);
console.log(status.pages_done, "/", status.pages_discovered); pip install "git+https://github.com/usewrit/writ-sdks#subdirectory=python"
from writ_agent import Cloud
cloud = Cloud(api_key=os.environ["WRIT_API_KEY"])
job = cloud.crawl("https://example.com", max_depth=3, page_budget=500)
status = cloud.crawl_status(job["id"])
print(status["pages_done"], "/", status["pages_discovered"]) go get github.com/usewrit/writ-sdks/go
client := writ.New(writ.WithAPIKey(os.Getenv("WRIT_API_KEY")))
job, err := client.Cloud.Crawl(ctx, writ.CrawlStartParams{
URL: "https://example.com",
MaxDepth: writ.Ptr(int64(3)),
PageBudget: writ.Ptr(int64(500)),
})
status, _ := client.Cloud.CrawlStatus(ctx, job.ID) cargo add writ-client --git https://github.com/usewrit/writ-sdks
use writ_client::{CloudClient, CrawlStartParams};
let cloud = CloudClient::from_env()?;
let job = cloud.crawl(&CrawlStartParams {
url: "https://example.com".into(),
max_depth: Some(3),
page_budget: Some(500),
..Default::default()
}).await?;
let status = cloud.crawl_status(job.id).await?; Inicia sesión como tú — 2FA incluida.
Una persona guarda las credenciales, la huella, la ruta de salida y una sesión que sobrevive entre ejecuciones. Usa las personas solo con sitios y cuentas a los que estés autorizado a acceder.
hunter2-prod-9f {{secret:password}} sustituido en la ejecución, nunca en una transcripción sid=8f3a…c21 cookie: [oculto] ocultado en cada cabecera capturada Guardado cifrado · resuelto al ejecutar · nunca devuelto en claro.
Una fila. Cinco puertas.
En cuanto se guarda ya es un endpoint REST, una herramienta MCP, un endpoint compatible con OpenAI, un webhook firmado y una tarea programada.
curl -X POST "https://api.usewrit.app/api/v1/workflows/353/runs" \
-H "Authorization: Bearer wt_…" \
-H "Content-Type: application/json" -d '{}'{
"mcpServers": {
"writ-cloud": {
"type": "http",
"url": "https://api.usewrit.app/mcp"
}
}
}POST https://api.usewrit.app/hooks/{path}
X-Writ-Signature: sha256=…0 7 * * 1-5 → workflow 353# chat with a live streaming session —
# your handler script answers, not a model
base_url = "https://api.usewrit.app/v1"
model = "writ/acme-support-chat" La misma fila, cinco entradas. La interfaz es la misma; su URL depende de dónde corre el workflow — en local, vía Uplink, auto-alojado o en Writ Cloud. Publicar expone el workflow; las Automations deciden cuándo y por qué corre.
Dos máquinas. Cada una alcanza lo que la otra no puede.
Tu máquina ya está dentro de tu red. La nuestra está siempre activa. Enlázalas y la nube se convierte en la puerta de ambas.
Lo que esto exigió de tu cortafuegos: ninguna regla entrante · ningún hostname público · ningún puerto abierto
Nada marca hacia dentro. El agente mantiene una sola conexión de salida y la llamada vuelve por ella. No hay regla de entrada que escribir ni puerto que abrir.
Tu propia máquina — gratis, sin cuenta, corre mientras esté encendida; solo sale el resultado.
El agente sale hacia fuera. Nada entra — un sistema detrás de tu VPN se vuelve invocable sin abrir un solo puerto entrante. Las llamadas locales pueden quedarse totalmente locales; añade Uplink solo cuando un llamante remoto necesite alcanzar un workflow tras tu cortafuegos.
Nuestra build de código abierto no puede facturarte — el código de facturación no está compilado en ella.
Construido con IA. Ejecutado sin ella.
La construcción es donde va la inteligencia, y cuesta lo que cuesta — una vez. Después no hay modelo en el bucle.
- un paso falla: ningún selector válido
- el paso fallido y el DOM en vivo se envían
- el candidato se valida contra la página real — o se rechaza
- la ejecución termina
La auto-reparación es opcional, desactivada por defecto y propia de la nube — activarla fija ese workflow en la nube.
Un cambio es un disparador, no solo una alerta.
Apunta un monitor a un valor. Cuando se mueve, eso es un evento — y el evento ejecuta un workflow.
La reacción parte de la sesión ya abierta de la persona — sin inicio en frío. Si la acción falla, Writ registra el run y aplica la política de reintentos que configuraste.
Un sitio entero, como conjunto de datos.
Describe lo que quieres en lenguaje natural. Writ lo compila en un alcance, lo recorre y te devuelve un conjunto de datos que es invocable.
Sin sesión la frontera termina en /login. Todo lo que hay más allá es indescubrible — no lento de alcanzar, indescubrible: esas URL no están en ningún sitemap y nada del sitio público enlaza a ellas.
Topología ilustrativa. Un Harvest real corre dentro del alcance que fijas — inclusiones, exclusiones y topes de ritmo — y respeta robots.txt.
Lee el código, y luego lee los límites.
Todo lo anterior es una afirmación hasta que puedas comprobarlo. Así que aquí está el código que lo respalda, las garantías que se cumplen por construcción, y lo que Writ no hace.
El motor que ejecuta tus workflows es público. Puedes leerlo, ejecutarlo y comprobar que hace lo que dice esta página.
También público: changelog · estado · docs · centro de confianza
No son promesas, sino consecuencias de cómo está construido. Cada una nombra su mecanismo.
- Una ejecución en tu propia máquina no puede facturarse: el código de facturación no está compilado en la versión de código abierto.
- Un sistema de intranet no necesita ningún puerto de entrada: el agente mantiene una conexión de salida y solo vuelve el resultado del workflow.
- Un workflow grabado se reproduce sin modelo: los pasos ya están decididos, así que un replay no gasta ningún token de IA.
Los límites, dichos con claridad. Si alguno es tu caso, lo sabrás antes de registrarte y no después.
- No vence controles de acceso. Inicia sesión como tú, con tus credenciales, en sitios que estás autorizado a usar.
- No es un índice general de la web. Tú lo apuntas a los sitios que eliges; nada se recoge en segundo plano.
- La nube gestionada corre hoy en una sola región: OVHcloud en Canadá. Nombraremos las demás cuando existan.
Un fondo. La mezcla que quieras.
Las ejecuciones en la nube se miden por tiempo y gastan un único fondo de créditos — cómputo, salida premium o IA, en la mezcla que elijas.
Las ejecuciones en tu propia máquina son gratis y no se miden, en todos los planes. Cuando el fondo se agota, las ejecuciones cloud se pausan hasta recargar — lo local nunca se detiene. Precios en USD, facturados mensualmente. Ejemplo: un mismo fondo puede gastarse en tiempo de navegador, salida premium o reparación IA opcional — las ejecuciones locales no consumen ningún crédito.
Las preguntas que de verdad nos hacen
¿Es realmente gratis?
¿En qué se diferencia esto de una integración web normal?
¿Mis datos salen de mi ordenador?
¿Puedo usar mis propias claves de IA?
¿Qué pasa cuando un sitio cambia?
¿Está permitido esto?
¿Dónde viven mis credenciales?
¿Puedo llevarme mis workflows a otro sitio?
¿Writ elude la 2FA?
¿Qué pasa cuando mi fondo de créditos se agota?
¿Qué recibe exactamente Writ Cloud?
¿Puedo borrar mis credenciales y sesiones guardadas?
Convierte tu primer sitio en un endpoint.
Gratis para empezar. Ilimitado en tu máquina, para siempre.