Vouchers
Voucher API
Endpoints, scopes, and constraints for independent application tokens.
Authentication
Runtime endpoints use an sop_ token. Do not send an account JWT or Bot Token to these endpoints.
API=https://api.example.com
Authorization: Bearer sop_xxxxxxxxxxxxxxxxx
Content-Type: application/jsonScopes
vouchers:readRead templates and redemption resultsvouchers:templates:writeCreate and submit templatesvouchers:issueIssue vouchersvouchers:verifyVerify voucher statevouchers:redeemRedeem vouchersvouchers:reverseReverse redemptionsResponse envelope
The HTTP status communicates transport and business outcome. The body includes success, code, message, data, and meta.requestId for support. Error responses set success to false and include error details.
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {},
"meta": {
"requestId": "REQUEST_ID",
"timestamp": "2026-09-08T10:30:00.000Z",
"duration": "12ms"
}
}Runtime endpoints
/api/v1/open-platform/meRead the token application for startup checks.
- Scope
vouchers:read- Default rate limit
- 60/minute
- Idempotency key
- No
/api/v1/open-platform/vouchers/templatesList all templates in the application.
- Scope
vouchers:read- Default rate limit
- 60/minute
- Idempotency key
- No
/api/v1/open-platform/vouchers/templatesCreate a draft template.
- Scope
vouchers:templates:write- Default rate limit
- 20/minute
- Idempotency key
- No
/api/v1/open-platform/vouchers/templates/:templateId/submitSubmit a draft or rejected template for review.
- Scope
vouchers:templates:write- Default rate limit
- 10/minute
- Idempotency key
- No
/api/v1/open-platform/vouchers/issueIssue an active-template voucher to a user.
- Scope
vouchers:issue- Default rate limit
- 30/minute
- Idempotency key
- Yes
/api/v1/open-platform/vouchers/verifyRead current status using a QR credential or six-character code.
- Scope
vouchers:verify- Default rate limit
- 30/minute
- Idempotency key
- No
/api/v1/open-platform/vouchers/redeemAtomically redeem an available voucher.
- Scope
vouchers:redeem- Default rate limit
- 20/minute
- Idempotency key
- Yes
/api/v1/open-platform/vouchers/redemptions/:redemptionIdRead a redemption or reversal record in the application.
- Scope
vouchers:read- Default rate limit
- 60/minute
- Idempotency key
- No
/api/v1/open-platform/vouchers/redemptions/:redemptionId/reverseReverse a successful redemption.
- Scope
vouchers:reverse- Default rate limit
- 10/minute
- Idempotency key
- Yes
Template endpoints
A template ID is unique within an application. Only draft or rejected templates can be submitted, and only active templates can issue vouchers.
| Field | Required | Description |
|---|---|---|
external_template_id | Yes | Your template ID; unique within the application. |
name | Yes | User-facing voucher name. |
type | Yes | discount | cash_discount | gift | service |
issuer_name | Yes | Issuer name. |
fulfiller_name | Yes | Name of the party fulfilling the benefit. |
fulfillment_category | Yes | physical_goods | offline_service | ecommerce_discount | app_credit |
acquisition_source | Yes | free | merchant_campaign | platform_campaign |
validity | Yes | fixed uses from/to; relative uses days_after_claim (1–3650). |
issue_limit | Yes | Total issuance limit; set to 0 for unlimited issuance. |
per_user_limit | No | Per-user limit from 1–100; defaults to 1. |
description / cover_file_id | No | Display description and an image file ID uploaded by the application owner. Upload and crop it in the console first; external image URLs are rejected. |
usage_rules / fulfillment / terms | No | Structured usage rules, fulfillment data, and terms snapshot; fulfillment may include an HTTPS redemption_url and an in_app or external open mode. |
Template statuses
draftDraft; can be submittedreviewingIn reviewactiveIssuablerejectedRejected; can be revised and resubmittedpaused / ended / archivedNot issuableIssuance parameters
| Field | Required | Description |
|---|---|---|
Idempotency-Key | Yes | Header identifying one issuance action. |
template_id | Yes | ID of an active template in this application. |
external_issue_id | Yes | Your unique business issuance ID. |
recipient_user_id | Yes | ID of an authorized user or existing customer relationship. |
A successful response returns issuanceId and voucher. Application APIs do not expose the code or QR secret; the holder-facing client presents credentials securely.
Voucher credential
{
"credential": {
"type": "qr_token",
"value": "SCANNED_VALUE"
}
}type accepts qr_token or redeem_code. Six-character codes ignore case, spaces, and hyphens. Verification marks an expired available voucher as expired, but does not redeem it.
Redemption parameters
| Field | Required | Description |
|---|---|---|
Idempotency-Key | Yes | Header identifying one redemption action. |
credential | Yes | A qr_token or redeem_code credential object. |
external_order_id | Yes | Your order or transaction ID. |
store_id | No | Store where redemption occurred. |
operator_id | No | Operator ID. |
occurred_at | No | ISO 8601 business timestamp; defaults to server time. |
Reversal
A reversal must reference a successful, unreversed redemption and use a new Idempotency-Key. The voucher returns to available if still valid, or expired otherwise.
{
"reason": "订单退款",
"operator_id": "manager_02"
}Idempotency and retries
- Use separate Idempotency-Key values for issuance, redemption, and reversal.
- Retry the same business action with the original key and identical request body.
- A client timeout does not mean server failure. Retry the original request or query the redemption record instead of changing the key.
- A 409 can mean exhausted quota, per-user limit, already redeemed, not redeemable, or idempotency conflict. Classify it using message/error.
Console management endpoints
These endpoints use the signed-in account JWT and only access applications owned by that account.
GET /api/v1/open-platform/applications
POST /api/v1/open-platform/applications
GET /api/v1/open-platform/applications/:id
PATCH /api/v1/open-platform/applications/:id
GET /api/v1/open-platform/applications/:id/tokens
POST /api/v1/open-platform/applications/:id/tokens
DELETE /api/v1/open-platform/applications/:id/tokens/:tokenId
PUT /api/v1/open-platform/applications/:id/bots/:botId
DELETE /api/v1/open-platform/applications/:id/bots/:botIdAllocate sender stock
Application owners use their account JWT to find senders and allocate stock. This does not create a usable voucher or redemption credential. A user voucher is created only when the recipient claims it. The existing runtime /issue endpoint still issues directly to the user who will use it.
GET /api/v1/open-platform/applications/:id/vouchers/recipients?keyword=sender
GET /api/v1/open-platform/applications/:id/vouchers/allocations?templateId=TEMPLATE_ID&page=1&limit=20
POST /api/v1/open-platform/applications/:id/vouchers/allocations
{
"templateId": "TEMPLATE_ID",
"recipientUserId": "SENDER_USER_ID",
"quantity": 5,
"idempotencyKey": "UNIQUE_ALLOCATION_REQUEST_ID"
}Search accepts a username of at least two characters or a full user ID, and returns up to 20 users. Quantity must be an integer from 1 to 10,000 within available stock. Network retries must reuse the original idempotency key and body. Allocation records include id, quantity, remaining, sendingCount, claimedCount, and status.
Common status codes
400A field is missing, malformed, or outside its allowed range.401The token is invalid, expired, or revoked.403The application is disabled, the feature is unavailable, or the token lacks scope.404The template, voucher, or redemption does not belong to the application.409State conflict, quota exhausted, or an idempotency key reused with a different request.429The request exceeded the endpoint rate limit.5xxA temporary platform failure. Keep the requestId and retry only with the original idempotency key and body.
Common business errors
VOUCHER_ALREADY_REDEEMEDThe voucher has already been redeemed.VOUCHER_NOT_REDEEMABLEThe voucher is not active, is expired or revoked, or otherwise cannot be redeemed.