Выпуск License по Subscription
Используйте эту Management-операцию, когда в Vendor automation уже есть Customer Subscription и нужно выпустить canonical License и human key.
POST /api/v1/licenses/subscription-issues
Authorization: Bearer <service-account-token>
Idempotency-Key: <unique-operation-key>
X-Correlation-Id: <correlation-id>
Content-Type: application/json
{
"customerSubscriptionId": "019b0000-0000-7000-8000-000000000101",
"correlationId": "019b0000-0000-7000-8000-000000000102"
}
Service account нужен permission licenses.manage. Tenant и actor берутся из
authenticated context. Не передавайте tenantId, actor, Product, Customer,
OfferVersion, Policy, validity, License code или key material: неизвестные
поля request отклоняются.
Первый успех и replay
Первый durable commit возвращает 201 Created. plaintextKey — shown-once
secret: сразу поместите его в разрешённое secret-хранилище и не логируйте.
{
"licenseId": "019b0000-0000-7000-8000-000000000201",
"licenseCode": "LIC-<server-generated-id>",
"keyMaterialRefId": "019b0000-0000-7000-8000-000000000202",
"snapshotId": "019b0000-0000-7000-8000-000000000203",
"snapshotVersion": 1,
"snapshotHash": "<lowercase-sha256>",
"maskedKey": "7K3M-••••-••••-••••-ABCD",
"plaintextKey": "<shown-once-secret>",
"issueMode": "Subscription",
"isIdempotentReplay": false
}
Повторяйте тот же effective request с тем же Idempotency-Key. Exact replay
возвращает 200 OK, те же references и mask, а также:
{
"plaintextKey": null,
"isIdempotentReplay": true
}
Если первый ответ потерян после commit, replay не восстановит plaintext. Чтобы получить новый secret, используйте отдельно авторизованную key rotation.
Ошибки
Все ошибки используют стандартный ErrorResponse. В SDK mapping ниже указана
рекомендуемая публичная категория исключения.
| HTTP / code | Retry | SDK category | Действие клиента |
|---|---|---|---|
400 license_issue.invalid_request | Нет | ValidationException | Исправить body или Idempotency-Key. |
404 license_issue.subscription_not_found | Нет | NotFoundException | Проверить tenant-scoped Subscription ID. |
409 license_issue.source_conflict | Нет | ConflictException | Обновить Subscription/Offer/Policy и устранить несовпадение. |
409 license_issue.not_issuable | Нет | ConflictException | Перевести Subscription/OfferVersion в допустимое состояние. |
409 license_issue.idempotency_conflict | Нет | IdempotencyConflictException | Использовать исходный payload или новый key для новой операции. |
409 license_issue.persistence_conflict | Да | ConflictException | Повторить с backoff и тем же key. |
503 license_issue.audit_unavailable | Да | ServiceUnavailableException | Повторить с backoff и тем же key. |
500 license_issue.stored_result_invalid | Нет | ServerContractException | Остановить retry и передать support значение correlationId. |
Ошибка authentication — 401 unauthorized; отсутствие licenses.manage —
403 forbidden.