POST /v1/qr

Render a base64 PNG QR code for the order pay-in address.

POST/api/v1/qrAuth required

Returns a base64 PNG data: URL of the order’s pay-in address, rendered at 256×256 with error-correction level M and a 2-module quiet zone. Drop the value directly into an <img src="…"> to show the deposit QR inline.

Caching. Successful responses are served from a one-hour server-side cache. The cached PNG is immutable per order, and every call is gated by partner ownership before the cache is consulted.

Request

Body
idstring (UUID)required
Order id from /v1/create. Same field name as /v1/order and /v1/emergency.
tokenstring (43-char base64url)required
Raw access token. Same verification contract as /v1/order; any mismatch returns code 6 NOT_FOUND.

Response

200 OK
{
  "code": 0,
  "msg": "",
  "data": {
    "qrPng": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAA..."
  }
}
Fields
data.qrPngstring (data: URL)
data:image/png;base64,… of the rendered QR. The encoded payload is the raw pay-in address; the address itself never appears in this response and must be fetched from data.from.address on /v1/order.

Errors

codemsgHTTPDescription
1INVALID_REQUEST400Body fails validation: unsupported asset, disabled pair, unparseable amount, invalid address, FLOAT without refundAddress, malformed Idempotency-Key. The same code + HTTP 409 fires on Idempotency-Key reuse with a different payload.
2AUTH_REQUIRED401One of X-API-KEY / X-API-SIGN is missing on an endpoint that requires authentication.
3AUTH_INVALID401Unknown key, malformed signature, signature mismatch, expired or replayed nonce, decrypt failure. Generic body — never an oracle for "which" of those it was.
4AUTH_DISABLED401Partner record enabled = false. Reachable only with a valid signature, so the operator can distinguish a kill-switched partner from a stolen-and-revoked key.
5RATE_LIMIT429Per-partner weight budget exhausted within the 60-second sliding window. Response includes Retry-After: <seconds>.
6NOT_FOUND404Order does not exist OR exists but belongs to a different partner OR exists and the token is wrong. The three cases collapse to one envelope.
99INTERNAL500Unexpected server-side condition. Already logged on our side; safe to retry.

Code examples

# Returns base64 PNG data URI of the order's pay-in address.
APIKEY="rWqZ...Rg"
APISECRET="G1JV...n4"
NONCE=$(openssl rand -hex 16)
BODY='{"id":"1f8c5e0b-9c92-4d6a-b0a8-3c5f8d6e7a4b","token":"v8k3-Po9...43-char-base64url"}'
SIGN=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$APISECRET" | sed 's/^.* //')

curl -sS -X POST "https://0trace.io/api/v1/qr" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: $APIKEY" \
  -H "X-API-SIGN: $SIGN" \
  -H "X-API-NONCE: $NONCE" \
  --data "$BODY"

Rate limit

Weight 5 per call. 5 weight units per call (heavier than /v1/order's 1 because PNG generation is CPU, lighter than /v1/create's 50).

Notes

Soft-deleted orders. Cached QRs are not served for soft-deleted orders. The route re-checks visibility on every call, even when the cache would otherwise hit. The response collapses to code 6 NOT_FOUND in that case.

No raw address in the body. Use this endpoint when you want a QR. Use /v1/order when you want the text address. They are separate so a UI that only renders a QR does not need to handle the address string format.

Partner API.
Same engine as 0trace.

A private partner integration surface. Signed quotes, server-side pricing, webhook delivery, multiple reference codes, and a self-serve cabinet — all backed by the production exchange engine.

Support

Questions? Answers.

Get the latest updates

Follow us on X

The 0trace team will never ask for KYC or AML. We retain no logs, metadata, or tracking cookies.

Learn more