Guide de développement de l'intégration de l'API Web FormRead

Comment fonctionne l'API FormRead

L'API FormRead est divisée en deux parties : une API REST pour gérer les formulaires (créer, mettre à jour, supprimer et stocker des données) et un iframe intégrable pour l'édition de formulaires et la lecture de documents numérisés. L'API seule ne traite pas et ne lit pas les formulaires — la lecture est entièrement gérée via l'iframe.

  • API REST (cette page) : Utilisez-la pour créer, mettre à jour, supprimer et récupérer les métadonnées des formulaires. L'API stocke les données de votre formulaire et renvoie les jetons nécessaires pour intégrer l'iframe.
  • Iframe (visionneuse intégrée) : Utilisez-le pour modifier les modèles de formulaires, télécharger des documents numérisés et extraire les résultats (OMR, OCR, BCR). Toute la lecture des formulaires et l'extraction de données se fait dans l'iframe.
Vous cherchez un traitement serveur à serveur ?

Si vous n'avez pas besoin d'interface visuelle et souhaitez simplement envoyer des images et recevoir des résultats en JSON, consultez l' API de traitement côté serveur.

Flux d'intégration typique
  1. Authentifiez-vous avec un jeton Bearer (généré depuis le tableau de bord).
  2. Utilisez le point d'accès POST /api/forms pour créer un formulaire et obtenir le iframe_token.
  3. Intégrez l'iframe dans votre page en utilisant le iframe_token pour permettre aux utilisateurs de modifier les formulaires et de numériser des documents.
  4. Écoutez les événements de l'iframe (editForm, getResults, rowResult) pour recevoir les données du formulaire et les résultats extraits, puis stockez-les dans votre système.

Authentification

Pour les utilisations en entreprise, l'API peut être utilisée en générant un jeton d'authentification Bearer.

Connectez-vous au tableau de bord FormRead tableau de bord et accédez à l'option Token API:

FormRead dashboard menu with the API Tokens option highlighted

Créez les jetons API pour permettre à des services tiers de s'authentifier auprès de notre application en votre nom:

Creating a new FormRead API token with permission checkboxes

Copiez le jeton généré dans un endroit sécurisé (il ne sera affiché qu'une seule fois):

The generated FormRead API Bearer token shown once — copy and store it securely

Créer un nouveau formulaire

POST /api/forms

Headers

Name Value
Authorization Bearer YOUR_API_TOKEN
Accept application/json

Request

curl --location --request POST 'https://formread.org/api/forms' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --form 'form_name="new form"' \
  --form 'custom_css="{ingest custom css to edit FormRead View}"'

Response

{
  "id": 8,
  "form_name": "new form",
  "iframe_token": "6ifvCyEcjB3D5SGqtFmJ5eg0sPYNQfLoWCEgv7bb",
  "created_at": "2022-02-28T21:22:55.000000Z",
  "updated_at": "2022-02-28T21:22:55.000000Z"
}

La variable custom_css permettra d'ingérer des règles css pour modifier l'apparence de FormRead et ajouter du texte personnalisé, comme par exemple :

#app-title::after{
  content: 'Your Tittle';
  color: white;
}
#app-subtitle::after{
  content: 'Your Custom sub-tittle Your Custom sub-tittle Your Custom sub-tittle';
  color: white;
}
#upload-from-cam{
  display: none;
}
#upload-from-system{
  background: lightblue;
}
#upload-from-csv{
  display: none;
}
#app > div.bg-gray-50.h-screen.overflow-auto > div > div{
  background-color: black;
}

Obtenir le formulaire par ID

GET /api/forms/{form_id}

Request

curl --location --request GET 'https://formread.org/api/forms/8' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN'

Response

{
  "id": 8,
  "form_name": "adsf",
  "iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
  "created_at": "2022-02-28T21:22:55.000000Z",
  "updated_at": "2022-03-01T01:40:19.000000Z"
}

Modifier un formulaire

Après qu'un formulaire a été créé ou obtenu, il peut être affiché dans un iframe en utilisant le iframe_token fourni dans la réponse (ce jeton varie donc assurez-vous de récupérer votre formulaire avant de rendre l'iframe)

Créez également un script qui écoute les événements de l'iframe comme dans l'exemple ci-dessous:

<!DOCTYPE html>
<html style="height: 100%">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body style="height: 100%">

<iframe src="https://formread.org/{lang}/api/forms/{form_id}/edit/{iframe_token}/{read_only}"
        style="height: 100%; width: 100%"></iframe>

<script>
    window.addEventListener('message', function (e) {
        // if (e.origin !== 'https://formread.org') return;

        console.log(e.data.method)

        if (e.data.method === "editForm") {
            let formData = e.data.formData // data used to saved your form
            let schema = JSON.parse(e.data.schema)
            console.log(schema)
            console.log(formData)
        }
        if (e.data.method === "getResults") {
            let results = JSON.parse(e.data.results)
            console.log(results)
        }
        if (e.data.method === "rowResult") {
            let rowResult = JSON.parse(e.data.rowResult)
            console.log(rowResult)
        }
    });
</script>
</body>
</html>

Paramètres de l'URL de l'iframe

Paramètre Description
lang Définissez la variable lang pour afficher les commandes de l'application dans la langue désirée. Actuellement, nous prenons en charge l'anglais (en), le français (fr), l'espagnol (es), le portugais brésilien (pt) ou le kazakh (kk)
read_only La variable read_only peut être définie sur 1 pour désactiver la modification du formulaire ou 0 pour autoriser la modification du formulaire

Événements de l'iframe

Lorsque les utilisateurs cliquent sur le bouton Enregistrer, la méthode <code class="language-plaintext">editForm</code> sera déclenchée, vous avez alors accès à 2 variables :

  • La variable formData contiendra les attributs de formulaire encodés qui peuvent être envoyés en utilisant la mise à jour pour enregistrer les modifications apportées à votre formulaire :
  • la variable schema vous permettra de savoir quels champs ont été créés jusqu'à présent:
    {
      "file_name": {
        "type": "text"
      },
      "BCR-0": {
        "type": "text"
      },
      "OCR-1": {
        "type": "text"
      },
      "OMR-2-0": {
        "type": "select",
        "options": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
        "questionIndex": "0"
      },
      "OMR-2-1": {
        "type": "select",
        "options": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
        "questionIndex": "1"
      },
      "OMR-2-2": {
        "type": "select",
        "options": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
        "questionIndex": "2"
      }
    }

    La variable schema est destinée uniquement à vous permettre d'afficher des alertes à vos utilisateurs dans le cas où vous exigeriez que des champs de zone obligatoires soient créés:

Lorsqu'un utilisateur clique sur télécharger les résultats, la méthode getResults sera déclenchée, vous obtiendrez alors les données de résultat dans un format JSON afin que vous puissiez les stocker dans votre système

De plus, vous pouvez obtenir les résultats ligne par ligne avec la méthode rowResult, qui sera déclenchée à chaque fois qu'une page est traitée

Mettre à jour le formulaire

PUT /api/forms/{form_id}

Request

curl --location --request POST 'https://formread.org/api/forms/8?_method=PUT' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --form 'form_data="eyJ2dWV4X3N0YXRlIjp7ImZvcm1OYW1lIjoiYWRzZiIsImZvcm1zIjp7f
                     Swic2VsZWN0ZWRGb3JtSWQiOiIiLCJmb3JtUmVhZEFyZWFzIjp7IkJDUi
                     0wIjp7ImNvbHVtblBvc2l0aW9uIjoxLCJ3aWR0aCI6MC4xMTQ5NTA0NTM
                     0MDUzNTE2NCwiaGVpZ2h0IjowL...' \
  --form 'custom_css="{ingest custom css to edit FormRead View}"'

Response

{
  "id": 8,
  "form_name": "adsf",
  "iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
  "created_at": "2022-02-28T21:22:55.000000Z",
  "updated_at": "2022-03-01T02:30:14.000000Z"
}

Supprimer le formulaire

DELETE /api/forms/{form_id}

Request

curl --location --request DELETE 'https://formread.org/api/forms/8' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN'

Response

1

Exemple complet : intégration du flux de notation

Voici un exemple de bout en bout montrant comment un enseignant peut concevoir un formulaire, numériser des examens et envoyer les résultats notés à votre propre backend — le tout depuis une seule page qui intègre l'iframe de FormRead.

Scénario

Un enseignant ouvre votre application, conçoit une feuille de réponses « Mathématiques 101 - Partiel », l'imprime, numérise les examens remplis, puis clique sur « Télécharger les résultats ». Votre page écoute les événements de l'iframe, envoie la disposition et les réponses notées à votre propre backend, qui les relaie ensuite à FormRead.

Étape 1 — Créer le formulaire depuis votre serveur

Sur votre backend, créez un formulaire pour l'enseignant. Vous recevez un id et un iframe_token — ce sont les valeurs que vous passerez à l'URL de l'iframe à l'étape suivante.

# From YOUR backend (never from the browser)
curl --location --request POST 'https://formread.org/api/forms' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --form 'form_name="Math 101 - Midterm"'
{
  "id": 42,
  "form_name": "Math 101 - Midterm",
  "iframe_token": "6ifvCyEcjB3D5SGqtFmJ5eg0sPYNQfLoWCEgv7bb",
  "created_at": "2026-04-20T10:00:00.000000Z",
  "updated_at": "2026-04-20T10:00:00.000000Z"
}

Enregistrez l'id et l'iframe_token avec la fiche de l'enseignant dans votre propre base de données. Vous les utiliserez pour afficher l'iframe en mode édition à l'étape 2.

Étape 2 — Ouvrir l'iframe en mode édition

Votre backend affiche une page contenant l'iframe FormRead avec read_only=0, afin que l'enseignant puisse dessiner les bulles OMR, les zones OCR et les codes-barres sur la feuille. Lorsqu'il clique sur « Enregistrer » dans l'iframe, l'événement editForm est déclenché — le navigateur transmet le formData brut à votre propre backend. Le navigateur n'appelle jamais FormRead directement.

<!-- /design-form page rendered by YOUR backend.
     read_only = 0 → editable mode -->
<iframe id="formread-frame"
        src="https://formread.org/en/api/forms/42/edit/6ifvCyEcjB3D5SGqtFmJ5eg0sPYNQfLoWCEgv7bb/0"
        style="width:100%; height:100vh; border:0"></iframe>

<script>
    // The browser ONLY talks to your own backend. Never to FormRead.
    const FORM_ID = 42;

    window.addEventListener('message', async function (e) {
        if (e.origin !== 'https://formread.org') return;

        // Teacher clicked "Save" inside the iframe
        if (e.data.method === 'editForm') {
            await fetch(`/api/forms/${FORM_ID}/layout`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ form_data: e.data.formData })
            });
        }
    });
</script>

Étape 3 — Persister la disposition depuis votre backend

Votre backend reçoit la chaîne formData et la transmet à FormRead via un PUT, en utilisant votre token Bearer (qui ne quitte jamais le serveur). C'est ce qui enregistre définitivement la configuration du formulaire afin que le même formulaire puisse ensuite être réutilisé pour scanner les examens.

# Inside your backend handler for POST /api/forms/42/layout
# $formData is the raw string your browser posted.
curl --location --request POST 'https://formread.org/api/forms/42?_method=PUT' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --form "form_data=${formData}"
{
  "id": 42,
  "form_name": "Math 101 - Midterm",
  "iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
  "created_at": "2026-04-20T10:00:00.000000Z",
  "updated_at": "2026-04-20T10:15:42.000000Z"
}
L'iframe_token change à chaque mise à jour

Chaque mise à jour d'un formulaire renvoie un nouvel iframe_token. Récupérez toujours le plus récent depuis votre backend juste avant d'afficher l'iframe — ne le codez pas en dur ni ne le mettez en cache durablement.

Étape 4 — Récupérer l'iframe_token actuel

Plus tard, lorsque l'enseignant est prêt à scanner les examens, votre backend interroge le formulaire par id pour obtenir l'iframe_token le plus récent.

# From YOUR backend, right before rendering the scan page
curl --location --request GET 'https://formread.org/api/forms/42' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN'
{
  "id": 42,
  "form_name": "Math 101 - Midterm",
  "iframe_token": "po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6",
  "created_at": "2026-04-20T10:00:00.000000Z",
  "updated_at": "2026-04-20T10:15:42.000000Z"
}

Étape 5 — Rouvrir l'iframe en lecture seule pour scanner

Affichez à nouveau l'iframe — cette fois avec read_only=1 à la fin de l'URL. L'enseignant ne peut plus modifier la disposition, uniquement téléverser des scans. Le navigateur transmet rowResult (progression par feuille) et getResults (téléchargement final) à votre backend.

<!-- /scan-exams page. Note read_only = 1 at the end of the URL. -->
<iframe id="formread-frame"
        src="https://formread.org/en/api/forms/42/edit/po75a0pqut4fa16XWgdEP2qRDwnhgfiqP3H0Dij6/1"
        style="width:100%; height:100vh; border:0"></iframe>

<script>
    const FORM_ID = 42;

    window.addEventListener('message', async function (e) {
        if (e.origin !== 'https://formread.org') return;

        // Live progress while each sheet is processed
        if (e.data.method === 'rowResult') {
            const row = JSON.parse(e.data.rowResult);
            console.log('Processed', row.file_name);
        }

        // Teacher clicked "Download results"
        if (e.data.method === 'getResults') {
            const results = JSON.parse(e.data.results);

            await fetch('/api/grades/bulk', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ form_id: FORM_ID, results })
            });
        }
    });
</script>

Étape 6 — Traiter les résultats sur votre backend

L'événement getResults fournit un tableau avec une entrée par examen traité. Les clés suivent le schéma {TypeZone}-{IndexZone}[-{IndexQuestion}]. Voici ce que le navigateur enverrait à votre endpoint /api/grades/bulk :

[
  {
    "file_name": "student_001.jpg",
    "BCR-0": "20260420-001",
    "OCR-1": "Alice Johnson",
    "OMR-2-0": "3",
    "OMR-2-1": "7",
    "OMR-2-2": "9"
  },
  {
    "file_name": "student_002.jpg",
    "BCR-0": "20260420-002",
    "OCR-1": "Ben Carter",
    "OMR-2-0": "3",
    "OMR-2-1": "6",
    "OMR-2-2": "9"
  }
]
Gardez votre token côté serveur

N'exposez jamais votre token Bearer dans le code exécuté côté navigateur. Tous les appels de création, mise à jour et lecture à l'API FormRead passent par votre propre backend — le navigateur ne voit jamais que l'iframe_token, qui est limité à un seul formulaire.

Questions fréquentes

Qu'est-ce que l'API d'intégration par iframe de FormRead ?

C'est une API REST associée à un iframe intégrable. Votre backend gère les formulaires via les endpoints REST ; l'iframe s'affiche dans votre application web pour que les utilisateurs puissent concevoir des formulaires, téléverser des scans et consulter les résultats sans quitter votre interface.

Le jeton iframe_token expire-t-il ou change-t-il ?

L'iframe_token est régénéré à chaque mise à jour du formulaire. Récupérez toujours la dernière valeur depuis votre backend (GET /api/forms/{id}) juste avant d'afficher l'iframe — ne le mettez pas en cache durablement.

Quelle est la différence entre read_only=0 et read_only=1 ?

read_only=0 ouvre l'iframe en mode édition pour que l'utilisateur puisse concevoir le formulaire (placer bulles OMR, zones OCR, codes-barres). read_only=1 l'ouvre uniquement en mode scan — l'utilisateur peut téléverser des feuilles remplies et télécharger les résultats, mais ne peut pas modifier la mise en page.

Puis-je garder mon token API dans le navigateur ?

Non. Le token Bearer doit rester côté serveur. Tous les appels de création, mise à jour et lecture à l'API REST FormRead doivent passer par votre propre backend. Le navigateur n'a besoin que de l'iframe_token, qui est limité à un seul formulaire.

Comment recevoir les résultats scannés ?

L'iframe envoie des messages via window.postMessage. Écoutez method="getResults" pour recevoir le tableau complet des résultats (une entrée par feuille scannée), et method="rowResult" pour afficher la progression feuille par feuille pendant le scan.

Lien de la collection Postman

Ouvrir la collection Postman

Prêt à essayer FormRead ?

Créez, lisez et traitez des formulaires OMR en toute simplicité. Commencez à extraire des données de vos formulaires dès aujourd'hui !

Aucune carte de crédit requise pour commencer