JSON Output Contract¶
Bullpen commands that support --output json are intended for scripts, agents, and dashboards. This page defines the shared JSON contract used by command-reference pages.
Successful Output¶
Non-streaming commands emit a single JSON document to stdout and then exit. The top-level value is normally an object envelope with command-specific fields. Some older commands may emit an array or a narrower object; command pages document the representative top-level keys for automation.
Streaming commands, such as websocket watches, emit one JSON document per event line. Consumers should parse each line independently.
Upstream API Shape¶
--output json is the Bullpen command contract. It is not automatically the raw upstream API response.
Command docs use these terms when the distinction matters:
| label | meaning |
|---|---|
exact |
The command or documented adapter matches the upstream endpoint's method, parameters, and response shape. |
normalized |
Bullpen calls an upstream API or SDK path, then returns a stable Bullpen envelope or field names for CLI and agent use. |
proxied |
Bullpen intentionally routes through Bullpen services for auth, safety, or trade execution instead of calling the upstream endpoint directly. |
Polymarket trade placement commands such as bullpen polymarket buy, sell, limit-buy, and limit-sell are proxied through Bullpen's trade path. They should not be treated as raw CLOB POST /order calls. Read-only market data commands may also normalize rows for stable CLI output.
Error Envelope¶
When JSON mode can handle an error before process exit, the CLI emits a single JSON object. Consumers should accept this shape:
| key | type | nullable | notes |
|---|---|---|---|
ok |
boolean | yes | false when the central typed error envelope is present |
code |
string | yes | Stable dotted error family, for example auth.login_required, auth.device_login_stalled, wallet.selection_disagreement, or redeem.discovery_rate_limited; prefer this over prose when present |
incident_code |
string | yes | Stable incident label for support-owned terminal cases, for example PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY |
recoverability |
string | yes | Machine-readable recovery class such as login_required, state_inspection_required, retryable_without_action, user_action_required, or support_required |
requires_login |
boolean | yes | Whether the next safe action requires bullpen login |
safe_to_retry |
boolean | yes | Whether the same operation can be retried without additional state inspection |
next_command |
string | yes | Single support-safe bullpen ... command to run next, if one exists |
terminal |
boolean | yes | Whether the command should stop until the next action completes |
write_mutations_allowed |
boolean | yes | Whether CLI write commands are allowed for the diagnosed state |
backend_action_required |
boolean | yes | Whether support-side action is required before local writes are safe |
status_source |
string | null | yes | Authoritative recovery-status source when available; null means unavailable |
status_updated_at |
string | null | yes | Authoritative recovery-status timestamp when available; null means unavailable |
eta |
string | null | yes | Recovery ETA when authoritative service data exists; null means unavailable |
support_safe_evidence |
object | yes | Redacted support context such as typed code, legacy error code, service, operation, auth state, or bounded device-login stall counters |
error |
string | no | Short human-readable failure summary |
error_code |
string | yes | Legacy or command-specific support code. Prefer code when both are present. |
support_safe_cause |
string | yes | Support-safe machine label for the diagnosed cause. It is a string enum, not a boolean. |
retryable_without_action |
boolean | yes | Whether the exact same command can be retried before running diagnostics or inspecting state. |
recovery_action |
string | yes | Ownership class for the next action, such as retry_later, contact_support, or support_backend_if_repeated. |
next_action |
string | yes | Human-readable next step when an older or command-specific envelope does not emit next_command. |
chain |
array |
yes | Sanitized cause chain when emitted by the central CLI error renderer; omits the top-level error frame |
caused_by |
array |
yes | Legacy error chain field when available |
hint |
string | yes | Recovery guidance when available |
recovery_command |
string | yes | Suggested bullpen ... command without internal sentinel wrappers |
recovery |
object | yes | Canonical money-path recovery projection for Polymarket trade, relayer, wallet-routing, redeem, and provider failures. Use this before scraping command-specific prose. |
recovery_plan |
object | yes | Shared account-level recovery plan emitted by bullpen fix, bullpen recover polymarket, bullpen support, and Polymarket wallet diagnostics. |
Legacy commands may emit only {"error": "..."}. Treat missing optional keys as
null. Agents should branch on code, requires_login, safe_to_retry, and
next_command when those fields are present, and should not start login,
forced logout, or money-moving retries from prose alone.
Wallet-routing diagnostics may include deposit_wallet_derivation. Valid values
include beacon_proxy, legacy_uups, and
legacy_uups_fallback_rpc_unavailable. Treat fallback provenance as evidence
quality, not as proof that the legacy address is the current trading wallet.
When retryable_without_action is false, do not keep retrying the same
command automatically. Follow the command-specific next_action. Relayer
submit failures with an unknown outcome require state reconciliation before
any retry.
Native-USDC pre-swap failures identify operation, route_owner, the
downstream execution route, resolution_owner, submission_state,
safe_to_retry, next_action, next_command, and an optional transfer trace
and balance proof. Human and JSON output use the same recovery policy. These
fields describe the pre-swap only. They do not imply that the separate
Polymarket wrap relayer batch was submitted. Compatibility output derived from
an older text-only failure includes
classification_source: "legacy_string_fallback"; typed failures do not claim
that legacy provenance. When submission is
not_submitted, the emitted read-only diagnostic is:
Live native-USDC wraps may return less USDC.e than the original request. The
CLI proceeds only when the proven output is at least 99% of the approved native
USDC input. In that bounded case, requested_amount and
requested_amount_raw preserve the original request while amount and
amount_raw identify the amount actually submitted to approve and wrap.
Live native-POL sweep output includes operation, route_owner,
submission_state, safe_to_retry, receipt_status, verification, and
balance_proof. Treat route_owner as routing metadata, not as user action.
A confirmed receipt without the expected source and recipient balance movement
is a hard failure and exits nonzero.
Recovery Objects¶
Polymarket money-path errors may include a nested recovery object. It
normalizes older top-level fields into one machine-readable shape:
| key | type | notes |
|---|---|---|
schema_version |
integer | Recovery object schema version. Current value: 1. |
status |
string | Usually mirrors the top-level command status, such as error. Recovery previews may also use values such as diagnostic_required, diagnostic_incomplete, or support_required. |
error_code |
string | Stable support code for the failure. |
incident_code |
string | Stable incident label when the recovery object describes a support-owned incident. |
code |
string | Alias for the stable incident or error code when emitted by the command. |
recovery_status |
string | Optional normalized recovery class, such as login_required, user_action_required, provider_transient, diagnostic_required, diagnostic_incomplete, support_required, or retryable. |
resolution_owner |
string | Who owns the next step: user, provider, Bullpen support, or unknown support inspection. |
next_action |
string | One human-safe next action. Prefer this over legacy prose fields when present. |
next_command |
string | One support-safe command to run next when a command is required. |
terminal |
boolean | Whether the current operation should stop until the next action completes. |
safe_to_retry |
boolean | Whether the same command may be retried without more state inspection. |
support_artifact |
string | Support-safe command to gather evidence when support owns the next step. |
funds_onchain_recoverable |
boolean | Whether the diagnosed funds are recoverable on-chain. |
cli_can_recover |
boolean | Whether the CLI can perform the recovery without support-side action. |
write_mutations_allowed |
boolean | Whether CLI write commands are allowed for the diagnosed state. |
backend_action_required |
boolean | Whether support-side action is required before local writes are safe. |
blocked_actions |
array |
Local action classes that should not be retried for the diagnosed state. |
status_source |
string | null | Authoritative recovery-status source when available; null means unavailable. |
status_updated_at |
string | null | Authoritative recovery-status timestamp when available; null means unavailable. |
eta |
string | null | Recovery ETA when authoritative service data exists; null means unavailable. |
evidence |
object | Redacted machine details copied from the command-specific envelope. |
Account-recovery commands emit recovery_plan instead of recovery.
recovery_plan has the same intent but describes account readiness rather than
one failed command. It includes status, title, reason, next_action,
terminal, safe_to_retry, resolution_owner, optional support_artifact,
and redacted evidence.
For PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY, the canonical contract is:
funds are safe and recoverable on-chain, cli_can_recover: false,
safe_to_retry: false, write_mutations_allowed: false,
backend_action_required: true, and next_command:
"bullpen support bundle --output json".
Do not retry approve, activate, reregister, wrap, trade, wallet selection,
redeposit, or login for that wallet. status_source, status_updated_at, and
eta remain null until authoritative service data exists.
bullpen recover funds --dry-run --output json emits a consolidation plan. If
that preview cannot prove order-credit state, it includes a plan-shaped
recovery object with the same status, resolution_owner, terminal,
safe_to_retry, next_action, and optional support_artifact fields.
For bullpen support --output json, next_action is the account recovery next
step. support_next_action is the artifact-handling instruction. Support
artifacts also include delivery.state: "local_file_not_uploaded",
delivery.uploaded: false, and delivery.artifact_path; the file is on this
machine and has not been uploaded. Attach the JSON file to your support ticket.
When originating_context is present, it contains only the recent command
family and typed error code, not raw arguments or error text.
Numeric Fields¶
Decimal values that represent token amounts, prices, rates, and balances may be serialized as strings to preserve precision. Examples include CLOB prices such as midpoint, Hyperliquid fields such as mark_px, and Solana token amounts. Consumers should parse numeric-as-string fields with decimal-safe libraries instead of binary floating point.
Integers used for counts, timestamps, and small indexes may be JSON numbers. When precision matters, prefer the type documented on the command page.
Some compatibility fields are raw token base units even when their names are
older and less explicit. For bullpen polymarket preflight --output json,
usdc_e_balance is the legacy raw micro-USDC.e value,
usdc_e_balance_base_units is the explicit raw micro-USDC.e value, and
usdc_e_balance_usd is the human-readable formatted value.
For bullpen polymarket positions --output json, redeemable is the
Bullpen-normalized actionable flag. It is true only when the row is expected to
pay non-zero value. upstream_redeemable preserves the raw Polymarket Data API
flag when available; a lost resolved row can have upstream_redeemable: true
and redeemable: false.
Schema Version¶
Commands may include schema_version at the top level. When present, it is an integer version for that command's JSON shape.
Commands that do not emit schema_version inherit contract version 1. Consumers should default absent schema_version to 1 and tolerate additional fields.
Simple Command Aliases¶
Simple user-journey commands such as bullpen trade buy,
bullpen trade sell, bullpen recover funds, and
bullpen recover redeem call the same underlying Polymarket handlers as the
detailed commands. In JSON mode, those simple commands may add a top-level
command_alias object:
| key | type | notes |
|---|---|---|
command_alias.command |
string | Simple command the user or agent ran, for example bullpen trade buy |
command_alias.underlying_command |
string | Detailed command family that produced the payload, for example bullpen polymarket buy |
command_alias.journey |
string | High-level journey, such as trade or recover |
Treat this object as additive metadata. It does not replace command-specific
fields and is not emitted by the detailed bullpen polymarket ... command when
run directly.
Most command pages document JSON output with worked examples. A smaller stable
subset also has machine-validated JSON Schemas under
reference/schemas/. Absence of a formal schema does not
mean JSON is unsupported; use the command page examples and this shared
contract for commands that do not yet have a dedicated schema file.
SIGPIPE Safety¶
JSON output is safe to pipe into tools such as head, jq, and shell pipelines. If the downstream reader closes the pipe early, Bullpen treats SIGPIPE or broken-pipe writes as a normal pipe termination and exits without printing a Rust panic or backtrace.
Stability¶
Patch releases may add optional or nullable fields and may add values to existing string enums. They should not remove documented fields, rename documented fields, or change documented field types.
Minor releases may add required fields, increment schema_version, or introduce a new envelope for a command when the old shape remains documented during migration.
Major releases may remove fields, rename fields, or change field types. Command pages and this contract should be updated in the same release.
Consumer Guidance¶
Treat unknown fields as non-breaking. Treat absent optional fields as null. For strict automation, validate the exact command path in the target Bullpen version and pin the CLI version used by production jobs.