API
Reseller API
POST /api/ · JSON responses · VIP card code as key
Send requests from your server using application/json or application/x-www-form-urlencoded. Keep the VIP card code out of page source and URLs.
Check card balance and spending history →List services services
Returns packages currently available on this site. price is the full package price in major currency units, price_minor is the same price in minor units, and rate is the equivalent price per 1,000 units for comparison. Each package has a fixed quantity, so quantity, min, and max are equal. Use that quantity when ordering and specify package_id to select an exact package. Filter with search or category. For pagination, send limit (1–100) and pass the returned next_cursor as cursor to fetch the next page. Unpaginated requests return an array. Paginated requests return an object with services and, when another page exists, next_cursor.
{
"key": "YOUR_VIP_CARD",
"action": "services"
}Place an order add
The server recalculates the price and charges the card balance. Use a SKU from services and replace YOUR_REQUEST_UUID with a UUID you generate and save. After a timeout, retry with the same request_id and exactly the same payload to avoid a duplicate charge. For legacy compatibility, requests without request_id are treated as new orders. Put one comment per line in comment_input, use hashtag_input for keywords, or send plain text in details. Conflicting text fields are rejected. Packages with additional requirements are validated against server rules. The API never substitutes another service.
{
"key": "YOUR_VIP_CARD",
"action": "add",
"sku": "YOUR_SERVICE_SKU",
"quantity": 100,
"link": "https://www.instagram.com/example/",
"request_id": "YOUR_REQUEST_UUID"
}Check order status status
Send up to 100 comma-separated order numbers. The response is keyed by order number and only includes order details for this card. The API may refresh the provider status for orders in progress. Fields include charge, url, count, status, currency, payment_state, and refund. Unavailable start_count and remains values are null. Check refund and payment_state separately when an order is canceled. If the status refresh fails, the API returns the last saved status and sets sync_unavailable to true.
{
"key": "YOUR_VIP_CARD",
"action": "status",
"order": "ORDER_NUMBER_1,ORDER_NUMBER_2"
}Get a quote quote
Returns a quote without creating an order or charging the card. The response includes quote_id, amount_minor, currency, expires_at, and terms. Quotes are valid for five minutes. Monthly plan terms include the quantity per post, number of posts, and duration in days. After reviewing the quote, send action=add, quote_id, request_id, and max_amount. Set max_amount in minor currency units (100 fen equals 1 yuan for CNY). When ordering from a quote, omit sku, quantity, link, package_id, and the order text fields.
{
"key": "YOUR_VIP_CARD",
"action": "quote",
"sku": "YOUR_SERVICE_SKU",
"quantity": 100,
"link": "https://www.instagram.com/example/"
}Check card balance balance
Returns balance, available, and currency. Amounts are decimal strings in major currency units. Checking the balance does not activate or charge the card.
{
"key": "YOUR_VIP_CARD",
"action": "balance"
}Python example
import os, requests
response = requests.post(
"https://www.runwulink.com/api/",
json={"key": os.environ["ZFENSI_CARD"], "action": "balance"},
timeout=30,
)
response.raise_for_status()
print(response.json())For local testing, replace the domain with your local server address. Check the deployment results to confirm that the production domain serves this API version.
Error handling
INVALID_CARD (invalid or expired card code). OFFER_UNAVAILABLE (no matching package). IDEMPOTENCY_CONFLICT (the same request_id was reused with different contents). RATE_LIMITED (too many requests). The order cannot succeed if the card balance is insufficient.
PRICE_LIMIT_EXCEEDED (the amount exceeds max_amount). QUOTE_EXPIRED (the quote has expired). AMBIGUOUS_PACKAGE (provide package_id). CONFLICTING_DETAILS (conflicting text fields or quote parameters). The server calculates all amounts. Client-supplied price and charge values cannot override the quote.
Review a quote before placing an order
import os, uuid, requests
base_url = "https://www.runwulink.com/api/"
key = os.environ["ZFENSI_CARD"]
quote = requests.post(base_url, json={
"key": key, "action": "quote",
"sku": os.environ["ZFENSI_SKU"],
"quantity": int(os.environ["ZFENSI_QUANTITY"]),
"link": os.environ["ZFENSI_TARGET"]
}, timeout=30)
quote.raise_for_status()
quote = quote.json()
print(quote)
# Review the target, amount, and currency before placing the order. Save the payload for retries.
payload = {
"key": key, "action": "add",
"quote_id": quote["quote_id"],
"request_id": str(uuid.uuid4()),
"max_amount": quote["amount_minor"]
}
# Paid operation. If you retry, reuse the same payload and UUID.
order = requests.post(base_url, json=payload, timeout=30)
order.raise_for_status()
print(order.json())