Provider-based keyless delivery for the Seller API. Instead of returning raw game keys to your store backend, Avrix issues a hosted redemption URL (provider hosted_redemption). Future providers may activate entitlement on platform accounts; they are not available in this release.
Keyless redemption flow#
Quantity policy#
quantity must be 1 per keyless order. Multi-unit keyless carts are rejected (422). Split cart lines into one order (or one hold→order) per unit.
Availability#
| Gate | Requirement |
|---|---|
| Capability | GET /api/seller/v1/whoami → capabilities.keylessEnabled === true |
| Provider | Only hosted_redemption in this release |
| Quantity | Must be 1 |
When keylessEnabled is false, keyless requests return 403 FEATURE_DISABLED — stay on key-based delivery. Sandbox SKU SANDBOX-KEYLESS-001 is available when sandbox and keyless are both enabled.
Create a keyless order#
curl -s -X POST "https://api.avrix.io/api/seller/v1/orders" \
-H "Authorization: Bearer $AVRIX_API_KEY" \
-H "Idempotency-Key: keyless-store-10432" \
-H "Content-Type: application/json" \
-d '{
"skuCode": "SANDBOX-KEYLESS-001",
"quantity": 1,
"orderReference": "keyless-store-10432",
"expectedUnitPriceCents": 5999,
"countryCode": "NL",
"deliveryMode": "keyless",
"integrationOrderContext": {
"schemaVersion": 1,
"salesCountryCode": "NL",
"currencyCode": "EUR",
"salesPriceGrossMinor": 7999,
"priceIncludesTax": true,
"salesTaxRatePercent": 21,
"salesChannel": "web",
"salesTaxAmountMinor": 1388,
"paymentProcessorReference": "pay_keyless_1",
"checkoutSessionId": "cs_keyless_1",
"consumerIp": "198.51.100.42"
}
}'Successful response:
{
"data": {
"type": "fulfilled",
"deliveryMode": "keyless",
"pulled": 1,
"orderReference": "store-order-10432",
"delivery": {
"provider": "hosted_redemption",
"redemptionUrl": "https://app.avrix.io/redeem/v1/...",
"fulfillmentId": "kf_4c81...",
"expiresAt": "2026-09-04T09:14:22.108Z"
}
}
}
Persist fulfillmentId and deliver redemptionUrl to the buyer. No key material passes through your systems.
Manage links — revoke and regenerate#
Requires scope seller:orders:manage.
| Operation | Path | Effect |
|---|---|---|
| Revoke | POST /api/seller/v1/orders/fulfillments/{fulfillmentId}/revoke | Invalidates the link. Idempotent when already terminal (revoked, redeemed, or activated). Does not return keys to inventory. |
| Regenerate | POST /api/seller/v1/orders/fulfillments/{fulfillmentId}/regenerate | Revokes the old link and issues a new fulfillmentId + URL. Not allowed after buyer activation (409 ALREADY_ACTIVATED). |
Buyer-facing expired copy#
When a buyer opens an expired hosted redemption link, they see:
This redemption link has expired.
Other terminal messages include revoked and already-used variants on the hosted page.
Link TTL and views#
Hosted redemption defaults (platform-issued):
| Setting | Default |
|---|---|
| Max views | 1 (one-time reveal) |
| Expiry | 30 days from issue (expiresAt on the delivery object) |
redemption.expiring gives advance notice inside the 24-hour window before expiresAt.
redemption.expired fires once when expiresAt has passed without activation. Regenerate
before activation if the link was lost or is about to lapse.
Webhooks#
| Event | When |
|---|---|
order.fulfilled | Inventory committed; includes delivery object (no keys) |
order.activated | Buyer revealed code or platform activation completed |
redemption.expiring | An unredeemed hosted link enters the 24h window before expiresAt |
redemption.expired | The hosted link has passed expiresAt without activation |
Security#
- Redemption tokens are cryptographically signed; the platform stores hash only
- Reveal is one-time (default max views 1) with expiry (default 30 days)
- Decrypt + audit occurs at reveal time, not at order time