BroSettlement API
Use the current Swagger for the selected environment as the source of truth. Production is the default:
- Production Swagger UI: https://brosettlement-api.brolabel.io/swagger-integration
- Production Swagger JSON: https://brosettlement-api.brolabel.io/swagger-integration-json
- Staging Swagger UI: https://brosettlement-staging-api.brolabel.io/swagger-integration#/
- Staging Swagger JSON: https://brosettlement-staging-api.brolabel.io/swagger-integration-json
Use production unless the user explicitly selects staging or the calling onboarding skill derives
staging from app-staging.brolabel.io. Never mix credentials, Swagger, REST, or WebSocket endpoints
between environments.
Read references/api.md before designing or changing an integration.
Credential protocol
Prefer an existing API key. Ask only for:
- the API Key ID;
- the absolute path to the matching Ed25519 private PEM already stored on the user's machine;
- confirmation that the key has the required scope and that all required settings shown on the API-key page are complete.
Never ask the user to paste a private key, password, JWT, TOTP code, or session token into chat. Do not ask for the user's outbound public IP or call an IP-discovery service; direct the user to the current network and allowlist instructions shown on the API-key page. Never log in to Console or call API-key CRUD endpoints to create, edit, rotate, or revoke a key. If a new key is required, generate a local Ed25519 pair only with the required confirmation, show only the public key, and give the user manual Console instructions. Wait until the user confirms that key creation, scopes, allowlist, and active status are complete.
Load existing credentials at runtime through BROSETTLEMENT_API_KEY_ID and
BROSETTLEMENT_API_PRIVATE_KEY_FILE. Select endpoints with
BROSETTLEMENT_ENVIRONMENT=production|staging; an unset value means production. Do not copy
credential values into source files, prompts, generated examples, or shell history.
Workflow
- Prepare the bundled CLI and run its automatic version gate as described below. This may update
only the compiled CLI executable; never update
SKILL.md, references, scripts, or sibling skills. - Default to production and state that explicitly. Use staging only when it was explicitly selected or derived from the staging Console hostname.
- Fetch the current Swagger JSON before answering endpoint, command, field, enum, scope, or error-schema questions.
- Identify the exact operation, request schema, response schema, required scope, authentication headers, body-hash requirement, and idempotency requirement.
- Resolve credentials through the credential protocol and verify prerequisites without printing secrets.
- Prepare a redacted request plan: environment, method, exact target, scope, body source, idempotency behavior, and expected success response. Keep it internal or summarize it in one sentence when a calling skill defines an authorized tutorial flow; show the full plan when the user requests it or before other mutations.
- Run a safe read-only authentication probe before the first mutation when an applicable read scope exists.
- Serialize the request body exactly once and hash the exact bytes that will be sent.
- Build the canonical string with the exact request target, including the raw query string.
- Ask for confirmation immediately before a state-changing request unless a calling skill has
already captured explicit, narrowly scoped standing authorization. In particular,
$brosettlement-onboardingmay authorize exactly one staging/testnet ledger account and one linked staging/testnet wallet as part of the requested tutorial. This exception never covers MPC initialization, withdrawal, signing, production/mainnet activity, destructive actions, or additional resources. - Sign and send the confirmed request once with all required headers.
- Validate the HTTP status and parse errors using the documented error schema.
- Verify the resulting resource or lifecycle through a read endpoint and, when relevant, WebSocket events.
- For uncertain outcomes, read the resource or status before retrying. Reuse the same idempotency key only for the identical logical request.
- Report the operation, target environment, status, sanitized API response, identifiers, and verification result without exposing secrets. After a create, read the resource back and state success explicitly only when verification succeeds.
Canonical signing invariants
For REST, use exactly six newline-separated fields:
METHOD, EXACT_REQUEST_TARGET, BODY_HASH, TIMESTAMP, NONCE, and API_KEY_ID.
- Preserve the raw query string exactly as sent; never strip everything after
?. - Include
API_KEY_IDas the sixth line; never use the obsolete five-line format. - Sign the same serialized body bytes that the HTTP client sends.
- Keep
X-Idempotency-Keyoutside the canonical string. - Never reuse a nonce.
- Treat
WS_CONNECTas a separate four-line WebSocket canonical; never reuse REST signing logic.
If the bundled Go client cannot be used, implement these same invariants in the user's language and verify a fixed timestamp/nonce test vector locally before any live mutation. Do not copy a signing algorithm from another skill or document unless it matches the selected environment's current Swagger and the current operation-specific requirements in this skill.
Use the bundled CLI
Use the unified Go CLI as the default execution surface. On the first request, or when the binary is missing, build it from the bundled source:
./scripts/build-cli.sh
At the start of every request that activates this skill, run exactly one automatic update check before any BroSettlement API operation:
./scripts/go/bin/brosettlement update --auto
./scripts/go/bin/brosettlement version
The updater accepts only published cli-vMAJOR.MINOR.PATCH GitHub Releases from the official
repository, selects the current OS/architecture binary, verifies checksums.txt and any GitHub
SHA-256 asset digest, verifies the downloaded CLI-reported version, and atomically replaces only
the current executable. It must never pull, clone, rewrite, or update skill content.
If GitHub is unavailable, no published CLI release exists yet, the platform is unsupported, the checksum fails, or the executable directory is not writable, report the skipped update briefly and continue with the installed CLI when it supports the required command. Never weaken checksum or source validation to make an update succeed.
Keep cmd/list-commands, cmd/api-request, and cmd/ws-listener only as legacy-compatible entry
points. Do not assemble signatures with ad hoc shell commands when the unified CLI is available.
Present commands to the user
When teaching or returning a reusable command in chat, use the portable @brosettlement command
surface instead of exposing the skill's internal executable path. Present commands in this form:
# Full command list
@brosettlement commands
# Search by topic
@brosettlement commands wallets
@brosettlement commands "ledger balance" --json
# Signed REST request
@brosettlement api GET '/api/v1/wallets'
# MPC status
@brosettlement mpc status
# WebSocket
@brosettlement websocket listen --stop-after 30s
Treat @brosettlement as the user-facing invocation handled by the installed skill. When actually
executing the operation, resolve it to the bundled verified CLI at
./scripts/go/bin/brosettlement (or the equivalent absolute installed path). Show the native path
only for direct-shell troubleshooting, builds, updates, or when the user's agent does not support
the @brosettlement command surface.
Answer API command questions
Use the Go command lister whenever the user asks what is available or asks for an operation by topic. It fetches Swagger on every run.
./scripts/go/bin/brosettlement commands
./scripts/go/bin/brosettlement commands wallets
./scripts/go/bin/brosettlement commands "ledger balance" --json
Return matching HTTP methods, paths, and Swagger summaries. Then inspect the selected operation in Swagger JSON before generating payloads or code. Do not answer from the bundled endpoint snapshot when live staging Swagger is reachable.
Send signed REST requests
Prefer the Go request client:
export BROSETTLEMENT_API_KEY_ID="<uuid>"
export BROSETTLEMENT_API_PRIVATE_KEY_FILE="/secure/path/private.pem"
./scripts/go/bin/brosettlement api GET '/api/v1/wallets'
./scripts/go/bin/brosettlement api POST '/api/v1/wallets' \
--body-file /secure/path/create-wallet.json \
--confirm
The client signs the exact target and body bytes, adds required empty-body hashes and idempotency
keys for the operations currently documented by Swagger, sends the request, and prints a
structured response. GET, HEAD, and OPTIONS run directly. Every other method requires
--confirm. Supply it only after explicit authorization: either immediate user confirmation or
narrow standing authorization defined by the calling skill. The onboarding exception covers only
one staging/testnet ledger account and one linked staging/testnet wallet; it does not remove the
CLI safeguard or authorize any other mutation.
For POST /api/v1/mpc/initialize, follow the current selected-environment operation contract
exactly. The verified production and staging contracts currently require:
- send the exact two-byte JSON body
{}withContent-Type: application/json; - set
X-Api-Body-Hashand the canonicalBODY_HASHline to44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a; - never send a zero-length body or reformat the payload.
The guarded mpc initialize command supplies {} automatically. Do not retry alternative
body/hash combinations after an uncertain outcome; check GET /api/v1/mpc/status first and
reuse the same idempotency key only for the same logical initialization.
Use the guarded convenience commands during onboarding:
./scripts/go/bin/brosettlement mpc status
./scripts/go/bin/brosettlement mpc initialize \
--idempotency-key '<stable-key-for-this-initialization>' \
--confirm
The dependency-free Node.js header generator remains available when only signing headers are needed:
Use scripts/sign-request.mjs to produce request headers from an exact method, request target, and optional body file:
BROSETTLEMENT_API_KEY_ID="<uuid>" \
BROSETTLEMENT_API_PRIVATE_KEY_FILE="/secure/path/private.pem" \
node scripts/sign-request.mjs \
--method POST \
--target /api/v1/wallets \
--body-file /tmp/request.json \
--idempotency-key "<stable-key-for-this-logical-request>"
Send the same bytes from --body-file; reformatting JSON after signing invalidates the body hash and signature.
If a documented operation requires idempotency and --idempotency-key is omitted, the generator
adds req-<nonce>. Pass an explicit stable key when preparing a request that may be retried.
Listen to WebSocket events
Use the Go listener:
export BROSETTLEMENT_API_KEY_ID="<uuid>"
export BROSETTLEMENT_API_PRIVATE_KEY_FILE="/secure/path/private.pem"
./scripts/go/bin/brosettlement websocket listen \
--log-path ./brosettlement_ws_listener.log
For a bounded smoke test:
./scripts/go/bin/brosettlement websocket listen --stop-after 30s
The listener uses the separate WS_CONNECT canonical string, reconnects after failures, and
writes structured JSON lines to stdout and a protected local log. Never log the signed WebSocket
URL because its query contains authentication material.
Safety rules
- Never invent endpoints, fields, scopes, network identifiers, or status values.
- Never expose or request a private key when a public key, key ID, signature, or redacted diagnostic is sufficient.
- Never request a password, JWT, TOTP code, or authenticated Console session to manage API keys.
- Never create, edit, rotate, or revoke API keys for the user; API-key management is user-only.
- Never log canonical strings when they may contain sensitive query parameters.
- Treat production and staging as distinct API environments, and testnet and mainnet as distinct blockchain targets. Production is the default API environment, but mainnet activity still requires explicit authorization.
- Treat create, withdrawal, MPC initialization, and signing actions as state-changing. Confirm the intended resource and environment before executing them.
- Do not retry a mutation with a new idempotency key after an unknown outcome until the existing outcome has been checked.
- Do not claim success from an HTTP request alone; verify the resulting resource or terminal lifecycle status.
WebSocket
REST and WebSocket signing formats differ. Use the WebSocket canonical format in the API reference and require websockets:read. Consume events idempotently by event ID, tolerate duplicates and reconnects, persist cursors when supported, and reconcile events against REST resources and ledger records.