---
title: "Exécuter une commande dans l’espace de travail"
description: "Exécute une commande shell sur une copie de travail du brouillon du site, dans son propre conteneur."
canonical: "https://atelier201.com/docs/fr/api/workspace/run"
updated: "2026-11-06"
---

# Exécuter une commande dans l’espace de travail

Nécessite `sites:write`. Ne coûte aucun crédit. Le chemin se termine par `/workspace:run`.

L’espace de travail est un shell exécuté hors ligne dans le conteneur propre au site, sur une copie de travail de son brouillon. Utilisez-le pour les tâches adaptées au shell : `rg`, `grep`, `find`, `cat`, `sed -i`, `node` et `npx astro build`, pour tester une compilation en quelques secondes. La commande s’exécute à la racine du projet avec un compte sans privilèges, sans accès au réseau.

Les modifications apportées par la commande ne sont pas validées. La réponse les répertorie dans `uncommitted`, à raison d’une par ligne, au format de `git status` (`M src/pages/index.astro`). Rien n’est ajouté à l’historique tant que vous n’avez pas [validé l’espace de travail](/docs/api/workspace/commit), et les visiteurs ne voient rien tant que vous n’avez pas publié.

`command` peut contenir jusqu’à 8000 caractères. `timeout_ms` doit être compris entre 1000 et 300000 et vaut 60000 par défaut : une commande toujours en cours à l’issue de ce délai est arrêtée et `timed_out` vaut `true`. L’échec d’une commande ne constitue pas une erreur d’API : l’appel réussit et `exit_code` est différent de 0. `output` regroupe stdout et stderr ; au-delà de 8 KB, il conserve le début et la fin, et `truncated` vaut `true`.

L’espace de travail suit l’évolution du brouillon. Si une autre modification a fait évoluer le brouillon depuis votre dernière commande, vos modifications non validées sont conservées et `note` le signale. Il en va de même si l’espace de travail a dû être recréé.

Un site dont la création est toujours en cours renvoie `result_not_ready`. Un site suspendu ou en cours de suppression renvoie `conflict`.

```http
POST https://api.atelier201.com/v1/sites/{site_id}/workspace:run
```

## Authorizations

- `Authorization` (bearer, in header, required)

## Path parameters

- `site_id` (`string`, required): L’identifiant du site ou son slug (l’adresse avant .atelier201.page).

## Body

`application/json`, required

- `command` (`string`, required, length: `1–8000 chars`): Une commande bash exécutée à la racine du projet, sur une copie de travail du brouillon : rg, grep, sed, find, cat, node... Aucun accès réseau. Les fichiers modifiés restent non validés jusqu’à `workspace:commit`, qui les compile et signale les erreurs éventuelles. La compilation du projet est refusée ici : elle a pris 30 s et ferait doublon.
- `timeout_ms` (`integer`, range: `1000–300000`): Valeur par défaut : 60000. La commande est interrompue au-delà de cette durée.

## Response

**200**: Exécuter une commande shell dans l’espace de travail du site

- `data` (`object`, required)
- `data.revision` (`string`, required, length: `40–40 chars`): La révision du brouillon à partir de laquelle l’espace de travail a été créé.
- `data.exit_code` (`integer`, required, range: `-9007199254740991–9007199254740991`)
- `data.timed_out` (`boolean`, required)
- `data.output` (`string`, required): stdout et stderr réunis ; au-delà de 8 KB, le début et la fin.
- `data.truncated` (`boolean`, required)
- `data.uncommitted` (`string[]`, required): Les changements non validés de l’espace de travail après la commande, au format de `git status` ("M src/pages/index.astro").
- `data.note` (`string,null`, required): Indique que l’espace de travail a été recréé ou basculé vers un brouillon plus récent avant l’exécution de la commande.
- `request_id` (`string`, required)

```json
{
  "data": {
    "revision": "<string>",
    "exit_code": 123,
    "timed_out": true,
    "output": "<string>",
    "truncated": true,
    "uncommitted": [
      "<string>"
    ],
    "note": null
  },
  "request_id": "<string>"
}
```

**400**: Codes possibles : invalid_request, unknown_field, invalid_parameter, invalid_cursor

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**401**: Codes possibles : authentication_required, invalid_api_key, api_key_expired, api_key_revoked

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**402**: Codes possibles : insufficient_credits

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**403**: Codes possibles : insufficient_scope, feature_not_available, admin_required

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**404**: Codes possibles : resource_not_found

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**409**: Codes possibles : conflict, result_not_ready, idempotency_key_reused

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**410**: Codes possibles : result_expired

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**413**: Codes possibles : request_too_large

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**422**: Codes possibles : request_too_large_for_plan

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**429**: Codes possibles : rate_limited

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**500**: Codes possibles : internal_error

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**503**: Codes possibles : service_unavailable

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**Example request**

```bash
curl --request POST \
  --url 'https://api.atelier201.com/v1/sites/<site_id>/workspace:run' \
  --header 'Authorization: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
  "command": "<string>"
}'
```
