Browse documentation

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/json
An sop_ token is bound to one application. Request fields such as application_id or bot_id cannot switch ownership; a revoked or expired token, or a disabled application, stops working immediately. Application policy also checks Origin: * is unrestricted, an exact domain excludes subdomains, and *.example.com allows only its subdomains; missing Origin returns 403 once restricted.

Production services can encrypt the logical path, sop_ token, idempotency key, request body, and response body. Read the request encryption guide.

Scopes

vouchers:readRead templates and redemption results
vouchers:templates:writeCreate and submit templates
vouchers:issueIssue vouchers
vouchers:verifyVerify voucher state
vouchers:redeemRedeem vouchers
vouchers:reverseReverse redemptions

Response 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

GET/api/v1/open-platform/me

Read the token application for startup checks.

Scope
vouchers:read
Default rate limit
60/minute
Idempotency key
No
GET/api/v1/open-platform/vouchers/templates

List all templates in the application.

Scope
vouchers:read
Default rate limit
60/minute
Idempotency key
No
POST/api/v1/open-platform/vouchers/templates

Create a draft template.

Scope
vouchers:templates:write
Default rate limit
20/minute
Idempotency key
No
POST/api/v1/open-platform/vouchers/templates/:templateId/submit

Submit a draft or rejected template for review.

Scope
vouchers:templates:write
Default rate limit
10/minute
Idempotency key
No
POST/api/v1/open-platform/vouchers/issue

Issue an active-template voucher to a user.

Scope
vouchers:issue
Default rate limit
30/minute
Idempotency key
Yes
POST/api/v1/open-platform/vouchers/verify

Read current status using a QR credential or six-character code.

Scope
vouchers:verify
Default rate limit
30/minute
Idempotency key
No
POST/api/v1/open-platform/vouchers/redeem

Atomically redeem an available voucher.

Scope
vouchers:redeem
Default rate limit
20/minute
Idempotency key
Yes
GET/api/v1/open-platform/vouchers/redemptions/:redemptionId

Read a redemption or reversal record in the application.

Scope
vouchers:read
Default rate limit
60/minute
Idempotency key
No
POST/api/v1/open-platform/vouchers/redemptions/:redemptionId/reverse

Reverse 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.

FieldRequiredDescription
external_template_idYesYour template ID; unique within the application.
nameYesUser-facing voucher name.
typeYesdiscount | cash_discount | gift | service
issuer_nameYesIssuer name.
fulfiller_nameYesName of the party fulfilling the benefit.
fulfillment_categoryYesphysical_goods | offline_service | ecommerce_discount | app_credit
acquisition_sourceYesfree | merchant_campaign | platform_campaign
validityYesfixed uses from/to; relative uses days_after_claim (1–3650).
issue_limitYesTotal issuance limit; set to 0 for unlimited issuance.
per_user_limitNoPer-user limit from 1–100; defaults to 1.
description / cover_file_idNoDisplay 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 / termsNoStructured 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 issuable

Issuance parameters

FieldRequiredDescription
Idempotency-KeyYesHeader identifying one issuance action.
template_idYesID of an active template in this application.
external_issue_idYesYour unique business issuance ID.
recipient_user_idYesID 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

FieldRequiredDescription
Idempotency-KeyYesHeader identifying one redemption action.
credentialYesA qr_token or redeem_code credential object.
external_order_idYesYour order or transaction ID.
store_idNoStore where redemption occurred.
operator_idNoOperator ID.
occurred_atNoISO 8601 business timestamp; defaults to server time.
Redemption atomically updates a voucher only when it is available, active, and unexpired. Only one concurrent request succeeds; the rest receive 409. A verification result never replaces the redemption result.

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/:botId

Allocate 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

  • 400 A field is missing, malformed, or outside its allowed range.
  • 401 The token is invalid, expired, or revoked.
  • 403 The application is disabled, the feature is unavailable, or the token lacks scope.
  • 404 The template, voucher, or redemption does not belong to the application.
  • 409 State conflict, quota exhausted, or an idempotency key reused with a different request.
  • 429 The request exceeded the endpoint rate limit.
  • 5xx A 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.