API Documentation

Homepage/API documentation
API CHARGING V2

Card submission integration guide

Documentation for Merchants submitting cards, checking transaction statuses and retrieving account-specific fees.

PRIMARY ENDPOINThttps://toctoico.com/chargingws/v2

1. Integration overview

InformationValue
Primary endpointhttps://toctoico.com/chargingws/v2
Fee schedule APIhttps://toctoico.com/chargingws/v2/getfee?partner_id=YOUR_PARTNER_ID
MethodPOST
Data typeapplication/json or application/x-www-form-urlencoded
Supported commandscharging, check

2. Requirements before calling the API

Nappay protocol compatibility: change the URL to this website and use the local Merchant's Partner ID/Key and wallet code. Catalogs, prices and processing conditions come from this system.

Integrate directly with this system using your account's Merchant. All amounts are in Vietnamese dong (VND); send integers without separators.

  1. Sign in → API Connections / Merchant, create a Merchant for the correct service and enable it.
  2. Get the Partner ID, Partner Key and wallet code from that Merchant. If an IP allowlist is configured, specify the public IP of the server sending requests.
  3. Configure the receiving system's HTTPS callback URL; select POST JSON or GET according to the Merchant.
  4. Retrieve catalog/fees and check the balance first; then integrate order creation, lookup and reconciliation.

The Partner Key is for your server only. Do not place it in browser JavaScript, public applications or URLs. YOUR_PARTNER_ID, YOUR_PARTNER_KEY and YOUR_WALLET below are placeholders for your own Merchant details on this website.

Endpoints for card exchange, top-ups and card code purchases
ServiceEndpointFormat
Exchange prepaid cardshttps://toctoico.com/chargingws/v2POST JSON or form-urlencoded
Service top-uphttps://toctoico.com/api/rechargewsPOST JSON or form-urlencoded
Buy card codeshttps://toctoico.com/api/cardwsPOST JSON or form-urlencoded
Card exchange feeshttps://toctoico.com/chargingws/v2/getfee?partner_id=YOUR_PARTNER_IDGET
Card code cataloghttps://toctoico.com/api/cardws/products?partner_id=YOUR_PARTNER_IDGET

3. Authentication signatures

Sign the UTF-8 string with MD5 by concatenating fields in the exact order below, without dots, spaces or separators. Send the hexadecimal MD5 string; command must use lowercase exactly as documented.

Command groupString to hash with MD5
Card exchange: chargingpartner_key + code + command + partner_id + request_id + serial + telco
Card exchange: checkpartner_key + command + partner_id + request_id
Card exchange: legacy signature still supportedpartner_key + code + serial
Topup: topup, getstatuspartner_key + partner_id + command + request_id
Topup: productlist, getbalance, feetopup, canceltopuppartner_key + partner_id + command
Card codes: buycard, redownloadpartner_key + partner_id + command + request_id
Card codes: getbalance, checkavailablepartner_key + partner_id + command
Card code catalog, getfeeMerchant/IP authentication through partner_id; this endpoint currently does not require sign
Serial lookup /api/checkcardpartner_key + serial
Python
hashlib.md5((partner_key + partner_id + command + request_id).encode("utf-8")).hexdigest()

Each Merchant may use only its registered API type (Charging, Recharge, Softcard or All). Authentication/IP errors may appear in JSON even when HTTP is 200.

4. Card exchange parameters and responses

POST /chargingws/v2

Submit cards with command=charging. Check using command=check with partner_id, request_id and sign as shown above; card details do not need to be resubmitted. The legacy MD5(partner_key + code + serial) signature is still supported when code and serial are included.

ParametersRequestMeaning / value
partner_id, signRequiredMerchant and signature for card exchange
commandRequiredcharging or check
request_idRequiredUnique request reference per Merchant; reuse the original reference for check
telcoKhi chargingUppercase network code; retrieve it from getfee
amountKhi chargingDeclared denomination; optional for check
code, serialKhi chargingCard code/serial strings; preserve leading zeros and resend exactly the original string for check
json
{
  "partner_id": "YOUR_PARTNER_ID",
  "command": "charging",
  "request_id": "CHARGE_DEMO_001",
  "telco": "VIETTEL",
  "amount": 100000,
  "code": "YOUR_CARD_CODE",
  "serial": "YOUR_CARD_SERIAL",
  "sign": "MD5_THEO_CONG_THUC_CHARGING"
}

Recheck transaction

json
{
  "partner_id": "YOUR_PARTNER_ID",
  "command": "check",
  "request_id": "CHARGE_DEMO_001",
  "sign": "MD5_PARTNER_KEY_CHECK_PARTNER_ID_REQUEST_ID"
}

Transaction response

json
{
  "trans_id": 123,
  "request_id": "CHARGE_DEMO_001",
  "status": 99,
  "message": "PENDING",
  "declared_value": 100000,
  "value": 0,
  "amount": 0,
  "telco": "VIETTEL",
  "code": "YOUR_CARD_CODE",
  "serial": "YOUR_CARD_SERIAL",
  "callback_sign": "MD5_PARTNER_KEY_CODE_SERIAL"
}
ParametersRequestMeaning / value
trans_id, request_idReceiveSystem transaction ID and your request reference
declared_valueReceiveDeclared denomination
valueReceiveConfirmed actual denomination
amountReceiveNet amount credited to the wallet after processing
status, messageReceiveCard status or error; always check both
statusMeaning
99Pending; not yet credited as a successful order
1Valid card, successful
2Valid card with incorrect denomination
3Failed / invalid card
4Skip / maintenance based on processing result
100Request error
101Transaction not found
102Invalid authentication, IP or data
104Invalid command

Merchant-specific fees

GET /chargingws/v2/getfee?partner_id=YOUR_PARTNER_ID. The response is a flat list containing telco, value, fees and penalty, compatible with Nappay. Existing integrations that need grouped objects can add format=grouped. fees is the customer fee for the account group; only enabled card types and denominations are returned. Do not hardcode the catalog or fees from the documentation examples.

json
[
  {
    "telco": "VIETTEL",
    "value": 100000,
    "fees": "18.5",
    "penalty": "50"
  }
]

The group fee is finalized per order when the card is accepted. For an incorrect denomination (status=2), a 50% penalty applies to the net amount after the group fee: credited amount = provider-confirmed denomination × (100 − group fee)% × 50%, rounded down to VND. For example, 10.000 VND with a 26,8% group fee credits 3.660 VND. Use amount from the final result to record the credit; do not recalculate it from the declared denomination. Orders routed to manual processing may remain at status 99 until an operator confirms them; lookup/callback results are the basis for the final update.

5. Callbacks and reconciliation

Register your callback URL in the Merchant on this website. The system sends card exchange/top-up results using POST JSON or GET according to the Merchant settings. Callbacks may be retried; handle repeats idempotently by order code and status.

ServiceVerify callback_signMain fields
Exchange cardsMD5(partner_key + code + serial)status, message, request_id, trans_id, declared_value, value, amount, telco, code, serial
TopupMD5(partner_key + order_code)status, request_id, order_code, request_value, amount, account

Top-up callbacks use status=completed for successful orders; request_value is the requested top-up amount and amount is the payment amount if a finalized quote exists. Order lookups may return data.status=success for the same outcome. GET card exchange callbacks also include card_value.

json
{
  "status": "completed",
  "request_id": "TOPUP_DEMO_001",
  "order_code": "R_DEMO_ORDER",
  "request_value": 100000,
  "amount": 92500,
  "account": {
    "game_id": "PLAYER_ID"
  },
  "callback_sign": "MD5_PARTNER_KEY_ORDER_CODE"
}
  1. Verify the signature using the corresponding Merchant key with a timing-safe comparison; verify that the order belongs to your system.
  2. Call check/getstatus to confirm the status and verify the denomination/amount before recording a result. The compatible signature does not sign all status fields.
  3. Record within a database transaction, prevent duplicate records/credits, then return HTTP 2xx promptly.
  4. If callbacks are delayed or lost, look up the order periodically; do not treat disconnection as failure or create a new order.

The callback queue retries up to 12 times with increasing delays. Top-up callbacks also depend on the product's callback settings. Card purchase results are obtained through buycard/redownload.

Python
import hashlib, hmac
expected = hashlib.md5((partner_key + payload["order_code"]).encode()).hexdigest()
valid = hmac.compare_digest(expected, str(payload.get("callback_sign", "")).lower())

6. Error codes and troubleshooting

Read the HTTP code, status, message and transaction status within data. Do not use one status table for all services: top-ups use strings, while card codes use numbers.

Common error codesReason
100Product not found or card exchange request error; read message
101E-wallet not found
102Insufficient wallet balance
103Missing data
104Incorrect submitted data
108Merchant nonexistent, disabled or invalid
109request_id already exists
110Invalid request, incorrect Merchant type or order not found
111wallet_number mismatch in the card code API
116Invalid signature
117Missing/invalid command
118The product is out of stock or unavailable
114IP not allowed
129Card code order not found
130Provider error
125Invalid quantity
126Quantity must be a positive integer
ScenarioHow to handle
HTTP 400Check data, customer fields, amount limits and product selection
HTTP 409 / duplicate request_idLook up the original order; do not send a different payload with an existing reference
HTTP 503 / timeoutKeep the request reference and reconcile before retrying; provider submission status may be uncertain
API success received but still pendingContinue monitoring status/callbacks; the transaction is not complete
Sai signCheck the correct service key, concatenation order, request_id and UTF-8
The price differs from the previous quoteRefresh the Merchant catalog; prices are finalized when an order is accepted

Space lookups at least a few seconds apart, increasing the delay while results are pending. Your server must generate and save request_id before sending. Do not use a real purchase to test connectivity; productlist/getbalance/getfee are read-only checks.

7. Code examples

Python example calling getbalance safely to test the connection (install requests using pip install requests). Use environment variables for private information; do not put keys in source code.

Python
import os, hashlib, requests
BASE = "https://toctoico.com"
partner_id = os.environ["GACHTHE_PARTNER_ID"]
partner_key = os.environ["GACHTHE_PARTNER_KEY"]

def recharge(command, **fields):
    request_id = str(fields.get("request_id", "")) if command in ("topup", "getstatus") else ""
    sign = hashlib.md5((partner_key + partner_id + command + request_id).encode()).hexdigest()
    payload = {**fields, "partner_id": partner_id, "command": command, "sign": sign}
    response = requests.post(BASE + "/api/rechargews", json=payload, timeout=20)
    result = response.json()
    response.raise_for_status()
    return result

print(recharge("getbalance"))
# Lưu request_id trước khi gọi topup. Sau đó lưu order_code trả về.
# Khi timeout: tra cứu/đối soát, không tạo request_id mới để mua lại.

PHP: signature and JSON submission

PHP
<?php
$partnerId = getenv('GACHTHE_PARTNER_ID');
$partnerKey = getenv('GACHTHE_PARTNER_KEY');
$command = 'getbalance';
$payload = ['partner_id' => $partnerId, 'command' => $command,
    'sign' => md5($partnerKey . $partnerId . $command)];
$ch = curl_init('https://toctoico.com/api/rechargews');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_TIMEOUT => 20]);
$body = curl_exec($ch);
if ($body === false) { throw new RuntimeException('Chưa xác nhận được phản hồi API'); }
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
// Kiểm tra $status, $result['status'] và trạng thái đơn trong data nếu có.

cURL

cURL
curl --request POST 'https://toctoico.com/api/rechargews' \
  --header 'Content-Type: application/json' \
  --data '{"partner_id":"YOUR_PARTNER_ID","command":"getbalance","sign":"YOUR_COMPUTED_MD5"}' 

Card exchange uses the separate charging/check formulas in the signature table; the legacy MD5(partner_key + code + serial) formula remains supported. For card code purchases, use the concatenation rule in the signature table and the /api/cardws endpoint.

8. Serial lookup

POST /api/checkcard. Only use this when an administrator has enabled the feature and granted access to the Merchant. Lookup availability, limits and returned information depend on the approved configuration. Do not infer that a card is unused from an incomplete response.

ParametersRequestMeaning / value
partner_idRequiredAuthorized Merchant
telcoKhi chargingCard type code
serialRequiredSerial string
signRequiredMD5(partner_key + serial)
json
{
  "partner_id": "YOUR_PARTNER_ID",
  "telco": "VIETTEL",
  "serial": "YOUR_CARD_SERIAL",
  "sign": "MD5_PARTNER_KEY_SERIAL"
}

Check status, message and the actual returned data. This is not a card top-up or PIN-check API; do not enable permissions yourself or run bulk lookups.

System API documentation · Updated 30/10/2026 · Code and prices are illustrative only.