# GENERATED — do not edit by hand. Run: pnpm api:openapi:generate
openapi: 3.1.0
info:
  title: FortFi REST API
  version: 1.0.0
  description: |-
    Human-developer REST API for FortFi treasury operations.
    Parity with the public MCP tool catalog.
    Agents may prefer MCP; both surfaces are public and supported.

    Authentication: `Authorization: Bearer frtfi_hu_*` or `frtfi_ag_*`.
    Session cookies are not accepted on /api/v1 routes.

    OpenAPI spec: https://fortfiapp.com/openapi/fortfi-v1.yaml
servers:
  - url: https://fortfiapp.com/api/v1
    description: Production
tags:
  - name: Portfolio & balances
    description: Wallets, holdings, portfolio totals, token discovery
  - name: Transfers & sends
    description: USDC transfers to allowlisted recipients
  - name: Swaps & bridges
    description: Quotes, allowances, same-chain swaps, cross-chain bridges
  - name: Yield
    description: Morpho vault markets, positions, deposit and withdraw proposals
  - name: Payment requests
    description: Shareable payment request links
  - name: Recipients & policy
    description: Allowlist, policy limits, routing guides, API guide
  - name: Account & audit
    description: Audit log and account-level reads
  - name: Wallets & accounts
    description: Create, rename, and metadata proposals
  - name: Security & cosigners
    description: Co-signer memberships, rules, invites, approvals
  - name: Governance
    description: Backup wallets and governance change requests
  - name: Agents
    description: Agent fleet and claim-link utilities
  - name: Proposals
    description: Confirm any propose_* action
paths:
  /wallets:
    get:
      operationId: listWallets
      summary: List treasury wallets
      description: "List FortFi wallets for this account: chain, address, nickname, metadata tags, and default flag. Optional
        metadataKey/metadataValue filter (exact match)."
      tags:
        - Portfolio & balances
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: list_wallets
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  wallets:
                    - id: 550e8400-e29b-41d4-a716-446655440000
                      name: Treasury
                      address: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
                      chain: base
        "400": &a1
          $ref: "#/components/responses/BadRequest"
        "401": &a2
          $ref: "#/components/responses/Unauthorized"
        "403": &a3
          $ref: "#/components/responses/Forbidden"
        "404": &a4
          $ref: "#/components/responses/NotFound"
        "429": &a5
          $ref: "#/components/responses/TooManyRequests"
      parameters:
        - name: metadataKey
          in: query
          required: false
          schema:
            type: string
            description: Filter wallets that include this metadata key (optional)
        - name: metadataValue
          in: query
          required: false
          schema:
            type: string
            description: When set with metadataKey, require an exact value match
  /recipients:
    get:
      operationId: listRecipients
      summary: List allowlisted recipients
      description: "List all allowlisted recipients. Includes cooldown status: `cooldownActive: true` means the recipient
        cannot yet receive funds (24-hour gate)."
      tags:
        - Recipients & policy
      security:
        - bearerAuth: []
      x-fortfi-scope: recipients:read
      x-fortfi-mcp-tool: list_recipients
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  recipients:
                    - id: 660e8400-e29b-41d4-a716-446655440001
                      label: Vendor ACME
                      address: "0x1234567890123456789012345678901234567890"
                      status: approved
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /audit-log:
    get:
      operationId: listAuditLog
      summary: List audit log entries
      description: "Recent account activity: transfers, swaps, security events."
      tags:
        - Account & audit
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: list_audit_log
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  entries:
                    - id: 990e8400-e29b-41d4-a716-446655440004
                      action: transfer.sent
                      createdAt: 2026-07-13T08:00:00.000Z
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: number
            description: Max entries to return (default 20, max 100)
  /policy/limits:
    get:
      operationId: getPolicyLimits
      summary: Get send policy limits and caps
      description: "Current policy limits: per-tx/daily/monthly caps (USDC smallest units). Agent accounts include billingPlan
        (personal|startup), billingPlanName, maxWallets, tier, and subscription expiry."
      tags:
        - Recipients & policy
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: get_policy_limits
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  dailySendCapUsd: "5000.00"
                  perTransferCapUsd: "1000.00"
                  v0HardCapUsd: "5.00"
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /portfolio:
    get:
      operationId: getPortfolio
      summary: Portfolio balances and USD summary
      description: "Full portfolio summary across all wallets: token balances with USD values, 24h change, and total net worth."
      tags:
        - Portfolio & balances
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: get_portfolio
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  totalUsd: "12345.67"
                  wallets:
                    - id: 550e8400-e29b-41d4-a716-446655440000
                      name: Treasury
                      address: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
                      chain: base
                      balanceUsd: "12345.67"
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /portfolio/holdings:
    get:
      operationId: getAccountHoldings
      summary: Holdings for a single wallet
      description: Token holdings for a specific wallet, with USD values and 24h change.
      tags:
        - Portfolio & balances
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: get_account_holdings
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  value: null
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: walletId
          in: query
          required: true
          schema:
            type: string
            description: Wallet id from list_wallets
  /tokens/discover:
    get:
      operationId: discoverTokens
      summary: Discover tokens by chain (trending, gainers, volume)
      description: "Market-wide token discovery on a FortFi chain (USD). Use for trending/gainers/volume/mcap — NOT the
        browser Explore REST route. Sorts: gainers_1d, gainers_30d, gainers_90d, market_cap, volume_1d. Returns contract
        addresses for propose_swap / propose_bridge."
      tags:
        - Portfolio & balances
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: discover_tokens
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: chainId
          in: query
          required: true
          schema:
            type: string
            description: FortFi chain id, e.g. base-mainnet, ethereum-mainnet
        - name: query
          in: query
          required: false
          schema:
            type: string
            description: Optional name/symbol filter, e.g. 'USDC' or 'wrapped'
        - name: limit
          in: query
          required: false
          schema:
            type: number
            description: Max results (default 10, max 25)
        - name: sort
          in: query
          required: false
          schema:
            type: string
            description: "Explore sort: gainers_1d, gainers_30d, gainers_90d, market_cap, volume_1d (default market_cap)"
        - name: verifiedOnly
          in: query
          required: false
          schema:
            type: boolean
            description: Only verified tokens
  /trade/routing-guide:
    get:
      operationId: getSwapRoutingGuide
      summary: Swap and bridge routing recommendations
      description: Returns which swap/bridge tool to use for a given from→to chain pair, with notes on protocols supported.
      tags:
        - Recipients & policy
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: get_swap_routing_guide
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  value: null
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: fromChainId
          in: query
          required: true
          schema:
            type: string
            description: Source chain id
        - name: toChainId
          in: query
          required: true
          schema:
            type: string
            description: Destination chain id
  /policy/token-spender-grants:
    get:
      operationId: listTokenSpenderGrants
      summary: List ERC-20 spender approvals
      description: List active ERC-20 token approvals (spender grants) on this account. Useful before proposing a swap to
        confirm the CoW vault is approved.
      tags:
        - Recipients & policy
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: list_token_spender_grants
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  token_spender_grants: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /guide:
    get:
      operationId: getGuide
      summary: API capabilities, workflows, and limits
      description: "FortFi MCP capability guide: onboarding paths, pricing, limits, workflows, and full tool catalog. Call
        first when unsure which tool to use (e.g. market research → discover_tokens, not the Explore UI REST route)."
      tags:
        - Recipients & policy
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: get_mcp_guide
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  topic: overview
                  workflows:
                    - list_wallets → propose_transfer → confirm
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: topic
          in: query
          required: false
          schema:
            type: string
            enum:
              - overview
              - tools
              - workflows
              - limits
              - pricing
              - all
            description: Default overview
  /payment-requests:
    post:
      operationId: createPaymentRequest
      summary: Create a shareable payment request
      description: Create a shareable payment request for a vault. Returns pid, paymentUrl, and qrPayload for humans or agents.
      tags:
        - Payment requests
      security:
        - bearerAuth: []
      x-fortfi-scope: payment_requests:write
      x-fortfi-mcp-tool: create_payment_request
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                walletMappingId:
                  type: string
                  description: Target collection vault id
                amountSmallestUnit:
                  type: string
                  description: USDC amount in smallest units (alternative to amountUsd)
                amountUsd:
                  type: number
                  description: Invoice amount in USD (1 USD = 1 USDC)
                description:
                  type: string
                  description: Optional invoice note
                externalReference:
                  type: string
                  description: Optional external invoice id
                metadata:
                  type: object
                  description: Optional metadata object
                expiryDays:
                  type: number
                  description: Days until expiry (default 30)
              required:
                - walletMappingId
              additionalProperties: false
    get:
      operationId: listPaymentRequests
      summary: List payment requests
      description: List payment requests for the authenticated account.
      tags:
        - Payment requests
      security:
        - bearerAuth: []
      x-fortfi-scope: payment_requests:read
      x-fortfi-mcp-tool: list_payment_requests
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  payment_requests: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: walletMappingId
          in: query
          required: false
          schema:
            type: string
            description: Optional vault filter
        - name: status
          in: query
          required: false
          schema:
            type: string
            enum:
              - open
              - processing
              - partially_paid
              - paid
              - expired
              - cancelled
  /payment-requests/{idOrPid}:
    get:
      operationId: getPaymentRequest
      summary: Get payment request by id or public pid
      description: Get a payment request by internal id or public pid, including settlement attempts.
      tags:
        - Payment requests
      security:
        - bearerAuth: []
      x-fortfi-scope: payment_requests:read
      x-fortfi-mcp-tool: get_payment_request
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  value: null
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: idOrPid
          in: path
          required: true
          schema:
            type: string
        - name: idOrPid
          in: query
          required: true
          schema:
            type: string
            description: Internal id or public pid
  /payment-requests/{idOrPid}/cancel:
    post:
      operationId: cancelPaymentRequest
      summary: Cancel an open payment request
      description: Cancel an open payment request with no verified settlement.
      tags:
        - Payment requests
      security:
        - bearerAuth: []
      x-fortfi-scope: payment_requests:write
      x-fortfi-mcp-tool: cancel_payment_request
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  ok: true
                  message: Request accepted
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: idOrPid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                idOrPid:
                  type: string
              required:
                - idOrPid
              additionalProperties: false
  /payment-requests/{idOrPid}/extend:
    post:
      operationId: extendPaymentRequest
      summary: Extend payment request expiry
      description: Extend an open payment request expiry (default extension window in days).
      tags:
        - Payment requests
      security:
        - bearerAuth: []
      x-fortfi-scope: payment_requests:write
      x-fortfi-mcp-tool: extend_payment_request
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: idOrPid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                idOrPid:
                  type: string
                expiryDays:
                  type: number
                  description: New expiry horizon from now (1-365)
              required:
                - idOrPid
                - expiryDays
              additionalProperties: false
  /yield/markets:
    get:
      operationId: listYieldMarkets
      summary: List Morpho yield vaults
      description: Morpho yield vaults by chain — APY, TVL. Use before propose_yield_deposit.
      tags:
        - Yield
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: list_yield_markets
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  yield_markets: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: chainId
          in: query
          required: false
          schema:
            type: string
            description: FortFi chain id or omit for all yield chains
        - name: asset
          in: query
          required: false
          schema:
            type: string
            description: Asset symbol filter, default USDC
        - name: verifiedOnly
          in: query
          required: false
          schema:
            type: boolean
            description: Only verified vaults
        - name: limit
          in: query
          required: false
          schema:
            type: number
            description: Max vaults (default 15, max 25)
  /yield/positions:
    get:
      operationId: listYieldPositions
      summary: List active yield positions
      description: User's Morpho yield positions from FortFi history.
      tags:
        - Yield
      security:
        - bearerAuth: []
      x-fortfi-scope: balances:read
      x-fortfi-mcp-tool: list_yield_positions
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  yield_positions: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /cosigners/memberships:
    get:
      operationId: listCosignerMemberships
      summary: List co-signer memberships
      description: Active co-signers on this account.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:read
      x-fortfi-mcp-tool: list_cosigner_memberships
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  cosigner_memberships: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /cosigners/rules:
    get:
      operationId: getCosignerRules
      summary: Get co-signer policy rules
      description: Amount-banded cosigner quorum rules for sends and swaps. Below-band amounts auto-execute; matching bands
        require N cosigner votes.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:read
      x-fortfi-mcp-tool: get_cosigner_rules
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  value: null
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
    put:
      operationId: updateCosignerRules
      summary: Update co-signer policy rules
      description: "Set cosigner quorum rules (send + swap USD bands). Tightening rules works with the agent key alone.
        WEAKENING them (lower required cosigners / raise the amount floor) is a GOVERN action: sign a challenge with
        your funding wallet (challengeId + walletSignature); applies immediately once signed (same as passkey in the
        UI). Amounts use USDC micro-units (1 USDC = 1000000)."
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: update_cosigner_rules
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  ok: true
                  message: Request accepted
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                rules:
                  type: array
                  items:
                    type: object
                challengeId:
                  type: string
                  description: Governance challengeId (only needed when weakening rules)
                walletSignature:
                  type: string
                  description: Funding-wallet signature over the challenge message
              required:
                - rules
              additionalProperties: false
  /cosigners/pending-approvals:
    get:
      operationId: listPendingCosignerApprovals
      summary: List pending co-signer approvals
      description: Pending actions that require this account's co-signer approval. Use when this agent is a co-signer on
        another account.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:read
      x-fortfi-mcp-tool: list_pending_cosigner_approvals
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  pending_cosigner_approvals: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: number
            description: Max entries (default 10)
  /cosigners/incoming-invites:
    get:
      operationId: listIncomingCosignerInvites
      summary: List incoming co-signer invites
      description: List pending co-signer invites sent TO this account (where this account is the invitee). Use to discover
        accounts you can become a co-signer for.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:read
      x-fortfi-mcp-tool: list_incoming_cosigner_invites
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  incoming_cosigner_invites: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /governance/requests:
    get:
      operationId: listGovernanceRequests
      summary: List open governance change requests
      description: "List open governance requests on this account: pending (awaiting signature) and legacy scheduled rows. Use
        to monitor for unexpected loosening attempts."
      tags:
        - Governance
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:read
      x-fortfi-mcp-tool: list_governance_requests
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  governance_requests: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /agents/funding-wallets:
    get:
      operationId: listFundingWalletAgents
      summary: List agents linked to funding wallets
      description: List all FortFi agent accounts funded by the same payment wallet as this agent. Use to discover agentLabel
        / userId when renewing or spawning siblings (treasury multi-agent setups).
      tags:
        - Agents
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: list_funding_wallet_agents
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  funding_wallet_agents: []
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
  /trade/quotes/swap:
    post:
      operationId: previewSwapQuote
      summary: Preview same-chain swap quote
      description: "Optional advanced step: fetch a same-chain swap quote (CoW on EVM, Jupiter on Solana) and return
        previewQuoteId. Omit previewQuoteId on propose_* to bundle quote+proposal in one call. Does not execute or move
        funds."
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: preview_swap_quote
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  quoteId: aa0e8400-e29b-41d4-a716-446655440005
                  sellAmount: "1000000"
                  buyAmount: "999500"
                  expiresAt: 2026-07-13T08:05:00.000Z
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                  description: Source wallet id
                sellTokenAddress:
                  type: string
                  description: EVM sell token (0x…) — omit for Solana
                buyTokenAddress:
                  type: string
                  description: EVM buy token (0x…) — omit for Solana
                sellMint:
                  type: string
                  description: Solana sell mint — omit for EVM
                buyMint:
                  type: string
                  description: Solana buy mint — omit for EVM
                sellSymbol:
                  type: string
                buySymbol:
                  type: string
                amountUsd:
                  type: string
                  description: Approximate sell amount in USD
                toWalletId:
                  type: string
                  description: Optional Solana receive wallet
                slippagePercent:
                  type: number
                  description: Optional Jupiter slippage 0–50
              required:
                - fromWalletId
                - sellSymbol
                - buySymbol
                - amountUsd
              additionalProperties: false
  /trade/quotes/bridge:
    post:
      operationId: previewBridgeQuote
      summary: Preview cross-chain bridge quote
      description: "Optional advanced step: fetch a cross-chain bridge quote (Fusion+ or deBridge) and return previewQuoteId.
        Omit previewQuoteId on propose_bridge to bundle quote+proposal in one call."
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: preview_bridge_quote
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  quoteId: aa0e8400-e29b-41d4-a716-446655440005
                  sellAmount: "1000000"
                  buyAmount: "999500"
                  expiresAt: 2026-07-13T08:05:00.000Z
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                toWalletId:
                  type: string
                sellSymbol:
                  type: string
                buySymbol:
                  type: string
                amountUsd:
                  type: string
              required:
                - fromWalletId
                - toWalletId
                - sellSymbol
                - buySymbol
                - amountUsd
              additionalProperties: false
  /trade/allowance:
    get:
      operationId: checkTradeAllowance
      summary: Check ERC-20 trade allowance
      description: Check ERC-20 allowance for an upcoming CoW swap (cow_swap) or Fusion bridge (fusion_bridge). Call before
        propose_swap / propose_bridge; if insufficient, use propose_token_approve then confirm.
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: account:read
      x-fortfi-mcp-tool: check_trade_allowance
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      parameters:
        - name: fromWalletId
          in: query
          required: true
          schema:
            type: string
            description: Source EVM wallet id
        - name: tokenAddress
          in: query
          required: true
          schema:
            type: string
            description: Sell token contract (0x…)
        - name: requiredAmountSmallest
          in: query
          required: true
          schema:
            type: string
            description: Required allowance in token smallest units (e.g. USDC 6 decimals)
        - name: flow
          in: query
          required: true
          schema:
            type: string
            enum:
              - cow_swap
              - fusion_bridge
            description: cow_swap = CoW VaultRelayer; fusion_bridge = 1inch Limit Order
  /agents/resend-claim-link:
    post:
      operationId: resendClaimLink
      summary: Resend agent claim link email
      description: "Resend the dashboard claim email to contactEmail (MCP agent API key only; keys:manage scope). Use when the
        original link expired (72h) or was lost. Rate limit: 3/hour."
      tags:
        - Agents
      security:
        - bearerAuth: []
      x-fortfi-scope: keys:manage
      x-fortfi-mcp-tool: resend_claim_link
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties: {}
              additionalProperties: false
  /proposals/transfers:
    post:
      operationId: proposeTransfer
      summary: Propose an allowlisted transfer
      description: Transfer USDC to an allowlisted recipient. The recipient must be approved (no active cooldown). Rejected
        with POLICY_LIMIT_EXCEEDED if above tier limits. Rejected with RECIPIENT_NOT_APPROVED if in cooldown.
      tags:
        - Transfers & sends
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_transfer
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: &a6
                  proposalId: 770e8400-e29b-41d4-a716-446655440002
                  kind: send
                  status: pending_confirm
                  message: Proposal created. Confirm with POST /api/v1/proposals/{proposalId}/confirm
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                recipientId:
                  type: string
                  description: Recipient id from list_recipients
                amountUsdc:
                  type: string
                  description: Amount in USDC as a decimal string, e.g. '5.00' for $5 USDC
                fromWalletId:
                  type: string
                  description: Source wallet id from list_wallets
                memo:
                  type: string
                  description: Optional transfer note (max 256 chars)
              required:
                - recipientId
                - amountUsdc
                - fromWalletId
              additionalProperties: false
  /proposals/recipients/add:
    post:
      operationId: addRecipient
      summary: Propose adding a recipient
      description: "Add a new payout address to the allowlist. GOVERN action: when called with an agent API key, you must sign
        a challenge with your funding wallet (call once to get the challenge, sign it, call again with challengeId +
        walletSignature). Once signed the recipient is approved immediately (no cooldown)."
      tags:
        - Transfers & sends
      security:
        - bearerAuth: []
      x-fortfi-scope: recipients:write
      x-fortfi-mcp-tool: add_recipient
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                address:
                  type: string
                  description: Wallet address (0x… or Solana base58)
                chainId:
                  type: string
                  description: FortFi chain id, e.g. base-mainnet, ethereum-mainnet, solana-mainnet
                nickname:
                  type: string
                  description: Optional display name
                challengeId:
                  type: string
                  description: Governance challengeId from the first call
                walletSignature:
                  type: string
                  description: Funding-wallet signature over the challenge message
              required:
                - address
                - chainId
              additionalProperties: false
  /proposals/recipients/approve:
    post:
      operationId: approveRecipient
      summary: Propose approving a pending recipient
      description: Approve a recipient still in cooldown (early release). A distinct active cosigner may approve directly;
        owner self-approval via an agent key is a GOVERN action requiring a funding-wallet signature (challengeId +
        walletSignature).
      tags:
        - Transfers & sends
      security:
        - bearerAuth: []
      x-fortfi-scope: recipients:write
      x-fortfi-mcp-tool: approve_recipient
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                recipientId:
                  type: string
                  description: Recipient id from list_recipients or add_recipient
                challengeId:
                  type: string
                  description: Governance challengeId from the first call
                walletSignature:
                  type: string
                  description: Funding-wallet signature over the challenge message
              required:
                - recipientId
              additionalProperties: false
  /proposals/token-approve:
    post:
      operationId: proposeTokenApprove
      summary: Propose ERC-20 approve for trading
      description: Propose max ERC-20 approval for CoW or Fusion spenders. Returns proposalId — confirm via POST
        /api/mcp/confirm before swap/bridge.
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_token_approve
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                  description: EVM wallet id
                tokenAddress:
                  type: string
                  description: Token to approve (0x…)
                flow:
                  type: string
                  enum:
                    - cow_swap
                    - fusion_bridge
              required:
                - fromWalletId
                - tokenAddress
                - flow
              additionalProperties: false
  /proposals/swaps:
    post:
      operationId: proposeSwap
      summary: Propose EVM same-chain swap
      description: "Propose an EVM CoW swap. Autonomous agents: fetches and binds a quote inline (default), or pass
        previewQuoteId from preview_swap_quote for a two-step review. confirm always signs the bound quote — same
        principle as FortFi Assist. Human session MCP: confirm requires passkey in the app."
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_swap
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                  description: Source wallet id (must be EVM, CoW-supported chain)
                sellTokenAddress:
                  type: string
                  description: Token contract address to sell (0x…)
                buyTokenAddress:
                  type: string
                  description: Token contract address to buy (0x…)
                sellSymbol:
                  type: string
                  description: Human-readable symbol of sell token, e.g. USDC
                buySymbol:
                  type: string
                  description: Human-readable symbol of buy token, e.g. ETH
                amountUsd:
                  type: string
                  description: Sell amount in USD
                previewQuoteId:
                  type: string
                  description: Optional — from preview_swap_quote for explicit quote review before propose
                slippagePercent:
                  type: number
                  description: Optional slippage tolerance 0–50 (default 0.5)
              required:
                - fromWalletId
                - sellTokenAddress
                - buyTokenAddress
                - sellSymbol
                - buySymbol
                - amountUsd
              additionalProperties: false
  /proposals/solana-swaps:
    post:
      operationId: proposeSolanaSwap
      summary: Propose Solana same-chain swap
      description: "Propose a Solana Jupiter swap. Autonomous agents: inline quote by default, or previewQuoteId for two-step
        review. confirm signs the bound quote."
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_solana_swap
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                  description: Solana wallet id to sell from
                toWalletId:
                  type: string
                  description: Solana wallet id to receive (can be same as fromWalletId)
                sellMint:
                  type: string
                  description: Mint address of token to sell
                buyMint:
                  type: string
                  description: Mint address of token to buy
                sellSymbol:
                  type: string
                  description: Human-readable sell symbol
                buySymbol:
                  type: string
                  description: Human-readable buy symbol
                amountUsd:
                  type: string
                  description: Sell amount in USD
                previewQuoteId:
                  type: string
                  description: Optional — from preview_swap_quote for explicit quote review before propose
                slippagePercent:
                  type: number
                  description: Optional slippage tolerance 0–50 (default 0.5)
              required:
                - fromWalletId
                - toWalletId
                - sellMint
                - buyMint
                - sellSymbol
                - buySymbol
                - amountUsd
              additionalProperties: false
  /proposals/bridges:
    post:
      operationId: proposeBridge
      summary: Propose cross-chain bridge
      description: "Propose a Fusion+ or deBridge transfer. Autonomous agents: inline quote by default, or previewQuoteId from
        preview_bridge_quote for two-step review."
      tags:
        - Swaps & bridges
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_bridge
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                  description: Source wallet id
                toWalletId:
                  type: string
                  description: Destination wallet id (different chain)
                sellTokenAddress:
                  type: string
                  description: Token to bridge out (0x…)
                buyTokenAddress:
                  type: string
                  description: Token to receive (0x…, use same asset if bridging stable)
                sellSymbol:
                  type: string
                  description: Sell token symbol
                buySymbol:
                  type: string
                  description: Buy token symbol
                amountUsd:
                  type: string
                  description: Bridge amount in USD
                previewQuoteId:
                  type: string
                  description: Optional — from preview_bridge_quote for explicit quote review before propose
              required:
                - fromWalletId
                - toWalletId
                - sellTokenAddress
                - buyTokenAddress
                - sellSymbol
                - buySymbol
                - amountUsd
              additionalProperties: false
  /proposals/rename-account:
    post:
      operationId: proposeRenameAccount
      summary: Propose renaming a wallet account
      description: Rename a wallet (account nickname). Confirm via POST /api/mcp/confirm with the returned proposalId.
      tags:
        - Wallets & accounts
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_rename_account
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                accountId:
                  type: string
                  description: Wallet id from list_wallets
                nickname:
                  type: string
                  description: New nickname (2–64 characters)
              required:
                - accountId
                - nickname
              additionalProperties: false
  /proposals/create-account:
    post:
      operationId: proposeCreateAccount
      summary: Propose creating a new wallet account
      description: Create a new wallet on a supported chain. Optional metadata tags (e.g. customer_id). Confirm via POST
        /api/mcp/confirm. Agent accounts execute server-side when no cosigners are configured.
      tags:
        - Wallets & accounts
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_create_account
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                chainId:
                  type: string
                  description: FortFi chain id, e.g. base-mainnet, solana-mainnet
                walletName:
                  type: string
                  description: Display name for the new wallet (2–64 chars)
                metadata:
                  type: object
                  description: 'Optional flat string tags (max 20 keys), e.g. { "customer_id": "cust_123" }'
                  additionalProperties:
                    type: string
              required:
                - chainId
                - walletName
              additionalProperties: false
  /proposals/wallet-metadata:
    post:
      operationId: updateWalletMetadata
      summary: Propose updating wallet metadata tags
      description: Set metadata tags on a wallet (flat string key/value pairs; replaces existing tags). Not a money-moving action.
      tags:
        - Wallets & accounts
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: update_wallet_metadata
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  ok: true
                  message: Request accepted
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                accountId:
                  type: string
                  description: Wallet id from list_wallets
                metadata:
                  type: object
                  description: 'Full metadata object, e.g. { "customer_id": "cust_123", "agent_id": "ag_1" }'
                  additionalProperties:
                    type: string
              required:
                - accountId
                - metadata
              additionalProperties: false
  /cosigners/invites:
    post:
      operationId: inviteAgentCosigner
      summary: Invite an agent co-signer
      description: "Add another FortFi agent (by their userId) as a co-signer on your account. GOVERN action: when called with
        an agent API key, sign a challenge with your funding wallet (challengeId + walletSignature). Use this to create
        multi-agent treasury approval workflows."
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: invite_agent_cosigner
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  ok: true
                  message: Request accepted
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                cosignerUserId:
                  type: string
                  description: The FortFi userId of the agent to invite as co-signer
                nickname:
                  type: string
                  description: Optional nickname for this co-signer
                challengeId:
                  type: string
                  description: Governance challengeId from the first call
                walletSignature:
                  type: string
                  description: Funding-wallet signature over the challenge message
              required:
                - cosignerUserId
              additionalProperties: false
  /cosigners/actions/approve:
    post:
      operationId: approveCosignerAction
      summary: Approve a pending co-signer action
      description: Approve a pending action as co-signer. Use with list_pending_cosigner_approvals.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: approve_cosigner_action
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pendingApprovalId:
                  type: string
              required:
                - pendingApprovalId
              additionalProperties: false
  /cosigners/actions/reject:
    post:
      operationId: rejectCosignerAction
      summary: Reject a pending co-signer action
      description: Reject a pending action as co-signer.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: reject_cosigner_action
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pendingApprovalId:
                  type: string
                reason:
                  type: string
                  description: Optional rejection reason
              required:
                - pendingApprovalId
              additionalProperties: false
  /cosigners/invites/accept:
    post:
      operationId: acceptCosignerInvite
      summary: Accept an incoming co-signer invite
      description: Accept a pending co-signer invite. After accepting, you will be able to approve/reject pending actions for
        that account.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: accept_cosigner_invite
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                inviteId:
                  type: string
                  description: Invite id from list_incoming_cosigner_invites
              required:
                - inviteId
              additionalProperties: false
  /cosigners/remove:
    post:
      operationId: removeCosigner
      summary: Remove a co-signer membership
      description: "Remove an active co-signer from this account. GOVERN action (it shrinks the approver set): via an agent
        key, sign a challenge with your funding wallet (challengeId + walletSignature); applies immediately once
        signed."
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: remove_cosigner
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                membershipId:
                  type: string
                  description: Membership id from list_cosigner_memberships
                challengeId:
                  type: string
                  description: Governance challengeId from the first call
                walletSignature:
                  type: string
                  description: Funding-wallet signature over the challenge message
              required:
                - membershipId
              additionalProperties: false
  /governance/backup-wallet/register:
    post:
      operationId: registerBackupGovernanceWallet
      summary: Register backup governance wallet
      description: "Register (or replace) a single backup governance wallet — the agentic equivalent of a backup passkey.
        Either the funding wallet or this backup can authorize future governance. GOVERN action: sign the challenge with
        your CURRENT funding wallet (challengeId + walletSignature); applies immediately once signed. Max one backup."
      tags:
        - Governance
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: register_backup_governance_wallet
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                walletAddress:
                  type: string
                  description: The backup wallet address (0x…) to register
                challengeId:
                  type: string
                  description: Governance challengeId from the first call
                walletSignature:
                  type: string
                  description: CURRENT funding-wallet signature over the challenge message
              required:
                - walletAddress
              additionalProperties: false
  /governance/backup-wallet/remove:
    post:
      operationId: removeBackupGovernanceWallet
      summary: Remove backup governance wallet
      description: "Remove the registered backup governance wallet. GOVERN action: sign with your funding wallet (challengeId
        + walletSignature); applies immediately once signed. After removal, only the funding wallet may authorize
        governance."
      tags:
        - Governance
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: remove_backup_governance_wallet
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                challengeId:
                  type: string
                  description: Governance challengeId from the first call
                walletSignature:
                  type: string
                  description: Funding-wallet signature over the challenge message
              additionalProperties: false
  /governance/requests/cancel:
    post:
      operationId: cancelGovernanceChange
      summary: Cancel a scheduled governance change
      description: Veto/cancel a pending governance challenge before it is signed and applied. Cancelling TIGHTENS security,
        so it needs only the agent key (no signature). Also cancels legacy scheduled rows from before immediate-apply
        parity.
      tags:
        - Governance
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: cancel_governance_change
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  ok: true
                  message: Request accepted
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                challengeId:
                  type: string
                  description: The governance request id from list_governance_requests
              required:
                - challengeId
              additionalProperties: false
  /cosigners/invites/revoke:
    post:
      operationId: revokeCosignerInvite
      summary: Revoke a pending co-signer invite
      description: Revoke a pending outbound co-signer invite before it is accepted.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: revoke_cosigner_invite
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  note: Operation-specific payload
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                inviteId:
                  type: string
                  description: Invite id from the invite you sent
              required:
                - inviteId
              additionalProperties: false
  /cosigners/pending-actions/cancel:
    post:
      operationId: cancelPendingAction
      summary: Cancel a pending co-signer approval
      description: Cancel a pending approval that you (the account owner) initiated.
      tags:
        - Security & cosigners
      security:
        - bearerAuth: []
      x-fortfi-scope: cosigners:write
      x-fortfi-mcp-tool: cancel_pending_action
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data:
                  ok: true
                  message: Request accepted
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pendingApprovalId:
                  type: string
                  description: Pending approval id from list_pending_cosigner_approvals or list_audit_log
              required:
                - pendingApprovalId
              additionalProperties: false
  /proposals/yield/deposit:
    post:
      operationId: proposeYieldDeposit
      summary: Propose Morpho vault deposit
      description: Propose Morpho vault deposit (real on-chain tx after confirm + passkey). Use list_yield_markets for vaultAddress.
      tags:
        - Yield
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_yield_deposit
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                  description: FortFi wallet id
                fromAccountQuery:
                  type: string
                  description: Wallet nickname (alternative to fromWalletId)
                vaultAddress:
                  type: string
                  description: Morpho vault contract (0x…)
                amountUsd:
                  type: string
                  description: USDC amount e.g. 100.00
                assetSymbol:
                  type: string
                  enum:
                    - USDC
                    - USDT
              required:
                - vaultAddress
                - amountUsd
              additionalProperties: false
  /proposals/yield/withdraw:
    post:
      operationId: proposeYieldWithdraw
      summary: Propose Morpho vault withdraw
      description: Propose Morpho vault withdraw (confirm + passkey). Use list_yield_positions for vaultAddress.
      tags:
        - Yield
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-mcp-tool: propose_yield_withdraw
      x-fortfi-rest-implemented: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OkEnvelope"
              example:
                ok: true
                data: *a6
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fromWalletId:
                  type: string
                fromAccountQuery:
                  type: string
                vaultAddress:
                  type: string
                amountDisplay:
                  type: string
                assetSymbol:
                  type: string
                  enum:
                    - USDC
                    - USDT
                vaultName:
                  type: string
              required:
                - vaultAddress
                - amountDisplay
              additionalProperties: false
  /proposals/{proposalId}/confirm:
    post:
      operationId: confirmProposal
      summary: Confirm a proposal created by a propose_* operation
      description: Executes a pending proposal. Human passkey accounts may require confirmation in the FortFi app; agent keys
        execute per policy. Returns `{ ok, executed, kind, ... }` (not wrapped in `data`).
      tags:
        - Proposals
      security:
        - bearerAuth: []
      x-fortfi-scope: proposals:write
      x-fortfi-rest-implemented: true
      parameters:
        - name: proposalId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                confirmToken:
                  type: string
                  minLength: 32
      responses:
        "200":
          description: Confirm result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConfirmResult"
              example:
                ok: true
                executed: true
                kind: send
                intentId: 880e8400-e29b-41d4-a716-446655440003
                message: Transfer submitted.
        "400": *a1
        "401": *a2
        "403": *a3
        "404": *a4
        "429": *a5
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: FortFi API key (frtfi_hu_* developer or frtfi_ag_* agent)
  schemas:
    OkEnvelope:
      type: object
      required:
        - ok
        - data
      properties:
        ok:
          type: boolean
          enum:
            - true
        data:
          description: Operation-specific payload (parsed JSON)
    ErrorEnvelope:
      type: object
      required:
        - ok
        - error
      properties:
        ok:
          type: boolean
          enum:
            - false
        error:
          type: object
          required:
            - message
          properties:
            message:
              type: string
            code:
              type: string
    ConfirmResult:
      type: object
      required:
        - ok
      properties:
        ok:
          type: boolean
        executed:
          type: boolean
        kind:
          type: string
        intentId:
          type: string
          format: uuid
        message:
          type: string
      additionalProperties: true
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
          examples:
            missing:
              value:
                ok: false
                error:
                  message: Authentication required
            invalidKey:
              value:
                ok: false
                error:
                  message: Invalid or expired API key
    Forbidden:
      description: Insufficient scope, session auth, or treasury access
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
          examples:
            sessionRejected:
              value:
                ok: false
                error:
                  message: "Session authentication is not supported on /api/v1. Use Authorization: Bearer <api_key>."
            scope:
              value:
                ok: false
                error:
                  message: "API key missing required scope: proposals:write"
    BadRequest:
      description: Invalid input or business rule violation
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
          example:
            ok: false
            error:
              message: "recipientId: Required"
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
          example:
            ok: false
            error:
              message: Payment request not found
    TooManyRequests:
      description: Rate limit exceeded
      headers:
        retry-after:
          schema:
            type: integer
          description: Seconds until retry
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
          example:
            ok: false
            error:
              message: Too many requests
