Payment Flow
The complete payment lifecycle from order creation to settlement.
Sequence Diagram
View diagram source
sequenceDiagram
participant M as Merchant Server
participant H as HashNut API
participant B as Blockchain
participant C as Customer
M->>H: 1. Create Order
H-->>M: payOrderId, receiptAddress, payUrl
M->>C: 2. Redirect to payUrl / show receiptAddress
C->>B: 3. Transfer tokens to receiptAddress
B-->>H: 4. Detect incoming transfer
Note over H: Order state → PAID (1)
B-->>H: 5. Block confirmations
Note over H: Order state → CONFIRMING (2)
Note over H: Order state → SUCCESS (3)
H->>M: 6. POST webhook to Notify URL
M-->>H: 7. HTTP 200 "success"
Step-by-Step
| Step | Action | Description |
|---|---|---|
| 1 | Create Order | Merchant calls POST /v4.0.0/pay/orders/api. HashNut returns receiptAddress and payOrderId. |
| 2 | Display Payment | Redirect customer to payUrl, or build your own page with receiptAddress and amount. |
| 3 | Customer Pays | Customer sends the token amount to receiptAddress on the specified chain. |
| 4 | Detection | HashNut detects the transfer. Order state → PAID (1). |
| 5 | Confirmations | HashNut waits for required block confirmations. State → CONFIRMING (2), then SUCCESS (3). |
| 6 | Webhook | HashNut POSTs to the merchant's Notify URL with the payment result. |
| 7 | Acknowledge | Merchant responds with HTTP 200 + body success. |
State Flow
View diagram source
stateDiagram-v2
[*] --> INIT: Create Order
INIT --> PAID: Payment detected
INIT --> EXPIRED: Timeout
INIT --> CANCELED: Merchant cancels
PAID --> CONFIRMING: Tx in block
CONFIRMING --> SUCCESS: Confirmations reached
CONFIRMING --> FAILED: Tx reverted
SUCCESS --> FINISH: Funds settled
Underpayment Handling
If the customer sends less than the required amount, HashNut creates a supplement order for the remaining balance.
| Scenario | Behavior |
|---|---|
| Partial payment | Supplement order created for the difference |
| Multiple partials | Each partial generates a new supplement until full amount covered |
| Query supplements | Use Query Supplements API |
WARNING
Supplement orders share the same payOrderId. Always check the supplement list when the order state does not progress to SUCCESS.
Order Expiration
- Default expiration: configurable via
expireDuration(max 259,200 seconds = 3 days) - Expired orders release their receipt address back to the pool
- Expired orders cannot be resumed — create a new order
DANGER
Do NOT reuse receipt addresses from expired orders. Always create a new order to get a fresh address.
