Files
nick-doc/03 - API Reference/Trezor API.md
Siavash Sameni dceaf82934 audit: 2026-05-30 full-codebase audit — report, issues, docs, runbooks
Full-codebase-audit 2026-05-30 outputs:
- Audit report: 09 - Audits/Full Codebase Audit - 2026-05-30.md
- 81 issue files ISSUE-055..135 (decisions + 1 skipped no-brainer).
- Scanner docs from scratch (was zero): architecture, data model, API ref, payment
  flow, operations runbook + repo README.
- Doc-sync updates across API reference, data models, flows, design system.
- Secret Rotation Runbook (08 - Operations) for the exposed credentials.
- Reusable workflow guide (07 - Development) + .claude/workflows/full-codebase-audit.js.

Issues remain status:open intentionally — the code fixes are uncommitted-then-committed
working-tree changes per repo and aren't "resolved" until merged/deployed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 18:48:04 +04:00

212 lines
4.5 KiB
Markdown

---
title: Trezor API
tags: [api, payments, trezor, safekeeping]
---
> **Last updated:** 2026-05-30 — break-glass mode added (commit `b21df25`)
# Trezor API
The Trezor API is mounted at `/api/trezor`. It is optional support for hardware-backed safekeeping and does not replace Request Network checkout, the funds ledger, or the broader Safe/multisig custody roadmap.
Enforcement is controlled by:
```env
TREZOR_SAFEKEEPING_REQUIRED=false
```
Only the literal value `true` makes Trezor proof mandatory during release/refund confirmation. When unset or `false`, release/refund flows continue without Trezor proof.
## Break-glass mode
When `TREZOR_SAFEKEEPING_REQUIRED=true` and the Trezor is unavailable (lost, dead battery, etc.), an admin can activate break-glass mode to bypass Trezor for up to 1 hour. Break-glass state is in-memory only and resets on server restart.
See [[Admin API]] — _Break-glass (Trezor bypass)_ section for the three management endpoints (`GET`, `POST`, `DELETE /api/admin/settings/break-glass`). Activating break-glass fires an immediate Telegram alert via `tgNotify`.
## GET /api/trezor/registration-message
Builds the exact message the user must sign to register a Trezor xpub.
Auth: bearer JWT
Query:
```text
xpub=<extended public key>
registrationAddress=<first derived address>
```
Response:
```json
{
"success": true,
"data": {
"message": "Amanat escrow Trezor registration\n..."
}
}
```
## POST /api/trezor/register
Registers a Trezor xpub after the first derived address signs the registration challenge.
Auth: bearer JWT
Body:
```json
{
"xpub": "xpub...",
"registrationAddress": "0x...",
"proofMessage": "Amanat escrow Trezor registration\n...",
"proofSignature": "0x...",
"basePath": "m/44'/60'/0'",
"deviceLabel": "Office Trezor"
}
```
Validation:
- Rejects private extended keys (`xprv`, `tprv`).
- Requires `registrationAddress` to equal xpub-derived `m/44'/60'/0'/0/0`.
- Requires `proofSignature` to recover `registrationAddress`.
Response:
```json
{
"success": true,
"data": {
"xpubFingerprint": "0x...",
"registrationAddress": "0x...",
"basePath": "m/44'/60'/0'",
"nextAddressIndex": 1
}
}
```
## GET /api/trezor/account
Returns the caller's active Trezor registration summary. If no Trezor has been registered for the authenticated user, returns `{ registered: false }` without an error.
Auth: bearer JWT
Response when registered:
```json
{
"success": true,
"data": {
"registered": true,
"xpubFingerprint": "0x...",
"registrationAddress": "0x...",
"basePath": "m/44'/60'/0'",
"deviceLabel": "Office Trezor",
"nextAddressIndex": 3
}
}
```
Response when absent:
```json
{
"success": true,
"data": {
"registered": false
}
}
```
## POST /api/trezor/addresses/next
Allocates or returns a deterministic receive address from the registered xpub.
Auth: bearer JWT
Body:
```json
{
"purpose": "deposit",
"paymentId": "..."
}
```
If `paymentId` already has an assigned address, the same address is returned. Otherwise the backend derives:
```text
m/44'/60'/0'/0/{nextAddressIndex}
```
## POST /api/trezor/operation-message
Builds the exact transaction-intent message an admin must sign when Trezor safekeeping is enabled.
Auth: bearer JWT, admin
Body:
```json
{
"operation": "release",
"paymentId": "...",
"transactionHash": "0x...",
"amount": 100,
"currency": "USDT",
"provider": "request.network"
}
```
Response:
```json
{
"success": true,
"data": {
"message": "Amanat escrow Trezor transaction approval\n..."
}
}
```
## POST /api/trezor/verify-operation
Admin-only standalone signature verification endpoint. Verifies a signed operation intent against the admin's registered Trezor safekeeping address without performing any release or refund. Use this to validate a Trezor proof before submitting it to the release/refund flow.
Auth: bearer JWT, admin
Body:
```json
{
"payload": {
"operation": "release",
"paymentId": "...",
"transactionHash": "0x...",
"amount": 100,
"currency": "USDT",
"provider": "request.network"
},
"message": "Amanat escrow Trezor transaction approval\n...",
"signature": "0x..."
}
```
## Release / Refund Integration
When `TREZOR_SAFEKEEPING_REQUIRED=true`, release/refund confirmation bodies must include the Trezor proof:
```json
{
"txHash": "0x...",
"amount": 100,
"trezor": {
"message": "Amanat escrow Trezor transaction approval\n...",
"signature": "0x..."
}
}
```
This proof is optional when enforcement is disabled.