Schemas、Destinations 与 Mappings
说明 Numora 对外 API 开发者预览版中的 destination 模型、schema catalog、mapping 资源与下游回写规则。
范围
本页定义 Numora 在对外 API 中如何建模下游系统与字段映射。
内容包括:
- 作为映射来源侧的 schema catalog
- 表示下游系统连接的 destination 资源
- 把提取结果转换为下游 payload 的 mapping 资源
- 基于当前 app 实现总结出的校验与上线建议
为什么对外 API 使用 destination
对外 API 应暴露稳定的 destination 模型,而不是直接泄露 provider 内部表名。
这点很重要,因为你当前 app 的实现仍然明显偏向 Dynamics 365 / Dataverse:
- connection 以 provider-specific integration connection 的形式存储
- 内部 mapping 按
targetTable分行持久化 - 当前真正启用的 provider 是
dynamics365
因此,对外契约应比当前存储模型更抽象,这样未来接入 Salesforce、HubSpot、Excel 等 provider 时,不需要推翻资源设计。
Schema Catalog
GET /v1/schemas
首批公开 schema 为:
invoice_v2receipt_v1contract_v1
建议响应:
{
"data": [
{
"id": "invoice_v2",
"label": "Invoice",
"status": "active"
},
{
"id": "receipt_v1",
"label": "Receipt",
"status": "active"
},
{
"id": "contract_v1",
"label": "Contract",
"status": "active"
}
]
}这些 schema 标识符就是下游映射的来源侧模型。
Destination 资源
GET /v1/destinations
POST /v1/destinations
POST /v1/destinations/{id}/test
一个 destination 表示一个下游系统连接,而不是该系统中的某一个具体对象。
建议资源结构:
{
"id": "dst_01jpx4m4j2j6x9j2k6r1m9aa0v",
"provider": "dynamics365",
"display_name": "Finance Dataverse",
"status": "active",
"has_credentials": true,
"created_at": "2026-03-21T15:00:00.000Z",
"updated_at": "2026-03-21T15:05:00.000Z"
}建议约定:
- 凭据字段只写不读
- secret 创建或更新后不再回传
- destination
status至少支持active和paused POST /v1/destinations/{id}/test应在正式使用前校验凭据与下游连通性
Destination 创建示例
对外 API 应保持 provider-neutral,同时允许在请求体里带 provider-specific 配置。
请求示例:
{
"provider": "dynamics365",
"display_name": "Finance Dataverse",
"config": {
"organization_url": "https://contoso.crm.dynamics.com",
"tenant_id": "11111111-2222-3333-4444-555555555555",
"client_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"client_secret": "nr_test_123"
}
}响应示例:
{
"id": "dst_01jpx4m4j2j6x9j2k6r1m9aa0v",
"provider": "dynamics365",
"display_name": "Finance Dataverse",
"status": "active",
"has_credentials": true
}Destination 测试示例
对于当前已启用的 provider,现有 app 已经会校验:
- access token 获取是否成功
- Dataverse service root 是否可达
建议测试响应:
{
"ok": true,
"provider": "dynamics365",
"organization_origin": "https://contoso.crm.dynamics.com",
"reachable": true,
"probe_status": 200
}Mapping 资源
GET /v1/mappings/{schema}/{destination}
PUT /v1/mappings/{schema}/{destination}
一个公开 mapping 资源应聚合“同一个 source schema 写入同一个 destination”所需的全部 target blocks。
这比当前内部按 targetTable 分多行存储的方式更适合作为对外契约,因为外部开发者更需要看到一份完整 mapping 文档,而不是若干数据库行。
建议响应:
{
"schema": "invoice_v2",
"destination_id": "dst_01jpx4m4j2j6x9j2k6r1m9aa0v",
"targets": [
{
"target_object": "vendor",
"provider_object": "account",
"source_path": "$",
"field_mappings": [
{
"source": "vendor_name",
"mode": "field",
"target_field": "account.name"
},
{
"source": "invoice_total",
"mode": "field",
"target_field": "new_totalamount"
}
],
"rules": {
"push_on_reviewed": true,
"require_approval": false
}
}
],
"updated_at": "2026-03-21T15:18:00.000Z"
}字段映射模型
每一条 mapping row 建议支持:
sourcemodeexpressiontarget_fieldrequired
建议语义:
mode = field表示值直接来自结构化提取字段mode = custom表示值由受控表达式计算得到source_path = "$"表示从文档级结果读取source_path = "$.lineItems[*]"表示对提取出来的行项目逐条迭代
对于行项目映射,一个 target block 可能还需要:
parent_target_objectparent_lookup_field
这两个字段用于把子项 payload 绑定回同一次 push 中先创建的父对象。
校验规则
公开契约应在 mapping 激活前完成校验。
建议检查项:
- 请求的 schema 是否受支持
- target object 是否在 destination scope 内
- target fields 是否对该 destination 可访问
- 文档级 mapping 是否覆盖了必要来源字段
- 重复 target field 应作为 warning 返回
- 空 mapping 定义应被拒绝
你当前 app 内部已经实现了其中的大部分校验能力,例如 target-table scope、required source rows 和 duplicate target-field warning。
当前可用性
app 里的 provider registry 当前状态是:
dynamics365:activesalesforce:plannedhubspot:plannedexcel:planned
因此,第一版对外 destination 文档应把 dynamics365 写成当前可用 provider,其他 provider 只作为后续扩展能力描述,而不是已可用集成。
推荐上线顺序
推荐顺序:
- 先发布
GET /v1/schemas - 再发布
dynamics365的 destination create/list/test - 再发布
GET/PUT /v1/mappings/{schema}/{destination} - 然后补 mapping validate/test endpoint
- 最后才扩展到更多 provider