Todo lo que hace el panel, desde tu terminal
Una clave de cuenta. Lista tus sitios, despliega en ellos, renómbralos, lee lo que recogieron tus formularios, bórralos — por HTTP a secas, desde un script, un job de CI o un agente.
Tres comandos
Crea una clave en tu panel, comprueba que funciona y pon una carpeta en línea. La clave va en una cabecera Authorization en cada llamada.
curl -H "Authorization: Bearer hvs_…" https://harvis.dev/api/v1
curl -H "Authorization: Bearer hvs_…" https://harvis.dev/api/v1/sites
curl -X POST https://harvis.dev/api/v1/sites \ -H "Authorization: Bearer hvs_…" \ -F "files=@index.html" -F "paths=index.html"
La app web y la API no pueden separarse
Cada capacidad se declara una vez, en un solo archivo, y tanto el panel como esta API se construyen a partir de ahí. openapi.json se genera desde esa declaración, y la compilación falla si las dos no coinciden. Así que esto no es documentación que describe el producto: es aquello de lo que está hecho el producto.
- Una implementación por capacidad, llamada igual por la app web que por tu script.
- openapi.json se genera, nunca se escribe a mano, y se sirve en /openapi.json.
- La compilación falla en cuanto una ruta, el contrato y el documento dejan de coincidir.
Con una clave, el sitio es tuyo de inmediato
Desplegar sin cuenta sigue funcionando y lo seguirá haciendo: recibes un enlace de reclamación privado para abrir más tarde. Manda una clave en la misma llamada y no hay nada que reclamar: el sitio está en tu cuenta desde el primer byte y nunca caduca.
zip -r site.zip . && curl -X POST https://harvis.dev/api/upload \ -H "Authorization: Bearer hvs_…" \ -H "Content-Type: application/zip" --data-binary @site.zip
Toda la superficie
Las formas completas de petición y respuesta están en el documento OpenAPI.
| método | ruta | qué hace |
|---|---|---|
| GET | /api/v1 | Check that a credential works. |
| GET | /api/v1/keys | The account's API keys. Revoked keys are not listed. |
| POST | /api/v1/keys | Create an API key. |
| DELETE | /api/v1/keys/{keyId} | Revoke an API key. Anything using it stops working immediately. |
| GET | /api/v1/me | The account a credential belongs to. |
| GET | /api/v1/sites | List the account's sites, newest first. |
| POST | /api/v1/sites | Create a site from a folder of files. |
| DELETE | /api/v1/sites/{id} | Delete a site, its files and its form submissions. |
| GET | /api/v1/sites/{id} | One site. |
| PATCH | /api/v1/sites/{id} | Rename a site, change its web address, or both. |
| POST | /api/v1/sites/{id}/deploy | Replace every file of a site with the uploaded set. |
| POST | /api/v1/sites/{id}/deploy-token | Issue a new deploy token for a site. The old one stops working immediately. |
| POST | /api/v1/sites/{id}/deploy/zip | Replace every file of a site from a zip archive sent as the raw request body. |
| GET | /api/v1/sites/{id}/files | Every file a site is serving. |
| POST | /api/v1/sites/{id}/files | Add or overwrite individual files, leaving the rest of the site alone. |
| DELETE | /api/v1/sites/{id}/submissions | Delete every submission for a site, or every one of a single form. |
| GET | /api/v1/sites/{id}/submissions | One page of a site's form submissions, newest first. |
| DELETE | /api/v1/sites/{id}/submissions/{submissionId} | Delete one submission. |
| GET | /api/v1/sites/{id}/submissions/{submissionId} | One submission. |
| GET | /api/v1/sites/{id}/submissions/csv | Export a site's form submissions as CSV. |
| POST | /api/v1/sites/{id}/submissions/read | Mark every unread submission as read. |
| GET | /api/v1/sites/{id}/submissions/summary | How many submissions a site holds, how many are unread, and which forms exist. |
| POST | /api/v1/sites/import | Create a site by downloading a single page from a known artifact URL. |
Todo fallo tiene la misma forma
Ramifica según el código, nunca según el mensaje. Los códigos son estables; la prosa es para quien lea el log.
{
"error": {
"code": "subdomainTaken",
"message": "That address is already taken. Try another."
}
}