Skip to content

Create Order ​

Create a new payment order. This endpoint uses header-based HMAC signing.

Endpoint ​

POST /v4.0.0/api/orders/create

Request Body ​

FieldTypeRequiredDescription
accessKeyIdstringYesYour merchant Access Key ID
merchantOrderIdstringYesYour order identifier, unique within (chain + merchant + channel)
merchantChannelstringNoMerchant channel; defaults to default
blockChainstringYesBlockchain name (e.g. ETH, TRON, BSC, POLYGON); case-insensitive
tokenSymbolstringYesToken symbol (e.g. usdt, usdc)
amountstringYesPayment amount as a decimal string (e.g. "10.50"); at most 2 decimal places
splitterAddressstringYesYour split contract address; must be active and belong to this merchant
subjectstringNoOrder subject / description
expireDurationintegerNoExpiration in seconds; defaults to 172800 (48 hours), capped at 259200 (72 hours)
callbackUrlstringNoPer-order frontend redirect URL; falls back to the api key's callbackUrl when omitted
remarkstringNoOrder remark
extrastringNoExtra order information
param1stringNoExtra parameter 1
param2stringNoExtra parameter 2

WARNING

There is no notifyUrl in the request body. The backend notification URL is configured on the api key and cannot be overridden per order; only callbackUrl (the frontend redirect) can. The two point in opposite directions — see Notify URL vs Callback URL.

NOTE

merchantOrderId uniqueness is scoped to (chain + merchant address + merchant channel), so the same merchantOrderId may exist as one order per chain.

Example Request ​

json
{
  "accessKeyId" : "01K...BB",
  "merchantOrderId" : "aaf..-8",
  "merchantChannel" : null,
  "blockChain" : "ETH",
  "tokenSymbol" : "usdt",
  "amount" : "0.05",
  "splitterAddress" : "0xfd5...f8b",
  "subject" : "Test Order - API Doc",
  "remark" : null,
  "param1" : null,
  "param2" : null,
  "callbackUrl" : null,
  "extra" : null,
  "expireDuration" : 60000,
  "payWebType" : null
}

Example Response ​

json
{
  "code" : 0,
  "msg" : "success",
  "ui" : null,
  "version" : null,
  "count" : 0,
  "data" : {
    "merchantAddress" : "0x17a...42",
    "merchantChannel" : "default",
    "blockChain" : "ETH",
    "tokenSymbol" : "usdt",
    "createChannel" : 1,
    "merchantOrderId" : "aaf..-8",
    "payOrderId" : "01K...H8",
    "tokenAddress" : "0xdac17f958d2ee523a2206206994597c13d831ec7",
    "receiptAddress" : "0x5...c4",
    "amount" : 0.05,
    "state" : 0,
    "accessSign" : "AA377....F5",
    "rate" : 80,
    "obtainAmount" : 0.0496,
    "platformFee" : 4.0E-4,
    "expireDuration" : "60000",
    "underPaid" : false,
    "paidAmount" : 0.0,
    "createTime" : 1785753243948
  }
}

NOTE

Fields in data that were never populated come back as null (e.g. payTxId, param1, errorMsg); the example omits them for readability. Also note that expireDuration, confirmCount, chainId, and eip712ChainId are JSON strings, not numbers — the server serializes Java long / Long as strings so JavaScript does not lose precision above 2^53.

Response Fields ​

FieldTypeDescription
codeinteger0 for success, non-zero for error
msgstringHuman-readable message
data.merchantAddressstringMerchant address that deployed the split contract
data.merchantChannelstringMerchant order channel; returns the default value default when the request leaves it empty
data.blockChainstringBlockchain name (e.g. ETH, TRON, BSC, POLYGON)
data.tokenSymbolstringToken symbol (e.g. usdt, usdc)
data.createChannelintegerCreation channel; 0 = created from the merchant dashboard, 1 = created via api key
data.merchantOrderIdstringThe merchant order ID you supplied when creating the order
data.payOrderIdstringUnique order ID generated by HashNut (26-character ULID)
data.tokenAddressstringContract address of the order's payment token, e.g. the USDT contract address
data.receiptAddressstringReceipt address of the order; the customer sends the token here to pay
data.amountnumberAmount due on the order
data.stateintegerOrder state (0 = INIT). See Order States
data.accessSignstringCredential required by later query / confirm calls — persist it
data.rateintegerFee rate; divide by rateBase for the actual ratio
data.obtainAmountnumberAmount the merchant receives after the platform fee
data.platformFeenumberPlatform fee; only charged when the merchant withdraws
data.expireDurationstringExpiration in seconds
data.underPaidboolWhether the order was underpaid. false while the customer has not paid; true once they pay less than the amount due, and it stays true after they top the order up in full
data.paidAmountnumberAmount the customer has paid so far
data.createTimedateOrder creation time

TIP

Store payOrderId, merchantOrderId, and accessSign on your side. accessSign is an HMAC the server computes over payOrderId + merchantOrderId with your secretKey — clients cannot recompute it — and both Query Order and Confirm Payment require it.

Redirect to the payment page ​

Once the order is created, build the payment page URL like this:

https://defi.hashnut.io/pay?accessSign=${accessSign}&merchantOrderId=${merchantOrderId}&payOrderId=${payOrderId}&blockChain=${blockChain}&payApiVersion=v4

Result Codes ​

Business errors do not use a dedicated error-code range; everything comes back through code plus msg, and msg carries the actual reason:

codeDescription
0Success
-1Failed
-2Exception (parameter validation failure, unmet business rule, …; see msg)
-3Unauthorized
-4Unauthenticated

Common msg values when creating an order:

msgMeaning
can not find api key by accessKeyId[...]accessKeyId does not exist, or is not an api key
invalid request signSignature mismatch — see Authentication
request timestamp out of allowed window, ...Timestamp outside the ±5 minute window; usually a skewed clock
duplicate request uuid, replay rejectedhashnut-request-uuid was reused
client ip [...] not allowedYour egress IP is not in the api key's bindIp allowlist
coin not support / chain not supportThat chain or token is not enabled
merchant order id already existDuplicate merchantOrderId for the same chain + merchant + channel
eoa splitter address not activeThe split contract is not active, or does not belong to this merchant
the minimum unit of the amount is 0.01amount has more than 2 decimal places
max expire duration is 259200expireDuration exceeds 72 hours