Hosted Checkout mode is Infini's most recommended integration method. Merchants only need to create orders, redirect to checkout_url, and handle Webhooks to complete payment integration. This chapter only contains API documentation and corresponding field descriptions for Hosted Checkout mode.
All API prefix:
/v1/acquiring
POST /v1/acquiring/order
Used to create an order and return the hosted checkout access URL (checkout_url).
Content-Type: application/json
Date: {GMT Time}
Authorization: Signature ...| Field | Type | Required | Description |
|---|---|---|---|
| amount | string/number | Yes | Order fiat amount (up to 6 decimal places) |
| currency | string | Yes | Fiat currency, e.g. "USD" |
| request_id | string | Yes | Merchant-generated idempotency key, UUID "a759b99a-9d22-433d-bced-ab1d2e1bea1d" |
| client_reference | string | No | Merchant custom order number, recommended to be unique |
| description | string | No | Order description |
| expires_in | number | No | Order expiration relative time (Unix seconds); use backend default if not provided |
| merchant_alias | string | No | Merchant display name (overrides backend configuration) |
| success_url | string | No | Redirect address after successful order payment |
| failure_url | string | No | Redirect address after failed order payment |
{
"order_id": "10290d05-xxxx",
"amount": "100",
"currency": "USD",
"checkout_url": "https://checkout.infini.money/pay/xxxx",
"expires_in": 3600
}GET /v1/acquiring/order?order_id ={order_id}
Returns real-time order status information.
Real-time calculated field reflecting the order's current payment progress (based on amount_confirmed vs order_amount).
| Value | Description |
|---|---|
pending | Awaiting payment, no funds received |
partial_paid | Partial payment, received partial funds but insufficient |
paid | Paid, received sufficient funds |
overpaid | Overpaid, received funds exceed order amount |
expired | Expired |
closed | Expired with only partial funds received |
Database stored field recording the order's processing status.
| Value | Description |
|---|---|
pending | Awaiting payment |
processing | Processing (partial funds received) |
paid | Paid |
partial_paid | Partial payment expired |
expired | Expired without payment |
Webhook Events The status field in Webhook is consistent with pay_status in the query interface.
{
"order_id": "ord-123",
"status": "processing",
"pay_status": "processing",
"amount": "100",
"currency": "USD",
"amount_confirming": "0",
"amount_confirmed": "0.5",
"expires_at": 1763512195,
"created_at": 1763512000,
"exception_tags": ["wrong_currency"],
"client_reference": "ORDER-001"
}POST /v1/acquiring/token/reissue
Used to regenerate the hosted checkout URL, suitable for scenarios such as payment page closure or Token expiration.
| Field | Type | Required | Description |
|---|---|---|---|
| order_id | string | Yes | Unique order ID |
{
"order_id": "ord-123",
"checkout_url": "https://checkout.infini.money/pay/xxxx"
}Merchants can configure Webhook receiving address in the backend. When order status changes, Infini will actively push the following events:
- order.created
- order.processing
- order.completed
- order.expired
- order.late_payment
| Header | Description |
|---|---|
| X-Webhook-Timestamp | Unix timestamp |
| X-Webhook-Event-Id | Unique event ID |
| X-Webhook-Signature | Webhook HMAC signature |
{
"event": "order.completed",
"order_id": "ord-123",
"client_reference": "ORDER-001",
"amount": "100",
"currency": "USD",
"status": "paid",
"amount_confirmed": "100",
"amount_confirming": "0",
"created_at": 1763512195,
"updated_at": 1763512573,
"exception_tags": []
}For Webhook signature verification methods, please refer to Chapter 4: Authorization and Security Mechanisms.
All error response format:
{
"code": 40001,
"message": "Invalid request",
"detail": "expires_at must be greater than current timestamp"
}| HTTP | Code | Description |
|---|---|---|
| 400 | 40003 | amount must be positive |
| 400 | 40006 | amount must be greater than 0.01 |
| 401 | 401 | Invalid HMAC signature |
| 404 | 40401 | Order does not exist |
| 409 | 40902 | client_reference duplicate |
| 409 | 40906 | Order expired |
The following example demonstrates the complete flow: Create Order → Redirect to Checkout → Webhook → Reissue Token.
import hmac, hashlib, base64, time
from datetime import datetime, timezone
import requests
key_id = "merchant-001-prod"
secret_key = b"your-secret-key"
def create_order(amount):
method = "POST"
path = "/v1/acquiring/order"
gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
signing_string = f"{key_id}\n{method} {path}\ndate: {gmt_time}\n"
signature = base64.b64encode(
hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest()
).decode()
response = requests.post(
f"https://openapi.infini.money{path}",
json={
"amount": amount,
"currency": "USD",
"client_reference": "ORDER-2024-001",
"description": "Product purchase",
"expires_at": int(time.time()) + 3600
},
headers={
"Date": gmt_time,
"Authorization": f'Signature keyId="{key_id}",algorithm="hmac-sha256",headers="@request-target date",signature="{signature}"',
"Content-Type": "application/json"
}
)
response.raise_for_status()
return response.json()@app.route('/create-payment', methods=['POST'])
def create_payment():
order = create_order(amount=request.json['amount'])
return {"checkout_url": order["checkout_url"]}@app.route('/webhook', methods=['POST'])
def handle_webhook():
event = request.json
if event['event'] == 'order.completed':
process_fulfillment(event['order_id'], event['amount_confirmed'])
elif event['event'] == 'order.processing':
update_order_progress(event['order_id'], event['status'])
elif event['event'] == 'order.expired':
mark_order_expired(event['order_id'])
return {"status": "ok"}def reissue_checkout_token(order_id):
method = "POST"
path = "/v1/acquiring/token/reissue"
gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
signing_string = f"{key_id}\n{method} {path}\ndate: {gmt_time}\n"
signature = base64.b64encode(
hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest()
).decode()
response = requests.post(
f"https://api.infini.money{path}",
json={"order_id": order_id},
headers={
"Date": gmt_time,
"Authorization": f'Signature keyId="{key_id}",algorithm="hmac-sha256",headers="@request-target date",signature="{signature}"',
"Content-Type": "application/json"
}
)
response.raise_for_status()
return response.json()