Quickstart
Créer une app minimale, importer son manifest, l'installer, échanger un launch_token et écrire une première donnée.
Ce guide crée une app "Audit Hello" qui stocke et relit des inspections depuis un frontend externe.
Prérequis. Vous avez un espace client Superfasttt actif, un jeton
utilisateur disposant des droits d'administration nécessaires, et une URL de
frontend. En développement, http://localhost:3000 est accepté.
1. Créer le manifest
Créez manifest.json :
{
"manifest_version": "2.0",
"id": "audit-hello",
"name": "Audit Hello",
"version": "1.0.0",
"description": "Application de démonstration pour gérer des inspections.",
"runtime": {
"type": "external",
"entry_url": "http://localhost:3000",
"allowed_origins": ["http://localhost:3000"]
},
"permissions": [
"app_data:read",
"app_data:write"
],
"collections": {
"inspections": {
"schema": {
"type": "object",
"properties": {
"title": { "type": "string" },
"status": { "type": "string", "enum": ["draft", "done"] }
},
"required": ["title", "status"],
"additionalProperties": false
},
"indexes": ["status"]
}
}
}entry_url est l'URL vers laquelle l'utilisateur sera envoyé au lancement.
allowed_origins doit contenir l'origin exacte de votre frontend
(scheme + host + port).
2. Valider le manifest
Les endpoints de manifest attendent une enveloppe JSON :
{
"manifest": {
"...": "contenu de votre manifest"
}
}Créez manifest-request.json avec cette enveloppe, puis validez :
curl -X POST https://api.superfasttt.ai/api/v1/app-platform/manifests/validate \
-H "Authorization: Bearer <user_access_token>" \
-H "X-Tenant-ID: <espace_client>" \
-H "Content-Type: application/json" \
-d @manifest-request.jsonRéponse attendue :
{
"valid": true,
"errors": [],
"warnings": []
}La validation ne modifie rien. Utilisez-la avant chaque import ou dans votre CI pour détecter les erreurs de manifest.
3. Importer puis installer
L'import enregistre la version du manifest pour l'espace client.
curl -X POST https://api.superfasttt.ai/api/v1/app-platform/manifests/import \
-H "Authorization: Bearer <user_access_token>" \
-H "X-Tenant-ID: <espace_client>" \
-H "Content-Type: application/json" \
-d @manifest-request.jsonExemple de réponse :
{
"app_id": "audit-hello",
"version": "1.0.0",
"lifecycle_status": "draft",
"created": true,
"validation": {
"valid": true,
"errors": [],
"warnings": []
}
}Installez ensuite l'app :
curl -X POST https://api.superfasttt.ai/api/v1/app-platform/apps/audit-hello/install \
-H "Authorization: Bearer <user_access_token>" \
-H "X-Tenant-ID: <espace_client>"Exemple de réponse :
{
"id": "<id>",
"app_id": "audit-hello",
"state": "active",
"enabled": true,
"app_version_id": "<version_id>",
"granted_permissions": ["app_data:read", "app_data:write"]
}N'exposez jamais un jeton utilisateur d'administration dans votre frontend externe. Les actions d'import et d'installation doivent être effectuées depuis un contexte autorisé.
4. Générer une URL de lancement
Un utilisateur autorisé peut demander un launch_token pour ouvrir l'app :
curl -X POST https://api.superfasttt.ai/api/v1/app-platform/apps/audit-hello/launch-token \
-H "Authorization: Bearer <user_access_token>" \
-H "X-Tenant-ID: <espace_client>"Réponse :
{
"launch_token": "<launch_token>",
"entry_url": "http://localhost:3000?launch_token=<launch_token>",
"expires_at": "2026-05-28T10:17:37Z"
}Redirigez l'utilisateur vers entry_url. Le launch_token est court et à
usage unique : votre frontend doit l'échanger immédiatement.
5. Échanger le launch_token dans le frontend
Dans votre app, lisez launch_token, appelez l'endpoint d'échange, puis retirez
le paramètre de l'URL.
const url = new URL(window.location.href);
const launchToken = url.searchParams.get("launch_token");
if (!launchToken) {
throw new Error("launch_token manquant");
}
const response = await fetch(
"https://api.superfasttt.ai/api/v1/app-platform/runtime/exchange",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ launch_token: launchToken }),
}
);
if (!response.ok) {
throw new Error(`Exchange failed: ${response.status}`);
}
const { access_token, token_type, expires_in, scopes } = await response.json();
url.searchParams.delete("launch_token");
window.history.replaceState({}, document.title, url.toString());curl -X POST https://api.superfasttt.ai/api/v1/app-platform/runtime/exchange \
-H "Content-Type: application/json" \
-H "Origin: http://localhost:3000" \
-d '{"launch_token":"<launch_token>"}'{
"access_token": "<app_access_token>",
"token_type": "Bearer",
"expires_in": 900,
"scopes": ["app_data:read", "app_data:write"]
}Gardez l'access_token uniquement le temps de la session app. Pour les appels
suivants, envoyez-le dans le header Authorization.
6. Créer et lister une inspection
const headers = {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
};
const created = await fetch(
"https://api.superfasttt.ai/api/v1/app-data/inspections",
{
method: "POST",
headers,
body: JSON.stringify({
data: { title: "Inspection ligne A", status: "draft" },
}),
}
).then((r) => r.json());
const list = await fetch(
"https://api.superfasttt.ai/api/v1/app-data/inspections/query",
{
method: "POST",
headers,
body: JSON.stringify({
filter: { status: "draft" },
sort: "-updated_at",
page: 1,
page_size: 50
}),
}
).then((r) => r.json());Réponse de liste :
{
"items": [
{
"id": "<record_id>",
"collection": "inspections",
"data": { "title": "Inspection ligne A", "status": "draft" },
"version": 1,
"created_at": "2026-05-28T10:20:00Z",
"updated_at": "2026-05-28T10:20:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 50
}7. Aller plus loin : documents riches et fichiers
Si votre app gère des rapports éditables ou des pièces jointes, vous appelez
deux API supplémentaires avec le même access_token. Pensez d'abord à ajouter
les permissions et déclarations dans votre manifest, puis réimportez et
réinstallez :
"permissions": [
"app_data:read", "app_data:write",
"rich_documents:read", "rich_documents:write",
"assets:read", "assets:write"
],
"rich_documents": {
"audit_report": {
"editor": "prosemirror",
"schema_version": "audit-report-v1"
}
},
"assets": {
"allowed_mime_types": ["application/pdf", "image/png"],
"max_file_size_mb": 25,
"max_total_size_mb": 1024
}Créer un document riche
La clé collection correspond à celle déclarée dans manifest.rich_documents.
editor et schema_version doivent matcher la déclaration du manifest installé.
const doc = await fetch(
"https://api.superfasttt.ai/api/v1/rich-documents",
{
method: "POST",
headers,
body: JSON.stringify({
collection: "audit_report",
title: "Rapport site A",
editor: "prosemirror",
schema_version: "audit-report-v1",
content: {
type: "doc",
content: [
{
type: "paragraph",
content: [{ type: "text", text: "Contenu initial." }],
},
],
},
}),
}
).then((r) => r.json());Le serveur extrait automatiquement plain_text depuis content pour la
recherche. Les mises à jour suivantes via PATCH /api/v1/rich-documents/{id}
incrémentent version. L'historique est listable via
GET /api/v1/rich-documents/{id}/versions.
Uploader un fichier
Le flow assets est en 3 appels — l'upload binaire va directement au stockage, votre serveur ne le voit jamais transiter.
// 1. URL signée
const { asset_id, upload_url, required_headers } = await fetch(
"https://api.superfasttt.ai/api/v1/app-assets/upload-url",
{
method: "POST",
headers,
body: JSON.stringify({
filename: "rapport.pdf",
content_type: "application/pdf",
size_bytes: 12345,
}),
}
).then((r) => r.json());
// 2. PUT direct au stockage S3-compatible
await fetch(upload_url, {
method: "PUT",
headers: required_headers,
body: fileBlob,
});
// 3. Confirmer — le serveur revérifie taille + content-type via HEAD
await fetch(
"https://api.superfasttt.ai/api/v1/app-assets/complete",
{
method: "POST",
headers,
body: JSON.stringify({ asset_id }),
}
);Pour télécharger ensuite, demandez une URL signée à durée limitée :
const { download_url } = await fetch(
`https://api.superfasttt.ai/api/v1/app-assets/${asset_id}/download-url`,
{ method: "POST", headers }
).then((r) => r.json());size_bytes doit être strictement positif et inférieur ou égal à
assets.max_file_size_mb de votre manifest. La somme des assets d'une
installation ne peut pas dépasser assets.max_total_size_mb. Le serveur
refuse les valeurs négatives avant d'enregistrer le fichier.
Erreurs fréquentes
| Erreur | Cause probable | Action |
|---|---|---|
422 à l'import | Le body n'est pas enveloppé dans { "manifest": ... } ou le manifest est invalide | Valider avec /manifests/validate et corriger les champs indiqués |
403 origin_required | L'échange est appelé sans header Origin | Tester depuis le navigateur ou ajouter Origin en curl |
403 origin_not_allowed | L'origin réelle n'est pas dans runtime.allowed_origins | Corriger le manifest, réimporter et réinstaller |
401 token_invalid_or_used_or_expired | launch_token déjà utilisé ou expiré | Générer un nouveau launch_token |
403 missing_scope | L'app n'a pas la permission requise | Ajouter la permission au manifest, réimporter et réinstaller |
404 collection_not_found | La collection n'est pas déclarée dans le manifest installé | Ajouter la collection, réimporter et réinstaller |
Et après
Consultez la référence du manifest pour ajouter des documents, des fichiers ou plusieurs collections. Consultez Authentification & sécurité pour les règles de session et d'origin.

