Référence de l’API

Toute l’API REST de Spunto — chaque endpoint, ses corps de requête et ses schémas de réponse.

L’API Spunto est une API REST. Tous les endpoints demandent un token Bearer (sauf les routes publiques d’authentification).

La référence interactive complète de l’API se trouve à :

https://spunto.net/api/docs

Elle est générée automatiquement à partir du spec OpenAPI 3.1 — toujours à jour.

Toutes les requêtes à l’API (sauf /api/auth/*) demandent :

Authorization: Bearer <token>

Deux sortes de tokens sont acceptées :

  • Token de session — émis quand vous vous connectez avec Google. Le parcours d’authentification pose le même token dans un cookie httpOnly session — les requêtes du navigateur l’envoient automatiquement. Accès complet (pas de scopes).
  • Clé d’API (spk_...) — un token à scopes, révocable, généré depuis le dashboard pour un accès sans navigateur (scripts, CI, agents IA). Voir la page Clés d’API pour en créer et en utiliser une.

https://spunto.net

Tous les endpoints commencent par /api/.

PATCH est partiel : le corps d’une requête ne touche que les champs qu’il nomme, et tout ce qu’il omet reste tel quel. Renommer un projet, c’est {"name": "..."} — ses dépôts, ses features et ses extensions restent où ils étaient.

Vider quelque chose doit donc se dire explicitement :

  • une liste se vide en l’envoyant explicitement vide — {"forwardPorts": []}
  • un champ de texte libre se vide en envoyant "" — {"description": ""} enregistre null (des espaces comptent comme vide). Omettre la clé garde l’ancienne valeur ; cela ne veut jamais dire « effacer ».

Les secrets partagés d’un projet passent dans le même corps, et sont partiels de la même façon — une liste de changements, pas l’état final voulu :

PATCH /api/orgs/:orgId/projects/:projectId
{
  "secrets": [
    { "name": "API_TOKEN", "value": "sk-..." },   // write (creates or replaces, by name)
    { "name": "OLD_TOKEN", "value": null }        // remove
  ]
}

Un nom que vous ne mentionnez pas garde ce qu’il avait. Les valeurs sont en écriture seule : aucun endpoint ne les renvoie jamais. Les écrire est réservé aux owners/admins, et une clé d’API a besoin du scope secrets:write en plus de projects:write — les mêmes garde-fous que les routes dédiées /secrets, qui restent disponibles pour un changement ponctuel.

GET    /api/orgs              List organizations
POST   /api/orgs              Create organization
GET    /api/orgs/:orgId       Get organization details
GET    /api/orgs/:orgId/members  List members

GET    /api/orgs/:orgId/projects                         List projects
POST   /api/orgs/:orgId/projects                         Create project
GET    /api/orgs/:orgId/projects/:projectId              Get project
PATCH  /api/orgs/:orgId/projects/:projectId              Update project
DELETE /api/orgs/:orgId/projects/:projectId              Delete project

GET    /api/orgs/:orgId/sandboxes                           List sandboxes (?projectId=)
POST   /api/orgs/:orgId/sandboxes                           Create a sandbox { projectId, appId: "spunto-cloud", branch?, size?, fromSnapshot? }
GET    /api/orgs/:orgId/sandboxes/:sandboxId                Get a sandbox
POST   /api/orgs/:orgId/sandboxes/:sandboxId/start          Start a stopped or paused sandbox
POST   /api/orgs/:orgId/sandboxes/:sandboxId/stop           Stop it (/workspace kept)
POST   /api/orgs/:orgId/sandboxes/:sandboxId/pause          Pause it (memory kept, not billed)
POST   /api/orgs/:orgId/sandboxes/:sandboxId/rebuild        Rebuild at the project's current version
POST   /api/orgs/:orgId/sandboxes/:sandboxId/exec           Run a command
GET    /api/orgs/:orgId/sandboxes/:sandboxId/ports          The IDE's URL and listening ports
POST   /api/orgs/:orgId/sandboxes/:sandboxId/snapshots      Snapshot it
DELETE /api/orgs/:orgId/sandboxes/:sandboxId                Destroy it and its storage

POST   /api/orgs/:orgId/projects/:projectId/tasks           Delegate a task { prompt, ... }
GET    /api/orgs/:orgId/tasks                               Every task of the organization
GET    /api/orgs/:orgId/projects/:projectId/tasks/:taskId   Get a task

Toutes les routes des tâches : Tâches avancées.

GET    /api/orgs/:orgId/api-keys           List keys
POST   /api/orgs/:orgId/api-keys           Create a key (token shown once)
DELETE /api/orgs/:orgId/api-keys/:keyId    Revoke a key

Session uniquement — une clé d’API ne peut pas servir à gérer d’autres clés d’API. Voir Clés d’API.

GET    /api/users/me            Get current user (dotfilesRepo)
PATCH  /api/users/me            Update user settings
GET    /api/users/me/secrets    List secret names
POST   /api/users/me/secrets    Create / replace secret
DELETE /api/users/me/secrets/:secretId  Delete secret

Tout ce qui est en direct passe par un upgrade WebSocket plutôt que par un appel REST. Ces endpoints figurent dans le spec OpenAPI comme le reste de l’API — repérez (WebSocket) dans leur résumé ; chacun documente ses paramètres de requête et la forme exacte des frames qu’il échange.

EndpointDescription
GET /api/sandboxes/:id/terminal?mode=terminalS’attacher à une session de terminal persistante dans une sandbox
GET /api/sandboxes/:id/terminal?mode=logsSuivre les logs de la sandbox
GET /api/sandbox-builds/:id/logsLe log du build d’un projet, avec ses étapes
GET /api/sandboxes/:id/prepare/logsLe log de setup d’une sandbox

Le handshake s’authentifie exactement comme un appel REST — Authorization: Bearer <token>, avec un token de session, ou une clé d’API qui a le scope workers:exec pour le terminal d’une sandbox. Un navigateur ne peut pas poser d’en-têtes sur un WebSocket : depuis le navigateur, c’est le cookie session qui sert.

Le terminal d’une sandbox est persistant : le programme continue de tourner quand vous vous déconnectez, et vous retrouvez en vous rattachant son historique de défilement — c’est ce qui le rend utilisable depuis un téléphone.

GET    /api/orgs/:orgId/sandboxes/:sandboxId/terminals        List sessions
POST   /api/orgs/:orgId/sandboxes/:sandboxId/terminals        Create a session
DELETE /api/orgs/:orgId/sandboxes/:sandboxId/terminals/:name  Kill a session

Listez les sessions, puis attachez-vous à l’une d’elles par son nom. Fermer le socket détache la session ; cela ne la tue pas.

const ws = new WebSocket(`wss://spunto.net/api/sandboxes/${sandboxId}/terminal?session=main`)
 
ws.onmessage = (e) => {
  const frame = JSON.parse(e.data)
  // "ready" once attached, then "output" frames — base64-encoded raw bytes.
  if (frame.type === "output") term.write(atob(frame.data))
}
 
ws.send(JSON.stringify({ type: "input", data: btoa("ls -la\n") }))
ws.send(JSON.stringify({ type: "resize", cols: 80, rows: 24 }))

Ils ne font pas partie de la surface de l’API — ils s’authentifient avec des tokens d’infrastructure, pas avec les vôtres.

EndpointDescription
GET /api/sandbox-agent/connectL’agent dans une sandbox (token de la sandbox)
GET /api/tunnel/relayRelais proxy ↔ agent

Remarque

Pour la référence interactive complète, avec les schémas de requête et de réponse et un client HTTP intégré, rendez-vous sur /api/docs.