Commands

agent-commerce resolve

Record an operator verdict on one unresolved payment attempt, once, with its reason and actor.

Usagebash
agent-commerce resolve <attemptId> --status settled|rejected --reason <text>
                       [--reference <ref>] [--actor <name>] [--confirm-expired]
                       [--config <path>] [--env-file <path>]

Records an operator's verdict on one unresolved payment attempt, including one that reconcile left unknown. It opens the receipt database directly and works with the gateway running or stopped. It never settles, broadcasts or refunds, and neither verdict is checked on chain. Like reconcile, it refuses a database below schema v5 and, with AP2 enabled, an AP2 replay file that has not been imported.

Options

--status <status>settled | rejectedrequired
--reason <text>required
The reason for the verdict, stored with the resolution. At most 1024 characters.
--reference <ref>
A transaction reference, stored as your unchecked claim. It does not replace the attempt's recorded transaction ID. At most 256 characters.
--actor <name>default: the OS user
A label for who resolved it, stored with each resolution. The caller supplies it; it does not authenticate their identity.
--confirm-expireddefault: false
Confirm that an authorization with no recorded expiry can no longer land. Required to reject one; it never bypasses a recorded expiry in the future.
--config <path>
Path to the config.
--env-file <path>
Load environment variables before reading the config. Variables already set in the environment take precedence.

Rules

  • Only reserved, settlement-uncertain and legacy failed attempts can be resolved, once each.
  • A reserved attempt younger than 15 minutes is refused (too_recent): the gateway may still be settling it.
  • --status settled has no expiry check. A rejection is recorded with rejectionReason not_settled.
  • --status rejected is refused while the recorded expiry is in the future (not_expired). Without a valid recorded expiry it needs --confirm-expired (expiry_unknown); that includes Solana and NEAR attempts and those written before the journal.

--actor, --reason and --reference must not be blank, and --actor takes at most 256 characters. A bad value, any status other than settled or rejected, or an unknown attempt id fails with the error code, such as FAIL INPUT_INVALID: … or FAIL RESOURCE_NOT_FOUND: ….

console
$ agent-commerce resolve attempt_7c1e… --status settled \
    --reason "transfer seen in explorer" --reference 0x4f2c…9ab1
RESOLVED  attempt_7c1e… status=settled
HOLD      ap2 consumed

$ agent-commerce resolve attempt_93ab… --status rejected --reason "never landed"
FAIL  attempt_93ab… not resolved: No expiry is recorded for this authorization; confirm that it has expired (pass --confirm-expired) [expiry_unknown, status=settlement-uncertain]

The HOLD line appears only for an attempt with a pending AP2 hold. Refusals go to stderr and name the reason in brackets.

With AP2 enabled, the command also tries to consume or release the attempt's mandate hold, as reconcile does. A disabled provider, failed provider call or failed journal write produces a WARN: the journal still shows the hold as pending. A later reconcile run can retry it with AP2 enabled. Exit 0 means the resolution was written; 1 means a refusal or an error.

POST /api/payment-attempts/:id/resolve applies the same rules over HTTP.