Pour des sites et des comptes auxquels vous êtes autorisé à accéder.
N’importe quel site. Derrière n’importe quel login. Appelable.
La majeure partie du web n’a pas d’API — et ce qui compte pour votre entreprise n’a ni API ni accès libre. Enregistrez la tâche une fois. Writ vous rend un endpoint.
Regardez Writ enregistrer un workflow — puis prenez la main.
Connexion, 2FA, extraction, téléchargement — sur un portail de démo. Cliquez n’importe où dans la page pour reprendre la main.
Vous venez de rendre un site appelable. Faites-le avec le vôtre.
- 9 actions enregistrées
- 4 étapes après optimisation
- 1 endpoint appelable
Le workflow de cette démo n’est pas enregistré : il vit dans cette page. Sans carte bancaire.
Nouveau workflow
Configurer ce qui doit être enregistré
Type d’exécutionModifierExécutez-le, obtenez un résultat, puis arrêtez. Idéal pour une extraction, un envoi de formulaire ou une récupération de données — c’est ce dont la plupart des workflows ont besoin.
URL d’entréeLa page où l’enregistrement commencera.
Exécuter surChoisissez où le navigateur s’exécute. Les agents locaux utilisent le navigateur et le réseau de votre machine.
Connexion au portail
Espace client · facturation
Vérification en deux étapes
Saisissez le code à 6 chiffres de votre application
Factures
Espace client · Acme Supply
/ INV-2291
INV-2291
Échéance 12 juil. 2026 · En retard
Paiements
Règlements des 12 derniers mois
Paramètres
Préférences de facturation
Les requêtes apparaissent au fil de la navigation.
Modifications proposées (3) — vérifiez avant d’appliquer
Le formulaire poste vers /api/client/session — un seul appel authentifie, sans piloter le DOM.
La page lit /api/client/invoices ; appeler le JSON est plus rapide et ne casse pas si la mise en page change.
L’appel d’API n’a pas besoin de la page intermédiaire.
Cette connexion utilise la 2FA. Une persona se connecte et saisit les codes automatiquement à chaque exécution.
Demandez à l’IA n’importe quoi — extraire des données, trouver un élément, créer un extracteur. Elle pilote le navigateur et ajoute l’étape pour vous.
Pour enregistrer votre site, il faut Writ.
Cette démo rejoue une session déjà enregistrée. Pour enregistrer votre propre site — y compris derrière un login — ouvrez un vrai navigateur Writ.
Exécutions illimitées sur votre machine · sans carte bancaire
Aucun type d’étape ne correspond.
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": {...}} — bloque jusqu’à 120 s pour le résultat.
# Ajoutez ?wait=false pour {"task_id": ...} tout de suite, puis GET la même URL + /{task_id}. Modifications rapides — réordonner, renommer ou supprimer. Pour tout ce qui est visuel, modifiez dans l’enregistreur.
Exécuter sur
Ce workflow se connecte / utilise des identifiants ; sur Writ Cloud, il s’exécute donc en mode ISOLÉ — un nouveau processus de navigateur en sandbox, détruit après chaque exécution. Isolation renforcée ; léger supplément. (Les exécutions sur votre propre agent ne sont pas affectées.)
Exécutez-le une fois pour confirmer que tout fonctionne.
Lancer un testPartez de votre besoin
Démarrez en une ligne.
Choisissez ce que vous voulez démarrer — enregistrer et appeler, surveiller une page, ou crawler un site — puis choisissez votre langage. Chacun tient en un seul appel, par la même porte : du HTTP simple, une ligne pour votre assistant, ou un SDK publié.
Un seul appel transforme un site en API. Writ vérifie d’abord vos propres workflows et les offres prêtes à l’emploi — les deux gratuits — puis son agent pilote un vrai navigateur et enregistre le workflow. Interrogez l’id de build ; le résultat a son propre 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" }Le slug existe parce que vous avez publié ce workflow, et la clé est une clé consommateur créée avec lui — pas la clé de votre compte.
Une ligne, et le site devient une API : dites ce qu’elle doit renvoyer et Writ ouvre un vrai navigateur, retrouve les appels derrière la page et enregistre le résultat comme 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",
}) Clients à fichier de config — Claude Desktop · Cursor · Windsurf
Le workflow sauvegardé devient son propre outil run_<name>, se rejoue sans coût d’IA et peut être planifié. Vous préférez REST ? L’onglet cURL montre le même démarrage : 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); Ceux-ci pilotent le démon LOCAL sur votre machine, où les exécutions sont gratuites et non comptées. L’onglet cURL ci-dessus est l’endpoint cloud publié.
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 Ceux-ci pilotent le démon LOCAL sur votre machine, où les exécutions sont gratuites et non comptées. L’onglet cURL ci-dessus est l’endpoint cloud publié.
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) Ceux-ci pilotent le démon LOCAL sur votre machine, où les exécutions sont gratuites et non comptées. L’onglet cURL ci-dessus est l’endpoint cloud publié.
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); Ceux-ci pilotent le démon LOCAL sur votre machine, où les exécutions sont gratuites et non comptées. L’onglet cURL ci-dessus est l’endpoint cloud publié.
Un moniteur, c’est un seul POST avec une clé. Aucune installation, aucun agent à lancer — Writ vérifie la page à votre cadence et enregistre chaque changement.
# 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 intervalle inférieur au minimum de votre plan est refusé net, en nommant le plancher — il n’est jamais ralenti en silence.
Pointez votre assistant vers Writ et il peut créer et câbler les moniteurs lui-même — surveiller une page, puis déclencher une action quand elle bouge.
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"] }) Clients à fichier de config — Claude Desktop · Cursor · Windsurf
Les mêmes moniteurs apparaissent dans l’app, l’API et les SDK ; le lieu d’exécution change, le moniteur non.
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 crawl de site complet, c’est un seul POST avec une clé. Writ répartit la graine sur la flotte et livre le résultat comme un jeu de données appelable.
# 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" Aucun compte pour essayer : le palier sans clé crawle quelques pages du même domaine, sur un niveau, dans la limite d’une allocation quotidienne. La portée complète, les logins et un jeu de données appelable demandent une clé.
Pointez votre assistant vers Writ et il peut crawler un site directement, puis relire les lignes sans que vous écriviez un parseur.
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 }) Clients à fichier de config — Claude Desktop · Cursor · Windsurf
Avec save_as, le crawl devient réexécutable et appelable : les exécutions suivantes réutilisent les données récentes au lieu de recrawler.
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?; Il se connecte à votre place — 2FA comprise.
Une persona détient les identifiants, l’empreinte, la route de sortie et une session qui survit d’une exécution à l’autre. N’utilisez les personas qu’avec des sites et des comptes auxquels vous êtes autorisé à accéder.
hunter2-prod-9f {{secret:password}} substitué à l’exécution, jamais dans une transcription sid=8f3a…c21 cookie : [masqué] masqué dans chaque en-tête capturé Stocké chiffré · résolu à l’exécution · jamais renvoyé en clair.
Une ligne. Cinq portes.
Dès l’enregistrement, c’est déjà un endpoint REST, un outil MCP, un endpoint compatible OpenAI, un webhook signé et une tâche planifiée.
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 même ligne, cinq entrées. L’interface reste la même ; son URL dépend d’où s’exécute le workflow — en local, via Uplink, auto-hébergé ou dans Writ Cloud. Publier expose le workflow ; les Automations décident quand et pourquoi il s’exécute.
Deux machines. Chacune atteint ce que l’autre ne peut pas.
Votre machine est déjà dans votre réseau. La nôtre est toujours active. Liez-les et le cloud devient la porte d’entrée des deux.
Ce que cela a exigé de votre pare-feu : aucune règle entrante · aucun nom d’hôte public · aucun port ouvert
Rien n’appelle vers l’intérieur. L’agent maintient une seule connexion sortante, et l’appel redescend par celle-ci. Aucune règle entrante à écrire, aucun port à ouvrir.
Votre propre machine — gratuit, sans compte, tourne tant qu’elle est allumée ; seul le résultat sort.
L’agent appelle vers l’extérieur. Rien n’entre — un système derrière votre VPN devient appelable sans ouvrir un seul port entrant. Les appels locaux peuvent rester entièrement locaux ; ajoutez Uplink seulement quand un appelant distant doit atteindre un workflow derrière votre pare-feu.
Notre build open source ne peut pas vous facturer — le code de facturation n’y est pas compilé.
Construit avec l’IA. Exécuté sans elle.
La construction est l’endroit où va l’intelligence, et elle coûte ce qu’elle coûte — une fois. Ensuite, plus aucun modèle dans la boucle.
- une étape échoue : aucun sélecteur valide
- l’étape en échec et le DOM en direct sont envoyés
- le candidat est validé sur la page réelle — ou rejeté
- l’exécution se termine
L’auto-réparation est optionnelle, désactivée par défaut, et propre au cloud — l’activer fixe ce workflow sur le cloud.
Un changement est un déclencheur, pas seulement une alerte.
Pointez un moniteur sur une valeur. Quand elle bouge, c’est un événement — et l’événement exécute un workflow.
La réaction part de la session déjà ouverte de la persona — pas de reconnexion à froid. Si l’action échoue, Writ journalise le run et applique la politique de reprise que vous avez configurée.
Un site entier, en jeu de données.
Décrivez ce que vous voulez en langage courant. Writ le compile en périmètre, explore, et vous rend un jeu de données lui-même appelable.
Sans session, la frontière s’arrête à /login. Tout ce qui est au-delà est indécouvrable — pas lent à atteindre, indécouvrable : ces URL ne figurent dans aucun sitemap et rien du site public n’y renvoie.
Topologie illustrative. Un vrai Harvest s’exécute dans le périmètre que vous fixez — inclusions, exclusions et plafonds de débit — et respecte robots.txt.
Lisez le code, puis lisez les limites.
Tout ce qui précède reste une affirmation tant que vous ne pouvez pas le vérifier. Voici donc le code qui la soutient, les garanties qui tiennent par construction, et ce que Writ ne fait pas.
Le moteur qui exécute vos workflows est public. Vous pouvez le lire, l’exécuter, et vérifier qu’il fait ce que cette page annonce.
Aussi public : changelog · statut · docs · centre de confiance
Pas des promesses — des conséquences de la façon dont c’est construit. Chacune nomme son mécanisme.
- Une exécution sur votre machine ne peut pas être facturée : le code de facturation n’est pas compilé dans la version open source.
- Un système intranet n’a besoin d’aucun port entrant : l’agent maintient une connexion sortante, et seul le résultat du workflow revient.
- Un workflow enregistré rejoue sans modèle : les étapes sont déjà décidées, donc un replay ne consomme aucun token d’IA.
Les limites, dites simplement. Si l’une d’elles est votre cas, vous le saurez avant de vous inscrire, pas après.
- Il ne défait aucun contrôle d’accès. Il se connecte en tant que vous, avec vos identifiants, sur des sites que vous êtes autorisé à utiliser.
- Ce n’est pas un index du web. Vous le pointez vers les sites que vous choisissez ; rien n’est collecté en arrière-plan.
- Le cloud managé tourne aujourd’hui dans une seule région — OVHcloud au Canada. Nous nommerons les autres quand elles existeront.
Un pool. Le mélange que vous voulez.
Les exécutions cloud sont facturées au temps d’exécution et puisent dans un seul pool de crédits — calcul, sortie premium ou IA, dans le mélange de votre choix.
Les exécutions sur votre machine sont gratuites et non comptées, sur tous les forfaits. Quand le pool est épuisé, les exécutions cloud se mettent en pause jusqu’à la recharge — le local ne s’arrête jamais. Prix en USD, facturés mensuellement. Exemple : un même pool peut se dépenser en temps de navigateur, en sortie premium ou en réparation IA optionnelle — les exécutions locales ne consomment aucun crédit.
Les questions qu’on nous pose vraiment
Est-ce vraiment gratuit ?
En quoi est-ce différent d’une intégration web classique ?
Mes données quittent-elles mon ordinateur ?
Puis-je utiliser mes propres clés IA ?
Que se passe-t-il quand un site change ?
Est-ce autorisé ?
Où vivent mes identifiants ?
Puis-je emporter mes workflows ailleurs ?
Writ contourne-t-il la 2FA ?
Que se passe-t-il quand mon pool de crédits est épuisé ?
Que reçoit exactement Writ Cloud ?
Puis-je supprimer mes identifiants et sessions stockés ?
Transformez votre premier site en endpoint.
Gratuit pour commencer. Illimité sur votre machine, pour toujours.