FormRead Web API 集成开发人员指南

Oscar Munoz Oscar Munoz · · 5 分钟阅读

FormRead API 如何工作

FormRead API 分为两部分:用于管理表单(创建、更新、删除和存储数据)的 REST API,以及用于表单编辑和读取扫描文档的可嵌入 iframe。仅 API 本身不处理或读取表单——读取完全通过 iframe 完成。

  • REST API(本页): 用于创建、更新、删除和检索表单元数据。API 存储您的表单数据,并返回嵌入 iframe 所需的令牌。
  • iframe(嵌入式查看器): 用于编辑表单模板、上传扫描文档和提取结果(OMR、OCR、BCR)。所有表单读取和数据提取都在 iframe 内完成。

正在寻找服务器到服务器处理?

如果您不需要可视化界面,只想发送图像并以JSON格式获取结果,请查看服务器端处理API。

典型集成工作流程

  1. 使用 Bearer 令牌(从仪表板生成)进行身份验证。
  2. 使用 POST /api/forms 端点创建表单并获取 iframe_token。
  3. 使用 iframe_token 将 iframe 嵌入到您的页面中,以便用户编辑表单和扫描文档。
  4. 监听 iframe 事件(editForm、getResults、rowResult)以接收表单数据和提取结果,然后将它们存储到您的系统中。

身份验证

对于企业用途,通过生成 Bearer Auth token 即可使用 API。

登录 FormRead 仪表盘 并访问 API Token 选项:

FormRead仪表板菜单,突出显示API Tokens选项

创建 API 令牌,以允许第三方服务代表您与我们的应用程序进行身份验证:

创建新的FormRead API令牌,带权限复选框

将生成的令牌复制到安全的地方(它只会显示一次):

生成的 FormRead API Bearer 令牌仅显示一次 - 请安全复制并存储

创建新表单

POST /api/forms

标题

名称 值
Authorization Bearer YOUR_API_TOKEN
Accept application/json

请求

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

回答

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

变量 custom_css 将允许引入 CSS 规则来编辑 FormRead 的外观并添加自定义文本,例如:

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

按 ID 获取表单

GET /api/forms/{form_id}

请求

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

回答

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

编辑表单

在表单 创建 或 获取 之后,可以使用响应中提供的 iframe_token 在 Iframe 中显示它(此令牌会变化,因此请确保在渲染 iframe 之前 获取 您的表单)

还要创建一个脚本,像下面的示例一样监听 iframe 的事件:

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

Iframe URL 参数

参数 描述
lang 设置 lang 变量以显示所需语言的应用程序命令。目前,我们支持英语(en)、法语(fr)、西班牙语(es)、巴西葡萄牙语(pt)或印地语(hi)。
read_only 变量 read_only 可以设置为 1 以禁用表单编辑,或 0 以允许表单编辑

Iframe 事件

当用户点击保存按钮时,将触发 <code class="language-plaintext">editForm</code> 方法,此时您可以访问 2 个变量:

  • formData 变量将包含编码的表单属性,可以使用 更新 来保存对表单所做的更改:
  • schema 变量将让您了解到目前为止创建的字段:
    {
      "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"
      }
    }

    schema 变量仅用于在您要求创建必填区域字段时向用户显示一些警报:

当用户点击下载结果时,将触发 getResults 方法,您将获得 JSON 格式的结果数据,以便您可以将其存储到您的系统中

此外,您可以使用 rowResult 方法逐行获取结果,该方法将在每次处理页面时触发

更新表单

PUT /api/forms/{form_id}

请求

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

回答

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

删除表单

DELETE /api/forms/{form_id}

请求

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

回答

1

完整示例:嵌入评分工作流

这是一个端到端示例,展示了教师如何设计表单、扫描试卷,并将批改结果推送到您自己的后端——所有这些都可以在嵌入 FormRead iframe 的单个页面中完成。

场景

教师打开您的应用,设计一张“数学101 - 期中考试”答题卡,打印出来,扫描已填写的试卷,然后点击“下载结果”。您的页面监听 iframe 事件,保存布局,并将批改后的答案发布到您的评分系统。

第1步 - 从您的服务器创建表单

在您的后端,为教师创建一个表单。您会得到一个 id 和一个 iframe_token - 这些是您将在下一步中传递给 iframe URL 的内容。

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

将 id 和 iframe_token 保存到您自己数据库中教师的记录中。您将在第2步中使用它们来渲染可编辑的 iframe。

第2步 - 以可编辑模式打开 iframe

您的后端渲染一个包含 FormRead iframe 的页面,其中 read_only=0,这样教师可以在答题卡上绘制 OMR 气泡、OCR 区域和条形码。当他们在 iframe 内点击“保存”时,editForm 事件触发 - 浏览器将原始 formData 转发到您自己的后端。浏览器永远不会直接调用 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>

第3步 - 从您的后端持久化布局

您的后端接收 formData 字符串,并使用您的 Bearer 令牌(永远不会离开服务器)通过 PUT 将其转发给 FormRead。这样就能永久保存表单配置,以便以后重用同一表单来扫描试卷。

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

iframe_token 会轮换

每次更新表单都会返回一个新的 iframe_token。始终在渲染 iframe 之前从您的后端获取最新的令牌 - 不要硬编码或长期缓存它。

第4步 - 获取当前的 iframe_token

之后,当教师准备扫描试卷时,您的后端通过 id 读取表单以获取最新的 iframe_token。

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

第5步 - 以只读模式重新打开 iframe 进行扫描

再次渲染 iframe - 这次在 URL 末尾加上 read_only=1。教师无法再编辑布局,只能上传扫描件。浏览器将 rowResult(每张表的进度)和 getResults(最终下载)转发到您的后端。

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

第6步 - 在您的后端处理结果

getResults 事件会传递一个数组,每个已处理的考试对应一个条目。键遵循模式 {AreaType}-{AreaIndex}[-{QuestionIndex}]。以下是浏览器将发布到您的 /api/grades/bulk 端点(endpoint)的内容:

[
  {
    "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"
  }
]

将您的令牌保存在服务器上

切勿在面向浏览器的代码中暴露您的 Bearer token。对 FormRead API 的所有创建/更新/读取调用都应通过您自己的后端进行——浏览器只会看到 iframe_token,该 token 仅限于单个表单。

常见问题解答

什么是 FormRead Iframe 集成 API?

它是一个 REST API 外加一个可嵌入的 iframe。您的后端通过 REST 端点管理表单;iframe 在您的 Web 应用内渲染,用户无需离开您的界面即可设计表单、上传扫描件和查看结果。

iframe_token 会过期或更改吗?

iframe_token 在表单每次更新时都会重新生成。在渲染 iframe 之前,务必从您的后端通过 FormRead REST API(GET /api/forms/{id})获取最新值——不要长期缓存它。

read_only=0 和 read_only=1 有什么区别?

read_only=0 以可编辑模式打开 iframe,以便用户设计表单(放置 OMR 气泡、OCR、条码区域)。read_only=1 仅以扫描模式打开——用户可以上传已填写的表格并下载结果,但不能更改布局。

我可以将 API token 保存在浏览器中吗?

不可以。Bearer token 必须保存在您的服务器上。对 FormRead REST API 的所有创建、更新和读取调用都应通过您自己的后端进行代理。浏览器只需要 iframe_token,该 token 仅限于单个表单。

如何接收扫描结果?

iframe 通过 window.postMessage 发布消息。监听 method="getResults" 以接收完整的结果数组(每张扫描表对应一个条目),并监听 method="rowResult" 以在扫描时显示每张表的进度。

Postman 集合链接

打开 Postman 集合

停止手动评分表单。

立即让FormRead发挥作用:创建您的表单,扫描您的第一张表,几分钟内获得结构化结果。

立即开始——无需信用卡