Tally
2026-03-29
新闻来源:网淘吧
围观:19
电脑广告
手机广告
Tally
通过托管的OAuth认证访问Tally API。管理您Tally账户的表单、提交、工作区和网络钩子。
快速开始
# List your forms
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/tally/forms')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('User-Agent', 'Maton/1.0')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
基础URL
https://gateway.maton.ai/tally/{native-api-path}
将{native-api-path}替换为实际的Tally API端点路径。网关将请求代理到api.tally.so并自动注入您的OAuth令牌。
认证
所有请求都需要在Authorization头部中包含Maton API密钥,以及User Agent头部:
Authorization: Bearer $MATON_API_KEY
User-Agent: Maton/1.0
环境变量:将您的API密钥设置为MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
获取您的API密钥
复制您的API密钥
管理您的Tally OAuth连接,请访问https://ctrl.maton.ai。
列出连接
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=tally&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
创建连接
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'tally'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
获取连接
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
响应:
{
"connection": {
"connection_id": "cd54e2b0-f1d0-435e-a97d-f2d6a5c474bf",
"status": "ACTIVE",
"creation_time": "2026-02-07T21:00:31.222600Z",
"last_updated_time": "2026-02-07T21:00:37.821240Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "tally",
"metadata": {}
}
}
在浏览器中打开返回的网址以完成OAuth授权。
删除连接
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
指定连接
如果您有多个Tally连接,请使用Maton-Connection请求头指定要使用的连接:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/tally/forms')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', 'cd54e2b0-f1d0-435e-a97d-f2d6a5c474bf')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
如果省略,网关将使用默认(最早创建的)活动连接。
API参考
用户
获取当前用户
GET /tally/users/me
响应:
{
"id": "w2lBkb",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"organizationId": "n0Ze8Q",
"subscriptionPlan": "FREE",
"createdAt": "2026-02-07T20:58:54.000Z",
"updatedAt": "2026-02-07T22:50:35.000Z"
}
表单
列出表单
GET /tally/forms
查询参数:
页码- 页码(默认值:1)限制- 每页项目数(默认值:50)
响应:
{
"items": [
{
"id": "GxdRaQ",
"name": "Contact Form",
"workspaceId": "3jW9Q1",
"organizationId": "n0Ze8Q",
"status": "PUBLISHED",
"hasDraftBlocks": false,
"numberOfSubmissions": 42,
"createdAt": "2026-02-09T08:36:00.000Z",
"updatedAt": "2026-02-09T08:36:17.000Z",
"isClosed": false
}
],
"page": 1,
"limit": 50,
"total": 1,
"hasMore": false
}
获取表单
GET /tally/forms/{formId}
响应:
{
"id": "GxdRaQ",
"name": "Contact Form",
"workspaceId": "3jW9Q1",
"status": "PUBLISHED",
"blocks": [
{
"uuid": "11111111-1111-1111-1111-111111111111",
"type": "FORM_TITLE",
"groupUuid": "22222222-2222-2222-2222-222222222222",
"groupType": "FORM_TITLE",
"payload": {}
},
{
"uuid": "33333333-3333-3333-3333-333333333333",
"type": "INPUT_TEXT",
"groupUuid": "44444444-4444-4444-4444-444444444444",
"groupType": "INPUT_TEXT",
"payload": {}
}
],
"settings": null
}
创建表单
POST /tally/forms
Content-Type: application/json
{
"status": "DRAFT",
"workspaceId": "3jW9Q1",
"blocks": [
{
"type": "FORM_TITLE",
"uuid": "11111111-1111-1111-1111-111111111111",
"groupUuid": "22222222-2222-2222-2222-222222222222",
"groupType": "FORM_TITLE",
"title": "My Form",
"payload": {}
},
{
"type": "INPUT_TEXT",
"uuid": "33333333-3333-3333-3333-333333333333",
"groupUuid": "44444444-4444-4444-4444-444444444444",
"groupType": "INPUT_TEXT",
"title": "Your name",
"payload": {}
}
]
}
区块类型:
表单标题- 表单标题区块输入_文本- 单行文本输入输入_邮箱- 邮箱输入输入_数字- 数字输入输入_电话号码- 电话号码输入输入_日期- 日期选择器输入_时间- 时间选择器输入_链接- 网址输入文本域- 多行文本输入多项选择- 单选按钮复选框- 复选框组下拉菜单- 下拉选择线性量表- 量表评分评分- 星级评分文件上传- 文件上传字段签名- 签名字段支付- 支付字段隐藏字段- 隐藏字段
注意:区块uuid和groupUuid必须是有效的UUID(GUID)。
更新表单
PATCH /tally/forms/{formId}
Content-Type: application/json
{
"name": "Updated Form Name",
"status": "PUBLISHED"
}
状态值:
草稿- 表单为草稿状态已发布- 表单已上线
删除表单
DELETE /tally/forms/{formId}
将表单移至回收站。
表单问题
列出问题
GET /tally/forms/{formId}/questions
响应:
{
"questions": [
{
"uuid": "33333333-3333-3333-3333-333333333333",
"type": "INPUT_TEXT",
"title": "Your name"
}
],
"hasResponses": true
}
表单提交
列出提交
GET /tally/forms/{formId}/submissions
查询参数:
页码- 页码(默认值:1)限制- 每页项目数(默认值:50)开始日期- 按开始日期筛选(ISO 8601格式)结束日期- 按结束日期筛选(ISO 8601格式)后续ID- 获取此ID之后的提交(用于游标分页)
响应:
{
"page": 1,
"limit": 50,
"hasMore": false,
"totalNumberOfSubmissionsPerFilter": {
"all": 42,
"completed": 40,
"partial": 2
},
"questions": [
{
"uuid": "33333333-3333-3333-3333-333333333333",
"type": "INPUT_TEXT",
"title": "Your name"
}
],
"submissions": [
{
"id": "sub123",
"respondentId": "resp456",
"formId": "GxdRaQ",
"createdAt": "2026-02-09T10:00:00.000Z",
"isCompleted": true,
"responses": [
{
"questionId": "33333333-3333-3333-3333-333333333333",
"value": "John Doe"
}
]
}
]
}
获取提交
GET /tally/forms/{formId}/submissions/{submissionId}
删除提交
DELETE /tally/forms/{formId}/submissions/{submissionId}
工作空间
列出工作空间
GET /tally/workspaces
响应:
{
"items": [
{
"id": "3jW9Q1",
"name": "My Workspace",
"createdByUserId": "w2lBkb",
"createdAt": "2026-02-09T08:35:53.000Z",
"updatedAt": "2026-02-09T08:35:53.000Z"
}
],
"page": 1,
"limit": 50,
"total": 1,
"hasMore": false
}
获取工作空间
GET /tally/workspaces/{workspaceId}
响应:
{
"id": "3jW9Q1",
"name": "My Workspace",
"createdByUserId": "w2lBkb",
"createdAt": "2026-02-09T08:35:53.000Z",
"members": [
{
"id": "w2lBkb",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com"
}
]
}
创建工作空间
POST /tally/workspaces
Content-Type: application/json
{
"name": "New Workspace"
}
注意:创建工作空间需要专业版订阅。
更新工作空间
PATCH /tally/workspaces/{workspaceId}
Content-Type: application/json
{
"name": "Updated Workspace Name"
}
删除工作空间
DELETE /tally/workspaces/{workspaceId}
将工作空间及其所有表单移至回收站。
组织用户
列出用户
GET /tally/organizations/{organizationId}/users
响应:
[
{
"id": "w2lBkb",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"createdAt": "2026-02-07T20:58:54.000Z"
}
]
移除用户
DELETE /tally/organizations/{organizationId}/users/{userId}
组织邀请
列出邀请
GET /tally/organizations/{organizationId}/invites
创建邀请
POST /tally/organizations/{organizationId}/invites
Content-Type: application/json
{
"email": "newuser@example.com",
"workspaceIds": ["3jW9Q1"]
}
取消邀请
DELETE /tally/organizations/{organizationId}/invites/{inviteId}
Webhooks
列出Webhooks
GET /tally/webhooks
注意:列出Webhooks可能需要特定权限。
创建 Webhook
POST /tally/webhooks
Content-Type: application/json
{
"formId": "GxdRaQ",
"url": "https://your-endpoint.com/webhook",
"eventTypes": ["FORM_RESPONSE"]
}
Webhook 事件类型:
表单响应- 当提交新的表单响应时触发
更新 Webhook
PATCH /tally/webhooks/{webhookId}
Content-Type: application/json
{
"url": "https://new-endpoint.com/webhook"
}
删除 Webhook
DELETE /tally/webhooks/{webhookId}
列出 Webhook 事件
GET /tally/webhooks/{webhookId}/events
重试 Webhook 事件
POST /tally/webhooks/{webhookId}/events/{eventId}
分页
Tally 使用基于页面的分页:
GET /tally/forms?page=1&limit=50
响应包含分页信息:
{
"items": [...],
"page": 1,
"limit": 50,
"total": 100,
"hasMore": true
}
对于提交,也可以使用基于游标的分页,通过afterId参数实现。
代码示例
JavaScript
const response = await fetch(
'https://gateway.maton.ai/tally/forms',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
'User-Agent': 'Maton/1.0'
}
}
);
const data = await response.json();
console.log(data.items);
Python
import os
import requests
response = requests.get(
'https://gateway.maton.ai/tally/forms',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'User-Agent': 'Maton/1.0'
}
)
data = response.json()
print(data['items'])
创建表单并获取提交
import os
import requests
import uuid
headers = {
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'User-Agent': 'Maton/1.0'
}
# Create a simple form
form_data = {
'status': 'DRAFT',
'blocks': [
{
'type': 'FORM_TITLE',
'uuid': str(uuid.uuid4()),
'groupUuid': str(uuid.uuid4()),
'groupType': 'FORM_TITLE',
'title': 'Contact Form',
'payload': {}
},
{
'type': 'INPUT_EMAIL',
'uuid': str(uuid.uuid4()),
'groupUuid': str(uuid.uuid4()),
'groupType': 'INPUT_EMAIL',
'title': 'Your email',
'payload': {}
}
]
}
response = requests.post(
'https://gateway.maton.ai/tally/forms',
headers=headers,
json=form_data
)
form = response.json()
print(f"Created form: {form['id']}")
# Get submissions for a form
response = requests.get(
f'https://gateway.maton.ai/tally/forms/{form["id"]}/submissions',
headers=headers
)
submissions = response.json()
print(f"Total submissions: {submissions['totalNumberOfSubmissionsPerFilter']['all']}")
注意事项
- 表单和工作区 ID 是简短的字母数字字符串(例如,
GxdRaQ) - 区块
uuid并且groupUuid字段必须是有效的UUID(GUID) - 创建工作空间需要专业版订阅
- API处于公开测试阶段,可能会发生变化
- 频率限制:每分钟100个请求
- 使用webhook而非轮询来获取实时提交通知
- 重要提示:当通过管道将curl输出传递给
jq或其他命令时,某些shell环境中像$MATON_API_KEY这样的环境变量可能无法正确展开
错误处理
| 状态码 | 含义 |
|---|---|
| 400 | 缺少Tally连接或验证错误 |
| 401 | 无效或缺少Maton API密钥 |
| 403 | 权限不足 |
| 404 | 资源未找到 |
| 429 | 请求频率受限 (100次/分钟) |
| 4xx/5xx 错误 | 来自 Tally API 的透传错误 |
故障排除:API 密钥问题
- 请检查
MATON_API_KEY环境变量是否已设置:
echo $MATON_API_KEY
- 通过列出连接来验证 API 密钥是否有效:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
故障排除:无效的应用名称
- 请确保您的 URL 路径以
tally开头。例如:
- 正确示例:
https://gateway.maton.ai/tally/forms - 错误示例:
https://gateway.maton.ai/forms
资源
文章底部电脑广告
手机广告位-内容正文底部


微信扫一扫,打赏作者吧~