OpenAPI · REST 參考
REST primitives for every WIDTH OpenAPI call — request envelope, signing, errors, idempotency, configuration, and file upload. Workflow endpoints (KYC, KYB, transactions, monitoring) are documented in their own pages.
請求結構
所有 OpenAPI 呼叫使用相同的請求結構。端點名稱、該端點適用的 API 版本、金鑰和簽章透過查詢參數傳遞;請求正文使用 JSON。
POST {base_url}?api={apiName}&apiVersion={apiVersion}&apiKey={apiKey}&sign={sign}
Content-Type: application/json
x-domain: {domainId}
{
...request body...
}
| Parameter | Where | Description |
|---|---|---|
api | query | API name, e.g. workflow.apply.submit |
apiVersion | query | 按具體端點指定的版本。workflow.apply.submit 使用 2.0.0;請勿假設所有端點使用同一預設版本。 |
apiKey | query | Your public key (prefixed ak_) |
sign | query | HMAC-SHA256 hex string of the body, keyed by apiSecret |
x-domain | header | Business unit (domain) identifier |
提交工作流
端點:workflow.apply.submit(POST)。用於啟動目前已發布工作流的一次執行。使用 apiVersion=2.0.0 時,可選傳入 workflowId,以明確指定要執行的已發布工作流。如果 workflowId 為空或未傳入,WIDTH 將繼續按照 eventType + source 自動路由請求。
API 版本行為
| apiVersion | 行為 |
|---|---|
1.0.0 | 按照 eventType + source 自動路由。 |
2.0.0 | 包含 1.0.0 的全部行為,並支援可選的 workflowId,用於明確指定已發布工作流。如果 workflowId 為空或未傳入,則其路由行為與 1.0.0 完全一致。建議使用。 |
請求正文
{
"eventType": "{eventType}",
"source": "API",
"data": {
"customerId": "demo-customer-001"
},
"workflowId": "{publishedWorkflowId}"
}
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
eventType | string | 是 | 用於啟動或路由工作流的事件類型。 |
source | string | 是 | 請求來源。伺服器端整合使用 API。 |
data | object | 是 | 工作流業務資料。請包含工作流入口事件所要求的欄位。 |
workflowId | string | 否 | 僅適用於 2.0.0。用於指定要執行的已發布工作流。如果為空或未傳入,WIDTH 將按照 eventType + source 自動路由。 |
workflowId 傳入。響應格式
All responses share the same envelope:
{
"apiCode": 200,
"apiMsg": "OK",
"data": { ... }
}
Errors use the same shape with a non-200 apiCode and a null data field:
{
"apiCode": 999001,
"apiMsg": "SIGN_ERROR",
"data": null
}
Error codes
| Code | Message | Description | Action |
|---|---|---|---|
200 | OK | Success | — |
999000 | GATEWAY_ERROR | General gateway error | Contact support |
999001 | SIGN_ERROR | Signature verification failed | See authentication |
999301 | API_INVALID_REQUEST | Malformed request | Check request body |
999302 | API_NOT_FOUND | API not found | Verify api parameter |
999303 | API_NON_AUTHORIZED | Unauthorized | Check tenant permissions |
999401 | SERVICE_TIME_OUT | Backend timeout | Retry with backoff |
999402 | SERVICE_INVOKE_ERROR | Invocation failed | Retry or contact support |
身份驗證
Every request is signed with HMAC-SHA256 over the raw request body. The signature is sent as the sign query parameter.
sign = HmacSHA256(apiSecret, requestBody)
Both the key and body use UTF-8 encoding. The result is a 64-character lowercase hexadecimal string.
import hmac, hashlib
sign = hmac.new(
api_secret.encode('utf-8'),
request_body.encode('utf-8'),
hashlib.sha256
).hexdigest()
const crypto = require('crypto');
const sign = crypto
.createHmac('sha256', apiSecret)
.update(requestBody, 'utf8')
.digest('hex');
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiSecret.getBytes("UTF-8"), "HmacSHA256"));
byte[] hash = mac.doFinal(requestBody.getBytes("UTF-8"));
String sign = HexFormat.of().formatHex(hash);
apiSecret in client code. Signing must happen on a server you control. The SDKs use a session-scoped sdkToken instead.冪等性
All node-data submission APIs are idempotent by callbackKey. Submitting the same callbackKey multiple times is safe — the workflow advances only once.
Use idempotency for safe retries on network failure or timeouts. Persist your callbackKey with the original request and reuse it on retry.
互動模式
用戶端:鏈式流程
前端根據每次提交回應傳回的 nextStep 物件推進。每個步驟會說明下一個節點及介面需要收集的資料。
伺服器端:狀態查詢
伺服器對伺服器的流程在自動處理期間應每 3–5 秒查詢一次 workflow.execution.status。當 caseStatus 為 UNASSIGNED、UNDER_REVIEW 或 RETURNED 時,將間隔放寬至 30–60 秒。執行達到終止狀態後停止。請參閱 KYC 狀態與審核結果及執行狀態。
Configuration
Endpoint: prepare.avira.config (POST). Returns reference data used by workflow nodes — country lists, document types, industry codes.
| Key | Description | Used by |
|---|---|---|
particular | Personal / corporate field definitions | Particular nodes |
required-form | Form templates with validation rules | Required Forms nodes |
avira_countries | Country list (ISO codes + names) | Nationality, residence |
avira_document_master | Supported documents per country | OCR & upload |
avira_ssic | Industry classification codes | Industry field |
avira_ssoc | Occupation classification codes | Occupation field |
avira_phone_code | Country phone codes | Phone verification |
avira_entity_types | Corporate entity types | KYB particular |
File upload
Two-step upload: request a short-lived token, then POST the file.
Step 1 — get upload token
Endpoint: storage.upload.token (POST). Body: {}.
{
"apiCode": 200,
"data": {
"uploadToken": "a1b2c3d4...",
"expiresIn": 900
}
}
Tokens are valid for 15 minutes.
Step 2 — upload the file
Multipart:
curl -X POST "${STORAGE_URL}/api/v1/upload/file" \
-F "uploadToken=a1b2c3d4..." \
-F "file=@passport_front.jpg"
Base64 (for in-memory images):
curl -X POST "${STORAGE_URL}/api/v1/upload" \
-H "Content-Type: application/json" \
-d '{
"uploadToken": "a1b2c3d4...",
"image": "data:image/jpeg;base64,/9j/4AAQ...",
"filename": "passport_front.jpg"
}'
Supported types: PNG, JPG, JPEG, GIF, WEBP, TIFF, PDF. Max size: 20 MB.
Error handling & retry strategy
| Scenario | Recommendation |
|---|---|
| Signature error (403) | Do not retry; fix signing implementation |
| Server error (500) | Retry 3× with exponential backoff (1s → 2s → 4s) |
| Status polling | Every 2–5 seconds, max 30 minutes |
| Upload token 401 | Get a new token, retry once |
| OTP verify fail | Resend OTP if max attempts exhausted |
| Network timeout | Safe to retry — all submission APIs are idempotent |