一个请求,完成一次 人工确认
通过 API 发起请求,Ask4Me 把交互链接推送到通知渠道。你在手机或浏览器里点按钮、输入文字或提交表单,原始 HTTP 长连接拿到最终结果。
curl -sS --max-time 120 \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "Ask4Me Demo",
"body": "请点一个按钮回复。",
"mcd": ":::buttons\n- [OK](ok)\n- [Later](later)\n:::"
}'
{
"request_id": "req_xxx",
"last_event_type": "user.submitted",
"data": { "action": "ok", "text": "" },
"last_event_id": "evt_xxx"
}
快速使用
nonStream 是默认模式:不带 stream=true 时,/v1/ask 会一直等待用户提交或请求过期,然后一次性返回 JSON。
mcd 或 jsonforms.schema,这样交互页才有按钮、输入框或表单可提交。
POST 裸请求
curl -sS --max-time 120 \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "Ask4Me Demo",
"body": "请选择一个动作。",
"mcd": ":::buttons\n- [OK](ok)\n- [Later](later)\n:::",
"expires_in_seconds": 600
}'
GET 裸请求
如果环境不方便设置 Authorization header,可以用 GET 并在 URL 上带 key。
curl -sS --max-time 120 -G '' \
--data-urlencode 'key=change-me' \
--data-urlencode 'title=Ask4Me Demo' \
--data-urlencode 'body=请点一个按钮回复。' \
--data-urlencode $'mcd=:::buttons\n- [OK](ok)\n- [Later](later)\n:::'
API 用法
续接等待
当客户端超时后,可以用同一个 request_id 再请求一次,继续等待或取回终态结果。
curl -sS --max-time 40 -G '' \
--data-urlencode 'key=change-me' \
--data-urlencode 'request_id=req_xxx'
SSE 备用模式
需要实时拿到 request.created 和后续事件流时,使用 stream=true。
curl -N -sS \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "Ask4Me",
"body": "Please respond.",
"mcd": ":::buttons\n- [OK](ok)\n:::"
}'
SSE 输出格式为 data: <Event JSON>\n\n,结束标记为 data: [DONE]\n\n。响应头会带 X-Ask4Me-Request-Id。
终态事件
| 事件 | 含义 |
|---|---|
user.submitted | 用户点击按钮、提交输入或提交表单 |
request.expired | 请求到期仍未提交 |
notify.failed | 通知发送失败,通常是通知渠道不可用或返回错误 |
MCD 语法
MCD 是交互控件描述。它会在交互页里渲染按钮和输入框。
Buttons 块
:::buttons
- [OK](ok)
- [Later](later)
:::
Input 行
:::input name="note" label="补充说明" submit="提交"
:::
按钮结果
用户点击按钮后,提交值会出现在终态结果的 data.action。
输入结果
用户提交输入后,文本会出现在终态结果的 data.text。
混合使用
按钮和输入框可以同时出现;任一提交都会完成这次交互。
JSON Forms
需要更复杂的表单时,POST JSON 里提供 jsonforms.schema。当提供 jsonforms.schema 时,交互页会渲染表单并忽略 mcd。
curl -sS --max-time 120 \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "JSON Forms Demo",
"body": "请填写表单。",
"jsonforms": {
"schema": {
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
},
"uischema": {
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/name" },
{ "type": "Control", "scope": "#/properties/age" }
]
},
"data": { "age": 18 },
"submit_label": "提交"
},
"expires_in_seconds": 600
}'
表单提交后,终态事件 user.submitted 的 data 会包含 payload。
{
"action": "",
"text": "",
"payload": { "name": "Alice", "age": 18 }
}
扩展用法
可折叠分组
在 Group 的 options 中设置 collapsible: true,可把一组字段放进折叠区。
长文本说明
Label 支持 maxHeight、collapsible 和 markdown: true,适合展示长说明。
只读长文本
Control 设置 readonlyBlock: true 后,可把字符串字段显示为不可编辑的滚动块。
JavaScript SDK 与 CLI
JavaScript SDK
SDK 默认使用 SSE 模式,适合在程序里实时消费事件。
npm i ask4me-sdk
import { ask } from "ask4me-sdk";
const endpoint = "";
const apiKey = "change-me";
const { requestId, result } = await ask({
endpoint,
apiKey,
payload: {
title: "Ask4Me Demo",
body: "请随便点一个按钮或回一段话。",
mcd: ":::buttons\n- [OK](ok)\n- [Later](later)\n:::"
},
onEvent: (ev) => process.stdout.write(`${JSON.stringify(ev)}\n`)
});
console.log("request_id:", requestId);
console.log("final:", result);
CLI
npm i -g ask4me-cli
ask4me-cli -h -k change-me \
--title 'Ask4Me' --body '请回复确认。'
One request,
one human decision
Create a request through the API. Ask4Me sends an interaction link to your notification channel. A human clicks a button, enters text, or submits a form, and the original HTTP long-poll receives the final result.
curl -sS --max-time 120 \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "Ask4Me Demo",
"body": "Click a button to respond.",
"mcd": ":::buttons\n- [OK](ok)\n- [Later](later)\n:::"
}'
{
"request_id": "req_xxx",
"last_event_type": "user.submitted",
"data": { "action": "ok", "text": "" },
"last_event_id": "evt_xxx"
}
Quick Use
nonStream is the default mode. Without stream=true, /v1/ask waits until the user submits or the request expires, then returns one JSON response.
mcd or jsonforms.schema so the interaction page has a button, input, or form to submit.
POST request
curl -sS --max-time 120 \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "Ask4Me Demo",
"body": "Choose an action.",
"mcd": ":::buttons\n- [OK](ok)\n- [Later](later)\n:::",
"expires_in_seconds": 600
}'
GET request
For environments where setting Authorization headers is difficult, pass key as a query parameter.
curl -sS --max-time 120 -G '' \
--data-urlencode 'key=change-me' \
--data-urlencode 'title=Ask4Me Demo' \
--data-urlencode 'body=Click a button to respond.' \
--data-urlencode $'mcd=:::buttons\n- [OK](ok)\n- [Later](later)\n:::'
API Usage
Resume waiting
If your client times out, call again with the same request_id to keep waiting or retrieve the terminal result.
curl -sS --max-time 40 -G '' \
--data-urlencode 'key=change-me' \
--data-urlencode 'request_id=req_xxx'
SSE mode
Use stream=true when you need real-time events, including request.created and the interaction URL.
curl -N -sS \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "Ask4Me",
"body": "Please respond.",
"mcd": ":::buttons\n- [OK](ok)\n:::"
}'
SSE output is data: <Event JSON>\n\n, ending with data: [DONE]\n\n. The response includes X-Ask4Me-Request-Id.
Terminal event types
| Event | Meaning |
|---|---|
user.submitted | User clicked a button, submitted input, or submitted a form |
request.expired | The request expired without user interaction |
notify.failed | Notification delivery failed because the notification channel was unavailable or returned an error |
MCD Syntax
MCD is the interaction control description. The interaction page renders buttons and inputs from it.
Buttons block
:::buttons
- [OK](ok)
- [Later](later)
:::
Input line
:::input name="note" label="Note" submit="Submit"
:::
Button result
When a user clicks a button, its value appears in the final result as data.action.
Input result
When a user submits text, the text appears in the final result as data.text.
Combined controls
Buttons and inputs can appear together. Either submission completes the interaction.
JSON Forms
For richer interactions, provide jsonforms.schema in a POST JSON body. When present, the interaction page renders the form and ignores mcd.
curl -sS --max-time 120 \
-X POST '' \
-H 'Authorization: Bearer change-me' \
-H 'Content-Type: application/json' \
-d '{
"title": "JSON Forms Demo",
"body": "Please fill the form.",
"jsonforms": {
"schema": {
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
},
"uischema": {
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/name" },
{ "type": "Control", "scope": "#/properties/age" }
]
},
"data": { "age": 18 },
"submit_label": "Submit"
},
"expires_in_seconds": 600
}'
After form submission, user.submitted includes payload in data.
{
"action": "",
"text": "",
"payload": { "name": "Alice", "age": 18 }
}
Extensions
Collapsible group
Set collapsible: true in Group options to put fields inside a collapsible section.
Long label
Label supports maxHeight, collapsible, and markdown: true for long instructions.
Read-only block
Set readonlyBlock: true on a Control to render a string field as a non-editable scrolling block.
JavaScript SDK and CLI
JavaScript SDK
The SDK uses SSE mode by default and is useful when a program needs to consume events in real time.
npm i ask4me-sdk
import { ask } from "ask4me-sdk";
const endpoint = "";
const apiKey = "change-me";
const { requestId, result } = await ask({
endpoint,
apiKey,
payload: {
title: "Ask4Me Demo",
body: "Click a button or type a reply.",
mcd: ":::buttons\n- [OK](ok)\n- [Later](later)\n:::"
},
onEvent: (ev) => process.stdout.write(`${JSON.stringify(ev)}\n`)
});
console.log("request_id:", requestId);
console.log("final:", result);
CLI
npm i -g ask4me-cli
ask4me-cli -h -k change-me \
--title 'Ask4Me' --body 'Please respond.'