Guía para desarrolladores de integración de la API web de FormRead

Cómo funciona la API de FormRead

La API de FormRead se divide en dos partes: una API REST para gestionar formularios (crear, actualizar, eliminar y almacenar datos) y un iframe integrable para editar formularios y leer documentos escaneados. La API por sí sola no procesa ni lee formularios — la lectura se realiza completamente a través del iframe.

  • API REST (esta página): Úsela para crear, actualizar, eliminar y obtener metadatos de formularios. La API almacena los datos de su formulario y devuelve los tokens necesarios para integrar el iframe.
  • Iframe (visor integrado): Úselo para editar plantillas de formularios, cargar documentos escaneados y extraer resultados (OMR, OCR, BCR). Toda la lectura de formularios y extracción de datos ocurre dentro del iframe.
¿Buscas procesamiento servidor a servidor?

Si no necesitas una interfaz visual y solo quieres enviar imágenes y recibir resultados como JSON, consulta la API de procesamiento del lado del servidor.

Flujo de integración típico
  1. Autentíquese con un token Bearer (generado desde el panel de control).
  2. Use el endpoint POST /api/forms para crear un formulario y obtener el iframe_token.
  3. Integre el iframe en su página usando el iframe_token para permitir a los usuarios editar formularios y escanear documentos.
  4. Escuche los eventos del iframe (editForm, getResults, rowResult) para recibir los datos del formulario y los resultados extraídos, luego almacénelos en su sistema.

Autenticación

Para usos empresariales, la API se puede usar generando un token de autenticación "Bearer".

Inicie sesión en el panel de FormRead, y acceda a la opción API Token:

FormRead dashboard menu with the API Tokens option highlighted

Cree los tokens de API para permitir que los servicios de terceros se autentiquen con nuestra aplicación en su nombre:

Creating a new FormRead API token with permission checkboxes

Copie el token generado en un lugar seguro (solo se mostrará una vez):

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

Crear nuevo formulario

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 permitirá ingresar reglas CSS para editar la apariencia de la vista FormRead y agregar texto personalizado, como por ejemplo:

#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;
}

Obtener formulario por 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"
}

Editar un formulario

Después de que un formulario es Creado o traido (GET) se puede mostrar en un Iframe usando el iframe_token proporcionado en la respuesta (este token varía, así que asegúrese de Traer (GET) su formulario antes de renderizar el iframe)

Cree también un script que escuche los eventos del iframe como en el siguiente ejemplo:

<!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>

Parámetros de URL del iframe

Parámetro Descripción
lang Configure la variable lang para mostrar los comandos de la aplicación en el idioma deseado. Actualmente, admitimos inglés (en), francés (fr), español (es), portugués brasileño (pt) o kazajo (kk)
read_only Variable read_only se puede configurar en 1 para deshabilitar la edición de formularios o 0 para permitir la edición de formularios

Eventos del iframe

Cuando los usuarios hacen clic en el botón Guardar, el <code class="language-plaintext">editForm</code> se activará el método, allí tiene acceso a 2 variables:

  • La variable formData contendrá los atributos de formulario codificados que se pueden enviar utilizando el Actualizarpara guardar los cambios realizados en su formulario:
  • La variable schema le permitirá conocer los campos creados hasta el momento:
    {
      "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á destinada solo para que muestre, si asi lo desea, algunas alertas a sus usuarios en caso de que requiera que se creen campos de área obligatorios:

Cuando un usuario hace clic en los resultados de la descarga, el metodo getResults se activará, allí obtendrá los resultados en un formato JSON para que pueda almacenar luego en su sistema

Además, puede obtener los resultados fila por fila con el metodo rowResult, que se activará cada vez que se procese una página

Guardar Formulario

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"
}

Eliminar formulario

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

Ejemplo completo: integrando el flujo de calificación

Este es un ejemplo de extremo a extremo que muestra cómo un profesor puede diseñar un formulario, escanear exámenes y enviar los resultados calificados a tu propio backend, todo desde una sola página que integra el iframe de FormRead.

Escenario

Un profesor abre tu aplicación, diseña una hoja de respuestas "Matemáticas 101 - Examen parcial", la imprime, escanea los exámenes completados y hace clic en "Descargar resultados". Tu página escucha los eventos del iframe, guarda el diseño y publica las respuestas calificadas en tu sistema.

Paso 1 — Crear el formulario desde tu servidor

En tu backend, crea un formulario para el profesor. Recibirás un id y un iframe_token — son los valores que pasarás a la URL del iframe en el siguiente paso.

# 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"
}

Guarda el id y el iframe_token asociados al registro del profesor en tu propia base de datos. Los usarás para mostrar el iframe editable en el paso 2.

Paso 2 — Abrir el iframe en modo edición

Tu backend muestra una página que contiene el iframe de FormRead con read_only=0, para que el profesor pueda dibujar burbujas OMR, áreas OCR y códigos de barras en la hoja. Cuando hace clic en "Guardar" dentro del iframe, se dispara el evento editForm — el navegador reenvía el formData en bruto a tu propio backend. El navegador nunca llama directamente a FormRead.

<!-- /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>

Paso 3 — Persistir el diseño desde tu backend

Tu backend recibe la cadena formData y la reenvía a FormRead con un PUT usando tu token Bearer (que nunca sale del servidor). Esto es lo que guarda permanentemente la configuración del formulario para que el mismo pueda reutilizarse después para escanear los exámenes.

# 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"
}
El iframe_token rota

Cada actualización de un formulario devuelve un nuevo iframe_token. Siempre obtén el más reciente desde tu backend justo antes de mostrar el iframe — no lo codifiques ni lo caches a largo plazo.

Paso 4 — Obtener el iframe_token actual

Más adelante, cuando el profesor esté listo para escanear los exámenes, tu backend consulta el formulario por id para obtener el iframe_token más reciente.

# 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"
}

Paso 5 — Reabrir el iframe en modo solo lectura para escanear

Muestra el iframe nuevamente — esta vez con read_only=1 al final de la URL. El profesor ya no puede editar el diseño, solo cargar escaneos. El navegador reenvía rowResult (progreso por hoja) y getResults (descarga final) a tu 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>

Paso 6 — Manejar los resultados en tu backend

El evento getResults entrega un arreglo con una entrada por cada examen procesado. Las claves siguen el patrón {TipoÁrea}-{ÍndiceÁrea}[-{ÍndicePregunta}]. A continuación lo que el navegador enviaría a tu 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"
  }
]
Mantén tu token en el servidor

Nunca expongas tu token Bearer en código visible desde el navegador. Todas las llamadas de creación, actualización y lectura a la API de FormRead pasan por tu propio backend — el navegador solo ve el iframe_token, que está limitado a un único formulario.

Preguntas frecuentes

¿Qué es la API de integración por iframe de FormRead?

Es una API REST más un iframe integrable. Tu backend gestiona los formularios con los endpoints REST; el iframe se muestra dentro de tu aplicación web para que los usuarios puedan diseñar formularios, subir escaneos y revisar resultados sin salir de tu interfaz.

¿El iframe_token caduca o cambia?

El iframe_token se regenera cada vez que el formulario se actualiza. Obtén siempre el valor más reciente desde tu backend (GET /api/forms/{id}) justo antes de mostrar el iframe — no lo caches a largo plazo.

¿Cuál es la diferencia entre read_only=0 y read_only=1?

read_only=0 abre el iframe en modo edición para que el usuario diseñe el formulario (colocar burbujas OMR, áreas OCR y códigos de barras). read_only=1 lo abre solo en modo escaneo — el usuario puede subir hojas completadas y descargar resultados, pero no puede modificar el diseño.

¿Puedo tener mi token de API en el navegador?

No. El token Bearer debe permanecer en tu servidor. Todas las llamadas de creación, actualización y lectura a la API REST de FormRead deben pasar por tu propio backend. El navegador solo necesita el iframe_token, que está limitado a un único formulario.

¿Cómo recibo los resultados escaneados?

El iframe envía mensajes con window.postMessage. Escucha method="getResults" para recibir el arreglo completo de resultados (una entrada por hoja escaneada) y method="rowResult" para mostrar el progreso por hoja durante el escaneo.

Enlace de Postman

Abrir la colección de Postman

¿Listo para probar FormRead?

¡Cree, lea y procese formularios OMR con facilidad. Comience a extraer datos de sus formularios hoy mismo!

No se requiere tarjeta de crédito para comenzar