Vouchers
Voucher guide
Create vouchers step by step, stock a designated user’s backpack, and let them send vouchers to others.
Creates the voucher in the console, submits it for approval, and chooses a sender and quantity.
Checks stock in the “To send” backpack and chooses a chat to send vouchers. Cannot use this stock.
Claims the voucher in chat, then views its code or redemption link under usable vouchers. Cannot resend it.
End-to-end flow
- Create: open an application, choose Vouchers, click Create vouchers, and follow the prompts for content, quantity, and validity.
- Approval: confirm and submit. The voucher page shows progress and unlocks allocation after approval.
- Stock: search the sender’s username, select the user, enter a quantity, and confirm their backpack allocation.
- Send: the sender opens My benefits → To send in the app and chooses a chat, or sends from the chat toolbar.
- Use: the recipient claims the chat card, then follows the voucher rules to present its code or open the redemption link.
Sending 5 vouchers to 6 people is blocked as a whole with a shortage of 1. Retrying the same request does not deduct twice. Unclaimed vouchers return to sender stock after expiry.
Open console and get startedDeveloper API integration and redemption (optional)
The existing /issue API below creates usable vouchers for final recipients. It does not stock a sender’s backpack. Use the console wizard for backpack allocation; existing API integrations keep their behavior.
Prepare the integration
- Sign in to the Open Platform console and create an application.
- Configure the domain allowlist under Application policy. * is unrestricted; example.com matches only that host; *.example.com matches all subdomains but not the root. Restricted server calls must send a matching Origin.
- Create a voucher template in the application and submit it for review. Only approved templates can be issued.
- Generate an sop_ token with the least scopes required by the service. The full token is shown once.
Choose the right credential
| Credential | Use | Resource boundary |
|---|---|---|
JWT | Manage applications, tokens, and bot links | Applications owned by the signed-in account |
sop_ | Templates, issuance, verification, redemption, and reversal | The single application that owns the token |
sbot_ | Optional voucher delivery in bot chats | The bot-linked application and accessible chats |
Create and submit a template
A template defines the benefit, fulfiller, validity, and issuance limit. A new draft must be submitted and approved as active before issuance.
curl -X POST "$API/api/v1/open-platform/vouchers/templates" \
-H "Authorization: Bearer $OPEN_PLATFORM_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"external_template_id": "app_points_100_2026",
"name": "100 积分券",
"type": "gift",
"description": "核销后向外部应用账号增加 100 积分",
"issuer_name": "联享券测试系统",
"fulfiller_name": "联享券测试系统",
"fulfillment_category": "app_credit",
"acquisition_source": "merchant_campaign",
"validity": { "mode": "relative", "days_after_claim": 30 },
"issue_limit": 0,
"per_user_limit": 1,
"usage_rules": { "instructions": "登录联享券测试系统后确认兑换" },
"fulfillment": {
"points": 100,
"unit": "points",
"redemption_url": "https://www.example.com/linkedcoupons/login",
"open_mode": "in_app"
}
}'
curl -X POST "$API/api/v1/open-platform/vouchers/templates/$TEMPLATE_ID/submit" \
-H "Authorization: Bearer $OPEN_PLATFORM_TOKEN"- type accepts discount, cash_discount, gift, and service.
- Voucher backgrounds only accept platform file IDs, not external image URLs. The console uploads and crops to 16:9, and issued vouchers retain a snapshot of the background.
- fulfillment_category currently accepts physical_goods, offline_service, ecommerce_discount, and app_credit. Use app_credit for application points, and store the amount and unit in fulfillment.
- Set fulfillment.redemption_url to an HTTPS redemption entry. The client replaces {code} when present; otherwise it writes the one-time code to the voucher_code URL fragment. Set open_mode to in_app or external.
- acquisition_source accepts free, merchant_campaign, and platform_campaign.
- Validity can be a fixed date range or 1–3650 days after claim in relative mode.
- issue_limit is a non-negative integer; set it to 0 for unlimited issuance. per_user_limit ranges from 1 to 100. external_template_id is unique within an application.
Link users across systems
Vouchers do not merge account systems. Your server stores only the mapping from an external application user ID to an authorized IM user ID, while your application remains the source of truth for points.
- Let the user initiate linking in your application and complete authorization in IM, then store both immutable user IDs after a successful callback.
- For a linked bot, resolve the recipient from an authorized private chat. The initial bot issuance endpoint supports private chats only.
- Pass the mapped IM user ID as recipient_user_id, then credit fulfillment.points to the external account only after redemption succeeds.
Issue to a specific user
Issue from your server with vouchers:issue. recipient_user_id must come from user authorization or an existing business relationship and must not be enumerated.
curl -X POST "$API/api/v1/open-platform/vouchers/issue" \
-H "Authorization: Bearer $OPEN_PLATFORM_TOKEN" \
-H "Idempotency-Key: order_20260903_001" \
-H "Content-Type: application/json" \
-d '{
"template_id": "YOUR_TEMPLATE_ID",
"external_issue_id": "benefit_20260903_001",
"recipient_user_id": "AUTHORIZED_SOCHAT_USER_ID"
}'Issuance result
{
"success": true,
"data": {
"issuanceId": "ISSUANCE_ID",
"voucher": {
"id": "VOUCHER_ID",
"templateId": "TEMPLATE_ID",
"status": "available",
"validFrom": "2026-09-08T00:00:00.000Z",
"expiresAt": "2026-10-08T00:00:00.000Z",
"version": 1
}
}
}Verify, redeem, and reverse
Verification is read-only. Redemption and reversal change voucher state and must be called from trusted servers with separate idempotency keys.
curl -X POST "$API/api/v1/open-platform/vouchers/verify" \
-H "Authorization: Bearer $VERIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "credential": { "type": "redeem_code", "value": "ABC-123" } }'
curl -X POST "$API/api/v1/open-platform/vouchers/redeem" \
-H "Authorization: Bearer $REDEEM_TOKEN" \
-H "Idempotency-Key: redeem_order_9001" \
-H "Content-Type: application/json" \
-d '{
"credential": { "type": "redeem_code", "value": "ABC-123" },
"external_order_id": "order_9001",
"store_id": "store_01",
"operator_id": "cashier_07",
"occurred_at": "2026-09-08T10:30:00.000Z"
}'
curl "$API/api/v1/open-platform/vouchers/redemptions/$REDEMPTION_ID" \
-H "Authorization: Bearer $READ_TOKEN"
curl -X POST "$API/api/v1/open-platform/vouchers/redemptions/$REDEMPTION_ID/reverse" \
-H "Authorization: Bearer $REVERSE_TOKEN" \
-H "Idempotency-Key: reverse_order_9001" \
-H "Content-Type: application/json" \
-d '{ "reason": "订单退款", "operator_id": "manager_02" }'Voucher statuses
pendingNot valid yetavailableCurrently redeemablelockedTemporarily locked for processingredeemedRedeemedexpiredExpiredrevokedRevokedOptional: deliver through a bot
Link an approved bot owned by the same account to deliver application vouchers in private chats. These calls use the Bot Token and bot endpoint.
POST /api/v1/bots/vouchers/issue
Authorization: Bearer sbot_...
{
"chat_id": "PRIVATE_CHAT_ID",
"template_id": "APPLICATION_TEMPLATE_ID",
"external_issue_id": "benefit_20260903_002"
}Unlinking only disables bot delivery. It does not delete the application, templates, issued vouchers, or sop_ tokens.
Security and business boundaries
- Keep sop_ tokens and Bot Tokens on trusted servers only.
- Issue only to authorized users or users with an existing business relationship, and retain authorization evidence.
- Treat voucher codes and QR data as redemption credentials and prevent unrelated parties from accessing them.
- Developers own benefits, redemption rules, fulfillment, and support. The platform does not sell vouchers or collect payment.
Use the request encryption guide to encrypt the path, token, request body, and response body.
Production checklist
- Replace * with explicit production and test service origins, then verify that missing origins, wrong domains, and scheme mismatches return 403.
- Split token scopes by service, set expiry times, and confirm full tokens are stored and can be rotated.
- Store mappings for external_issue_id, Idempotency-Key, issuanceId, voucher.id, and redemptionId.
- Handle 401, 403, 404, 409, 429, and 5xx separately; retry recoverable errors with the original idempotent request.
- Protect voucher credentials, redact logs, and never place sop_ or sbot_ tokens in front-end code, URLs, or error reports.
- Use a test voucher to complete issuance, verification, duplicate-redemption rejection, lookup, and reversal.
