API Console
test
Sign in with BES

功能:开通客户

做完后,客户有自己的租户(tenant),能用买下的产品(product),第一位管理员收到登录链接。

环境登录地址带证书调用的接口地址
localhttps://id.local.globalbes.sghttps://id.local.globalbes.sg:19443
testhttps://id.test.globalbes.sghttps://id.test.globalbes.sg:9443
staging待定待定
prod待定待定

Sign in to send requests to see which of these steps are done. Sign in

1. 开通租户和产品
1.1

创建租户

在哪里做:程序代码

BOSS 为客户创建租户,得到 tenant_id。后面启用、开通、建管理员都要填它。

POSTTenant Create

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/tenants
Content-Type: application/json

{
  "request_ref": "create-tenant-topaz",
  "code": "topaz",
  "display_name": "Topaz Construction"
}

返回:

HTTP/1.1 201 Created

{
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "code": "topaz",
  "display_name": "Topaz Construction",
  "status": "provisioning",
  "created_at": "2026-01-01T08:00:00+00:00",
  "mfa_required": false
}
  • code:客户的短代码,唯一,登记后不再改。
  • subdomain:可选,写完整的已登记主机名,不是前缀。
  • administrator_person_id:可选,写一个已有的在用客户,这个人在同一事务里成为第一位租户管理员;新客户不写,在第 2 部分建人。
  • 同一个 request_ref 重发返回同一个租户。

错误:

HTTP 错误码 处理
409 TENANT_CODE_CONFLICT 这个 code 已被占用,换一个。
1.2

启用租户

在哪里做:程序代码

把租户改成 active,得到可进入的租户。客户的人登录后才能选它。

POSTTenant Set Status

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/tenants/7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11/status
Content-Type: application/json

{
  "request_ref": "activate-tenant-topaz",
  "status": "active"
}

返回:

HTTP/1.1 200 OK

{
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "code": "topaz",
  "display_name": "Topaz Construction",
  "status": "active",
  "created_at": "2026-01-01T08:00:00+00:00",
  "mfa_required": false
}
  • suspended 暂停访问,不删除任何东西;decommissioning 不能恢复。
1.3

创建项目

在哪里做:程序代码

项目级产品用:创建项目和它的开通记录,得到 project_id 和待启用的 entitlement_id。启用开通记录时填它们。

POSTProject Mint

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/projects
Content-Type: application/json

{
  "request_ref": "create-project-harbour-tower",
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "display_name": "Harbour Tower",
  "initial_entitlement": {
    "product_id": "b41d9a70-6c2e-4a0f-8e7d-52a9c3f0d614",
    "starts_at": "2026-01-01T00:00:00Z",
    "ends_at": "2027-01-01T00:00:00Z",
    "source": "subscription",
    "source_ref": "order-10027",
    "source_version": 1
  }
}

返回:

HTTP/1.1 201 Created

{
  "project": {
    "project_id": "e2f7a1c4-0d35-4b8e-a6c9-7d18f4b2a903",
    "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
    "display_name": "Harbour Tower",
    "status": "active",
    "version": 0
  },
  "entitlement": {
    "entitlement_id": "9e4b2d7a-1c58-4f36-b0e9-a7d3c5f81b24",
    "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
    "product_id": "b41d9a70-6c2e-4a0f-8e7d-52a9c3f0d614",
    "project_id": "e2f7a1c4-0d35-4b8e-a6c9-7d18f4b2a903",
    "starts_at": "2026-01-01T00:00:00+00:00",
    "ends_at": "2027-01-01T00:00:00+00:00",
    "source": "subscription",
    "source_ref": "order-10027",
    "source_version": 1,
    "seat_limit": null,
    "status": "pending",
    "readiness": "pending",
    "readiness_ref": null,
    "revoked_at": null,
    "version": 0
  }
}
  • 产品的 scope_level 是 tenant 时跳过这一步。
  • 项目和它的第一条开通记录一起创建;project_id 是项目唯一的标识,没有项目代码。
1.4

创建开通记录

在哪里做:程序代码

租户级产品用:给租户开通产品,得到待启用的 entitlement_id。下一步启用时填它。

POSTEntitlement Create

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/entitlements
Content-Type: application/json

{
  "request_ref": "create-topaz-cost-entitlement",
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "entitlement": {
    "product_id": "8a3e5c17-2f94-4b6d-a0c8-5e71d9b3f246",
    "starts_at": "2026-01-01T00:00:00Z",
    "ends_at": "2027-01-01T00:00:00Z",
    "source": "subscription",
    "source_ref": "order-10028",
    "source_version": 1,
    "seat_limit": 50
  }
}

返回:

HTTP/1.1 201 Created

{
  "entitlement_id": "0d5f3b8e-2a69-4c17-8e4b-b6f1d9a3c752",
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "product_id": "8a3e5c17-2f94-4b6d-a0c8-5e71d9b3f246",
  "project_id": null,
  "starts_at": "2026-01-01T00:00:00+00:00",
  "ends_at": "2027-01-01T00:00:00+00:00",
  "source": "subscription",
  "source_ref": "order-10028",
  "source_version": 1,
  "seat_limit": 50,
  "status": "pending",
  "readiness": "pending",
  "readiness_ref": null,
  "revoked_at": null,
  "version": 0
}
  • 项目级产品跳过这一步:project.mint 已建好开通记录。
  • source、source_ref、source_version:这段时间出自 BOSS 里哪份订单或合同。
  • ends_at 必填;同一租户、产品和项目的时段不能重叠。
  • seat_limit 可选,是能分配角色(role)的人数上限。

错误:

HTTP 错误码 处理
409 ENTITLEMENT_PERIOD_OVERLAP 与已有开通记录的时段重叠,调整 starts_at、ends_at。
1.5

启用开通记录

在哪里做:程序代码

启用开通记录,得到生效的开通。客户的人登录后能进入产品。

POSTEntitlement Activate

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/entitlements/9e4b2d7a-1c58-4f36-b0e9-a7d3c5f81b24/activate
Content-Type: application/json

{
  "request_ref": "activate-topaz-bim-entitlement",
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "product_id": "b41d9a70-6c2e-4a0f-8e7d-52a9c3f0d614",
  "project_id": "e2f7a1c4-0d35-4b8e-a6c9-7d18f4b2a903",
  "runtime_ready": true
}

返回:

HTTP/1.1 200 OK

{
  "entitlement_id": "9e4b2d7a-1c58-4f36-b0e9-a7d3c5f81b24",
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "product_id": "b41d9a70-6c2e-4a0f-8e7d-52a9c3f0d614",
  "project_id": "e2f7a1c4-0d35-4b8e-a6c9-7d18f4b2a903",
  "starts_at": "2026-01-01T00:00:00+00:00",
  "ends_at": "2027-01-01T00:00:00+00:00",
  "source": "subscription",
  "source_ref": "order-10027",
  "source_version": 1,
  "seat_limit": null,
  "status": "active",
  "readiness": "ready",
  "readiness_ref": "4bf92f3577b34da6a3ce929d0e0e4736",
  "revoked_at": null,
  "version": 1
}
  • runtime_ready: true 表示产品为这个客户准备的运行环境已就绪。

错误:

HTTP 错误码 处理
409 ENTITLEMENT_NOT_READY 产品为客户准备的环境就绪后,runtime_ready 写 true 再启用。

做完这一部分,手里有:启用的客户租户、项目(项目级产品)和生效的开通记录。客户的人登录后能进入产品。

2. 建客户的第一位管理员
2.1

创建客户管理员

在哪里做:程序代码

在客户租户里创建第一位管理员,得到 person_id。发首次登录链接时填它。

POSTPerson Create

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/people
Content-Type: application/json

{
  "request_ref": "create-person-marcus-lim",
  "tenant_id": "7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11",
  "display_name": "Marcus Lim",
  "channels": [
    {
      "channel_type": "email",
      "channel_identifier": "marcus.lim@topaz.example.com"
    }
  ],
  "role_id": "b7d3f9a1-2e64-4c08-a5b9-d1f7c3e5a862"
}

返回:

HTTP/1.1 201 Created

{
  "person_id": "5a9d3c1b-7e24-4f60-b8a1-c03e6d2f9475",
  "membership_id": "3b8d1f6a-7c24-4e95-a0b3-d5e2f9c84160",
  "person_role_id": "8c4e0a26-f1b7-4d39-a5c2-e7f3b9d1a648",
  "channel_identity_ids": [
    "6b1f4e9a-8c30-4d72-a5e6-f09c3b7d1e24"
  ]
}
  • 一次事务里建好人、地址(未验证)、租户成员(membership)和角色分配,这时还不发任何东西。
  • role_id:Control 产品(code 为 control)的 role.list 里 code 为 tenant-administrator 的角色。

错误:

HTTP 错误码 处理
409 CHANNEL_IDENTITY_BOUND 此人已有 BES 账号:用 membership.create 加进租户。
2.2

发首次登录链接

在哪里做:程序代码

给管理员发首次登录链接,得到 action_id。管理员用链接设好密码后登录;用 action_id 查链接状态。

POSTCredential Issue

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/internal/control/v1/credentials/recoveries
Content-Type: application/json

{
  "request_ref": "first-login-marcus-lim",
  "person_id": "5a9d3c1b-7e24-4f60-b8a1-c03e6d2f9475",
  "purpose": "initial_login",
  "reason": "Topaz Construction onboarding"
}

返回:

HTTP/1.1 201 Created

{
  "action_id": "1f7b3d9e-5c28-4a64-b0e3-c8d2a6f4e193",
  "purpose": "initial_login",
  "expires_at": "2026-01-03T08:00:00+00:00",
  "delivery": "queued"
}
  • Control 通过 Messaging 把链接发到此人的地址;返回里没有链接。
  • 首次登录链接最长 48 小时有效。

错误:

HTTP 错误码 处理
409 CREDENTIAL_CONFLICT 此人已设过密码,不用再发。
2.3

查链接状态

在哪里做:程序代码

用 action_id 查链接状态,得到 pending、completed 等状态。过期了就重发。

GETCredential Action Get

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

GET https://id.test.globalbes.sg:9443/internal/control/v1/credential-actions/1f7b3d9e-5c28-4a64-b0e3-c8d2a6f4e193

返回:

HTTP/1.1 200 OK

{
  "action_id": "1f7b3d9e-5c28-4a64-b0e3-c8d2a6f4e193",
  "status": "pending",
  "expires_at": "2026-01-03T08:00:00+00:00"
}
  • status:pending 还没用,completed 已激活,expired 过期了要重发,revoked 已撤销。

做完这一部分,手里有:管理员的 person_id 和首次登录链接的 action_id;管理员激活后能登录。