> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dakota.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Draft payment proposals from a conversation (BETA)

> > **Beta** — early access.

Pure cognition, no side effects: turn a customer's natural-language request into reviewable PROPOSALS — the same action-series shape POST /instructions accepts. Stateless: send the conversation so far in `messages` (and/or a `prompt` appended as the latest user turn) on each call, and the response carries either a clarifying/confirming reply, or — only at high confidence — validated proposals (sometimes both). The agent may consult the customer's existing payees and this agent's payment history; it never guesses amounts, assets, networks, or addresses, and proposals still only take effect via the instructions + mandate-signature flow. Requires the freeform LLM layer to be configured server-side.




## OpenAPI

````yaml /openapi.yaml post /payment-agents/{payment_agent_id}/proposals
openapi: 3.0.3
info:
  title: Dakota Platform API
  version: 1.0.0
  description: >-
    Combined API specification for Dakota Platform services:

    - Issuance API: Asset minting and burning operations

    - Onboarding API: Know Your Business/Customer verification

    - On/Off Ramp API: Managing on-ramp and off-ramp accounts

    - Recipients API: Managing destinations for KYB'd entities

    - Transactions API: Viewing transaction history across platform operations


    ## Authentication and API Headers


    All API endpoints require the following headers:


    - `x-idempotency-key`: Required for all POST endpoints to ensure request
    idempotency

    - `x-api-key`: Required for authentication across all endpoints


    Note: On /applications endpoints you need a token for authentication instead
    of a x-api-key

    - `x-application-token`: Required for authentication on public /applications
    endpoints (alternative to `x-api-key` where documented)



    ## Rate Limits


    Requests are rate limited per API key. Every response includes the following
    headers:


    | Header | Description |

    | --- | --- |

    | `X-RateLimit-Limit` | Maximum requests allowed in the current one-minute
    window. |

    | `X-RateLimit-Remaining` | Requests remaining in the current window. |

    | `X-RateLimit-Reset` | Absolute Unix timestamp (seconds since epoch) when
    the current rate-limit window resets. |


    When a request is throttled (`429`), responses also include `Retry-After`
    with seconds to wait before retrying.
servers:
  - url: https://api.platform.dakota.xyz
    description: Production environment
  - url: https://api.platform.sandbox.dakota.xyz
    description: Sandbox — safe for testing with simulated data
security:
  - ApiKeyAuth: []
tags:
  - name: Agentic Payments
    x-beta: true
    description: >-
      Beta — agent-driven payments: provision agents, draft and approve spending
      mandates, accept reviewed instructions, and manage scheduled payments.


      **Prerequisites:** Customer onboarded; signer groups attached for
      recognition.

      **Related:** Wallets, Signer Groups, Transactions
  - name: Mandates
    x-beta: true
    description: >-
      Beta — spending mandates: signed, signer-bound authorizations governing
      what may be spent, approved or cancelled by a second recognized signer (§8
      — the dual-control rule that every mandate mutation must be signed by a
      recognized signer OTHER than the bound one). Independent of agents and
      scheduled payments.


      **Prerequisites:** Signer groups attached for recognition.

      **Related:** Signer Groups, Transactions
  - name: Insights
    x-beta: true
    description: >-
      Beta — read-only account insight: a deterministic report over a customer's
      agentic activity (funding balances, upcoming obligations, failures,
      mandate headroom and expiry). Never moves money, never creates or changes
      anything.


      **Prerequisites:** Customer onboarded; insight is computed from the
      customer's scheduled payments, mandates, and wallets.

      **Related:** Agentic Payments, Mandates
  - name: Customers
    description: >-
      Manage customer entities representing businesses and organizations
      onboarded to Dakota.


      **Prerequisites:** Complete KYB via Onboarding endpoints before initiating
      money movement.

      **Related:** Onboarding, Recipients, Transactions, Accounts, Wallets
  - name: Wallets
    description: >-
      Manage wallets, balances, and wallet-to-signer-group relationships for
      custody and movement controls.


      **Prerequisites:** Customer must exist. Configure signer groups before
      policy-enforced workflows.

      **Related:** Signer Groups, Policies, Transactions, Customers
  - name: Transactions
    description: >-
      Create, cancel, and retrieve transaction records across account and wallet
      flows.


      **Prerequisites:** Accounts or destinations must be configured based on
      flow type.

      **Related:** Accounts, Recipients, Policies, Events
  - name: Recipients
    description: >-
      Manage recipient entities and destination rails used by customers for
      payouts and transfers.


      **Prerequisites:** Customer must be onboarded and active.

      **Related:** Customers, Transactions, Accounts, Onboarding
  - name: Accounts
    description: >-
      Manage account resources used for onramp, offramp, and swap operations.


      **Prerequisites:** Customer must be created and network/asset constraints
      must be known.

      **Related:** Customers, Transactions, Auto Transactions, Info
  - name: Auto Transactions
    description: >-
      Manage automated transaction configurations and execution history for
      account automation workflows.


      **Prerequisites:** Source account must exist and be configured for
      automation.

      **Related:** Accounts, Transactions, Events
  - name: Onboarding
    description: >-
      Manage KYB/KYC onboarding lifecycle, application documents, attestations,
      and verification steps.


      **Prerequisites:** Customer context and required entity/application
      metadata.

      **Related:** Customers, Exceptions, Recipients, Transactions
  - name: Policies
    description: >-
      Define and manage policy objects and rules used for transaction governance
      and risk controls.


      **Prerequisites:** Wallet and signer group resources should be configured
      for enforcement scenarios.

      **Related:** Wallets, Signer Groups, Transactions
  - name: Signer Groups
    description: >-
      Manage signer groups and signer assignments for multi-party authorization
      models.


      **Prerequisites:** Wallets should exist before linking signer groups.

      **Related:** Wallets, Policies, Transactions
  - name: Authentication
    description: >-
      Manage API authentication credentials and key lifecycle for platform
      access.


      **Prerequisites:** Client organization must be provisioned.

      **Related:** Users, Info
  - name: Users
    description: >-
      Manage client users, roles, and identity metadata for platform access
      control.


      **Prerequisites:** Auth credentials and client context must be
      established.

      **Related:** Authentication
  - name: Webhooks
    description: >-
      Manage outbound webhook targets and delivery configuration for event
      notifications.


      **Prerequisites:** Subscriber endpoint must be reachable and secured.

      **Related:** Events, Authentication
  - name: Payouts
    description: >-
      Manage where Dakota sends your accrued developer-fee payouts.


      **Prerequisites:** Auth credentials and client context must be
      established.

      **Related:** Events
  - name: Events
    description: >-
      Retrieve event records emitted by platform operations for audit and
      troubleshooting.


      **Prerequisites:** Requesting client must have access to referenced
      resources.

      **Related:** Webhooks, Transactions, Onboarding
  - name: Info
    description: >-
      Read platform capability metadata, such as supported rails, networks, and
      assets.

      These operations are served under `/capabilities/*` - `GET
      /capabilities/countries`

      and `GET /capabilities/networks`. The tag name does not appear in the
      request paths.


      **Prerequisites:** Valid authentication headers.

      **Related:** Accounts, Transactions
  - name: Sandbox
    description: >-
      Trigger sandbox-only simulation endpoints for safe end-to-end integration
      testing with synthetic data. The sandbox host
      (`https://api.platform.sandbox.dakota.xyz`) also accepts a family of
      `X-Sandbox-*` request headers on most write endpoints (`Customers`,
      `Accounts`, `Transactions`, simulate endpoints) that let integrators drive
      deterministic failure modes — pick a preset via `X-Sandbox-Scenario`, or
      compose a custom one with
      `X-Sandbox-Error-Step`/`X-Sandbox-Error-Status`/`X-Sandbox-Error-Message`.
      `X-Sandbox-Instant-Completion` collapses async flows to a single
      synchronous step, and `X-Sandbox-Skip-Auto-Approval` keeps newly created
      KYB applications in `pending` for manual-review testing. All `X-Sandbox-*`
      headers are ignored in production.


      **Prerequisites:** Sandbox environment and test customer data.

      **Related:** Customers, Accounts, Transactions, Onboarding
  - name: Legal
    description: |-
      The legal documents customers accept — terms of service, privacy policy,
      e-sign notice, and partner agreements.

      Dakota publishes these here, and this is the authoritative source: the
      hosted onboarding flow, the dakota.xyz website, and your own integration
      all read the same revisions. Present the current revision to your customer
      before capturing their acceptance so the record reflects the text they
      actually saw.
paths:
  /payment-agents/{payment_agent_id}/proposals:
    post:
      tags:
        - Agentic Payments
      summary: Draft payment proposals from a conversation (BETA)
      description: >
        > **Beta** — early access.


        Pure cognition, no side effects: turn a customer's natural-language
        request into reviewable PROPOSALS — the same action-series shape POST
        /instructions accepts. Stateless: send the conversation so far in
        `messages` (and/or a `prompt` appended as the latest user turn) on each
        call, and the response carries either a clarifying/confirming reply, or
        — only at high confidence — validated proposals (sometimes both). The
        agent may consult the customer's existing payees and this agent's
        payment history; it never guesses amounts, assets, networks, or
        addresses, and proposals still only take effect via the instructions +
        mandate-signature flow. Requires the freeform LLM layer to be configured
        server-side.
      operationId: createPaymentAgentProposals
      parameters:
        - name: payment_agent_id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProposalsRequest'
            example:
              prompt: >-
                Pay Alice 10 USDC on base-sepolia
                0xa11ce00000000000000000000000000000000001 every month on the
                15th until Dec 26
      responses:
        '200':
          description: The agent's next step — a reply, proposals, or both
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgenticProposalsResult'
              example:
                reply: Drafting a monthly payment to Alice — review and sign below.
                proposals:
                  - summary: >-
                      Pay Alice 10 USDC on base-sepolia, on the 15th of every
                      month until Dec 2026 (7 payments)
                    actions:
                      - type: create_recipient
                        create_recipient:
                          name: Alice
                      - type: create_crypto_destination
                        create_crypto_destination:
                          address: '0xa11ce00000000000000000000000000000000001'
                          network_id: base-sepolia
                      - type: create_mandate
                        create_mandate:
                          rule:
                            target_type: recipient
                            targets:
                              - Alice
                            network_id: base-sepolia
                            asset: USDC
                            max_per_tx: '10'
                            window: MONTHLY
                            max_count_per_target_in_window: 1
                          valid_until: 1798675200
                      - type: create_scheduled_payments
                        create_scheduled_payments:
                          destination_id: ''
                          amount: '10'
                          asset: USDC
                          dates:
                            - 1782864000
                            - 1785542400
        '400':
          description: >-
            Invalid request, or the freeform conversation layer is not
            configured
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
              example:
                type: https://docs.dakota.xyz/api-reference/errors#invalid-request
                title: Invalid request
                status: 400
                detail: freeform proposals are not enabled (no LLM configured)
        '403':
          description: The customer is frozen and cannot move money
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
              example:
                type: >-
                  https://docs.dakota.xyz/api-reference/errors#account-under-review
                title: Account Under Review
                status: 403
                detail: >-
                  This account is under review and cannot move funds until the
                  review is resolved.
        '404':
          description: Agentic payments not enabled, or the agent was not found
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
              example:
                type: https://docs.dakota.xyz/api-reference/errors#not-found
                title: Not Found
                status: 404
                detail: agent not found
        '429':
          description: >
            The per-customer proposal-drafting rate limit was exceeded (an
            hourly burst window and a daily window). Back off and retry later.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
              example:
                type: https://docs.dakota.xyz/api-reference/errors#rate-limited
                title: Rate Limited
                status: 429
                detail: >-
                  proposal rate limit reached for this customer (hour window) —
                  retry later
components:
  schemas:
    CreateProposalsRequest:
      type: object
      description: >
        A freeform proposals conversation. The server is stateless — send the
        whole history in `messages` on each call. `prompt` is a convenience for
        a single-shot turn (or the latest user message); it is appended after
        `messages`. At least one of `prompt` or `messages` must be non-empty.
        Supplying both is valid only when `messages` does not already end with a
        user turn; otherwise the request is rejected with 400 (two consecutive
        user turns are not allowed).
      properties:
        prompt:
          type: string
          description: Single-shot input, appended as the latest user turn.
        messages:
          type: array
          description: The conversation so far, oldest first.
          items:
            $ref: '#/components/schemas/AgenticChatMessage'
        developer_fee:
          $ref: '#/components/schemas/DeveloperFee'
        timezone:
          type: string
          maxLength: 64
          description: >
            The customer's IANA timezone (e.g. "America/Los_Angeles"). When
            present, the agent resolves every relative date ("tomorrow",
            "Friday") and clock time ("10 am") in THIS timezone; a date without
            a time is drafted for the first working hours of the local day
            (10:00) and the draft summary states the resolved local time; a time
            without a date means its next local occurrence. Absent or
            unrecognized ⇒ times resolve as UTC and the agent says so when a
            specific clock time matters. Send it on EVERY turn — the server is
            stateless. Note: the zone's UTC offset is captured at drafting time,
            so a DST transition before a far-future fire date shifts the fire
            time by the DST delta.
          example: America/Los_Angeles
    AgenticProposalsResult:
      type: object
      description: >
        The agent's next step. At least one of `proposals` or `reply` is always
        present in a successful response — `proposals` at high confidence
        (optionally with a short `reply` note), or `reply` alone when the agent
        needs more from the user.
      properties:
        proposals:
          type: array
          description: >-
            Validated action-series proposals, ready to accept via POST
            /instructions. Present only at high confidence.
          items:
            $ref: '#/components/schemas/AgenticProposal'
        reply:
          type: string
          description: >-
            The agent's conversational reply — a clarifying question or
            confirmation. Present without proposals when the agent needs more
            from the user; may accompany proposals as a short note.
        blockers:
          type: array
          description: >
            BETA — machine-actionable reasons the agent could not complete the
            request, for the CLIENT APPLICATION rather than the customer.
            `reply` explains it in prose, which software cannot branch on:
            "extend the limit to cover Priya", "I need her bank details" and
            "that rail is not supported" all arrive as some text. A blocker
            names the reason as a stable code so the client can act on it —
            opening its own limit editor with the payee filled in, say — and
            only then decide what the customer sees.

            MAY ACCOMPANY PROPOSALS, and routinely does. The common case is a
            payee who does not exist yet: the turn proposes creating them AND
            reports that the limit will not reach them, because the client has
            to do both, in that order — accept the proposal so the payee has an
            id, then amend the limit to include it. Treat proposals and blockers
            as independent, never as alternatives.

            Absent when nothing blocked the turn. ALWAYS switch on `code` and
            ignore codes you do not know, as new ones are added over time. Every
            blocker returned has been re-checked against the server's own data,
            so a code never reflects only the model's opinion.
          items:
            $ref: '#/components/schemas/AgenticBlocker'
        conversation_status:
          type: string
          enum:
            - ok
            - warned
            - blocked
            - rejected_input
          description: >-
            How the boundary screen treated this turn. `ok` is a normal payments
            turn; `warned` means the request was off-topic and the customer was
            warned but may continue; `blocked` means the conversation has been
            terminated (repeated off-topic turns or a manipulation attempt) —
            the client should stop serving it and offer a fresh chat.
            `rejected_input` means this message was refused wholesale (e.g. more
            payees than one conversation supports) and should NOT be added to
            the conversation history — the reply explains what to resend; the
            conversation itself continues unaffected.
    ProblemDetails:
      type: object
      required:
        - type
        - title
        - status
      description: |
        Error response following RFC 9457 Problem Details.
        Public API error responses use this format.
      example:
        type: https://docs.dakota.xyz/api-reference/errors#not-found
        title: Customer Not Found
        status: 404
        detail: Customer cst_2abc123 was not found in your organization.
        instance: https://api.platform.dakota.xyz/customers/cst_2abc123
        request_id: req_7f3a8b2c
      properties:
        type:
          type: string
          format: uri
          description: |
            URI reference identifying the problem type.
            Resolves to human-readable documentation.
          example: https://docs.dakota.xyz/api-reference/errors#not-found
        title:
          type: string
          description: >-
            Short, human-readable summary of the problem type. Stable across
            occurrences.
          example: Customer Not Found
        status:
          type: integer
          description: HTTP status code for this occurrence.
          example: 404
        detail:
          type: string
          description: Human-readable explanation specific to this occurrence.
          example: Customer cst_2abc123 was not found in your organization.
        instance:
          type: string
          format: uri
          description: The request path that triggered this error.
          example: https://api.platform.dakota.xyz/customers/cst_2abc123
        request_id:
          type: string
          description: Unique request identifier. Include when contacting support.
          example: req_7f3a8b2c
        errors:
          type: array
          description: Field-level validation errors (present for validation failures).
          items:
            $ref: '#/components/schemas/ValidationError'
        resolution_url:
          type: string
          format: uri
          description: |
            A link the customer can follow to CLEAR this error, present only on
            problems with a concrete self-service remedy.

            Today this is returned by
            `#terms-not-accepted`, where it points at the hosted flow in which
            the outstanding agreement can be signed. The link is token-gated and
            usable as-is — send the customer to it directly rather than parsing
            it out of `detail`.
          example: >-
            https://onboarding.dakota.xyz/applications/2abc123?token=tok_7f3a8b2c
        user_message:
          type: string
          description: |
            A plain-language rendition of `detail` written for the end
            customer, present when one exists for this error. `detail` names
            request fields and actions so a machine caller (such as a payment
            agent drafting proposals) can self-correct; `user_message` says the
            same thing without API vocabulary. Clients that relay errors into a
            human surface (chat, email, UI) should show `user_message` when
            present and fall back to `detail`.
          example: >-
            ACH payments pay out USD, so a USDC payout isn't possible on this
            rail. Change the payout currency to USD and try again.
    AgenticChatMessage:
      type: object
      required:
        - role
        - content
      properties:
        role:
          type: string
          enum:
            - user
            - assistant
        content:
          type: string
        attachments:
          type: array
          description: >
            Input artifacts attached to this turn for the agent to investigate —
            e.g. an invoice PDF to draft a payment from. Optional. Document
            attachments (PDF or image) are accepted up to 8 MiB per document and
            16 MiB per request, measured on the decoded payload.
          items:
            $ref: '#/components/schemas/AgenticAttachment'
    DeveloperFee:
      type: object
      description: >
        Your developer fee, declared per payout type. A conversion is charged
        the rate for the kind of payout it funds: `swap_bps` for a crypto
        payout, `offramp_bps` for a bank payout. Omit a rate, or send zero, and
        that payout type carries no fee at all — nothing is charged, nothing is
        added to the amount, and the agent is told nothing about a fee it could
        mention. The two are independent, so one conversation can charge a swap
        and stay silent about a bank payout in the same turn.


        Both rates are DEFAULTS for the auto-accounts a request creates. An
        action-level `fee_bps` is an explicit override and still wins outright,
        for either type.
      properties:
        swap_bps:
          type: integer
          format: int32
          minimum: 0
          maximum: 10000
          description: |
            Rate for a crypto payout — a `create_auto_account` naming no `rail`.
        offramp_bps:
          type: integer
          format: int32
          minimum: 0
          maximum: 10000
          description: >
            Rate for a bank payout — a `create_auto_account` naming a `rail`. An
            offramp converts too (it just settles on a rail instead of a chain),
            so charging it is a pricing decision that belongs to you. Zero or
            omitted means the payout is free of a conversion fee.
    AgenticProposal:
      type: object
      description: >
        A self-contained series of actions. Cross-action links are <entity>_id
        fields - empty binds to the artifact created in this proposal, a real id
        reuses an existing one. Every proposal must instruct a payment or draft
        a mandate - a mandate-only proposal is a standing authorization (sign
        now, schedule under it later by mandate_id with no new signature).
      required:
        - actions
      properties:
        summary:
          type: string
        actions:
          type: array
          items:
            $ref: '#/components/schemas/AgenticAction'
        payment_agent_id:
          type: string
          description: >
            The payment agent this proposal was drafted under. Present on
            proposals returned by the drafting endpoint (it echoes the
            endpoint's agent); ignored on input - the accept endpoint takes the
            agent in its own payment_agent_id field.
    AgenticBlocker:
      type: object
      description: >
        One machine-actionable reason a drafting turn produced no proposals.
        Verified server-side before it is returned.
      required:
        - code
      properties:
        code:
          type: string
          enum:
            - mandate_does_not_cover_payee
            - no_mandate
          description: >
            `mandate_does_not_cover_payee` — a spending limit is in force but
            its rule does not reach the named payee. This is the ACTIONABLE one:
            the limit can be amended to ADD the payee as a target, which changes
            nothing else and so can never raise the limit; collect the
            customer's signature for that amendment and run the turn again.
            `no_mandate` — no active limit exists at all, so there is nothing to
            amend and the customer must establish one first. The two are kept
            distinct so a client never opens an amend flow against a limit that
            does not exist.
        mandate_id:
          $ref: '#/components/schemas/KSUID'
        payee_name:
          type: string
          description: >
            The payee the customer named, verbatim. A NAME and not an id,
            because in the case this exists for the payee does not exist yet —
            which is why nothing covers them.
        detail:
          type: string
          description: Short human-readable note. Advisory only — branch on `code`.
    ValidationError:
      type: object
      required:
        - field
        - message
      properties:
        field:
          type: string
          description: Field path using dot notation for nested fields.
          example: bank_account.routing_number
        message:
          type: string
          description: Human-readable description of the field error.
          example: Routing number must be exactly 9 digits
        code:
          type: string
          description: Machine-readable error code for this field.
          example: invalid_format
    AgenticAttachment:
      type: object
      description: >
        An input artifact attached to a conversation turn. Tagged union: exactly
        one payload field matching `type` is set. Extensible — further kinds
        (e.g. an email stream) are added as new `type` enum values + payload
        fields, additively, without breaking this shape.
      required:
        - type
      properties:
        type:
          type: string
          enum:
            - document
          description: >-
            The attachment kind — `document` (a PDF or image) today; further
            sources are added additively.
        document:
          $ref: '#/components/schemas/AgenticDocumentAttachment'
    AgenticAction:
      type: object
      description: Tagged union - exactly one payload field matching `type` is set.
      required:
        - type
      properties:
        type:
          type: string
          enum:
            - create_recipient
            - create_crypto_destination
            - create_bank_destination
            - create_mandate
            - create_scheduled_payments
            - create_auto_account
        create_recipient:
          $ref: '#/components/schemas/RecipientRequest'
        create_crypto_destination:
          $ref: '#/components/schemas/CreateCryptoDestinationAction'
        create_bank_destination:
          $ref: '#/components/schemas/CreateBankDestinationAction'
        create_mandate:
          $ref: '#/components/schemas/CreateMandateAction'
        create_scheduled_payments:
          $ref: '#/components/schemas/CreateScheduledPaymentsAction'
        create_auto_account:
          $ref: '#/components/schemas/CreateAutoAccountAction'
    KSUID:
      type: string
      title: KSUID
      description: >-
        KSUID is a 27-character globally unique ID that combines a timestamp
        with a random component. Used for all entity identifiers in the Dakota
        platform.
      pattern: ^[0-9A-Za-z]{27}$
      minLength: 27
      maxLength: 27
      example: 1NFHrqBHb3cTfLVkFSGmHZqdDPi
    AgenticDocumentAttachment:
      type: object
      required:
        - media_type
        - data
      properties:
        media_type:
          type: string
          enum:
            - application/pdf
            - image/png
            - image/jpeg
            - image/webp
            - image/gif
          description: MIME type of the attached document.
        data:
          type: string
          format: byte
          description: The document bytes, base64-encoded.
        filename:
          type: string
          description: Optional original filename, for display and audit.
    RecipientRequest:
      type: object
      title: Recipient Request
      description: >
        Request for creating or updating a recipient entity.


        **Address Requirements:**

        - **Optional** for crypto-only recipients (can be omitted or null)

        - **Required** before adding fiat destinations (ACH, Wire, SWIFT)


        **Migration Path:** Recipients created without addresses can be updated
        later to add an address when fiat capabilities are needed.
      required:
        - name
      properties:
        name:
          type: string
          description: Name of the recipient entity
          example: Acme Corporation
          minLength: 3
          maxLength: 140
        address:
          $ref: '#/components/schemas/Address'
          description: >
            Physical address of the recipient.

            - **Optional** when creating/updating crypto-only recipients

            - **Required** for recipients that will have fiat destinations (ACH,
            Wire, SWIFT)

            - Can be added later via PUT /recipients/{id} to enable fiat
            capabilities
    CreateCryptoDestinationAction:
      type: object
      required:
        - address
        - network_id
      properties:
        recipient_id:
          type: string
          description: >-
            recipient reference: empty = the recipient created in this proposal;
            a recipient id or name = an existing recipient
        address:
          type: string
        network_id:
          $ref: '#/components/schemas/NetworkId'
    CreateBankDestinationAction:
      type: object
      properties:
        recipient_id:
          type: string
        account_holder_name:
          type: string
        account_number:
          type: string
        routing_number:
          type: string
        account_type:
          type: string
          enum:
            - checking
            - savings
        iban:
          type: string
        bic:
          type: string
        bank_name:
          type: string
    CreateMandateAction:
      type: object
      required:
        - rule
      properties:
        rule:
          $ref: '#/components/schemas/MandateRule'
        valid_from:
          type: integer
          format: int64
        valid_until:
          type: integer
          format: int64
    CreateScheduledPaymentsAction:
      type: object
      required:
        - amount
        - asset
      properties:
        destination_id:
          type: string
        wallet_id:
          type: string
          description: >-
            The funding wallet for these payments — one the agent recognizes.
            Optional only when the agent recognizes exactly one wallet (used by
            default); otherwise required, since a signer can recognize several
            and the choice cannot be deferred to fire time. Its chain family
            must match the payment network.
        amount:
          type: string
          description: >
            Decimal string. What this MEANS depends on `amount_includes_fee`
            below: by default it is what the PAYEE RECEIVES, and the server
            grosses it up so the fee comes out on top.
        amount_includes_fee:
          type: boolean
          description: >
            Whose side of the conversion fee `amount` is on.


            Absent or `false` (the DEFAULT): `amount` is what the payee
            RECEIVES. The server adds the fee on top, so slightly more leaves
            the funding wallet. This is what "pay Bruno 10 USDC" means to a
            person, and it matches the same payment made through a client's own
            form.


            `true`: `amount` is what LEAVES the wallet, and the payee receives
            less the fee. Use it only when the customer says so — "send 10 in
            total", "including the fee".


            The gross-up is done SERVER-SIDE from the fee on the request; the
            agent never computes it, so it can neither get the arithmetic wrong
            nor be talked out of the fee. With no fee configured the two are
            identical.
        asset:
          type: string
        network_id:
          type: string
          description: >-
            The chain THIS payment settles on. The network belongs to the
            payment, not to the payee: an address belongs to a whole family, so
            which chain a given payment uses is chosen when the payment is made.
            Optional — the destination's own network is used when omitted. When
            the destination pins a DIFFERENT one in the same family, this
            payment's network wins (the pin records what an earlier payment did,
            not a restriction on the address). Across chain FAMILIES the address
            does not carry at all, and that is refused.
          example: base-sepolia
        dates:
          type: array
          maxItems: 366
          items:
            type: integer
            format: int64
        count:
          type: integer
          maximum: 366
        interval_seconds:
          type: integer
          format: int64
        start_at:
          type: integer
          format: int64
        local_time:
          type: string
          maxLength: 16
          description: >
            The FIRST entry of `dates` as the customer-local wall clock it is
            meant to fire at, "2006-01-02 15:04". When present together with
            `local_zone`, the server recomputes the epoch from the pair and
            rejects the action if it disagrees with `dates[0]` — a deterministic
            check under timezone arithmetic. Optional.
          example: 2026-07-24 10:00
        local_zone:
          type: string
          maxLength: 64
          description: The IANA timezone `local_time` is expressed in.
          example: America/Los_Angeles
    CreateAutoAccountAction:
      type: object
      description: >
        Provision a provider-managed convert-and-forward "auto-account" so a
        payment can cross chain families (crypto→crypto swap) or exit to a bank
        (crypto→bank offramp). The agent pays the auto-account's crypto DEPOSIT
        on source_network_id (on the funding wallet's own family) and the
        provider converts source_asset→output_asset and forwards to
        destination_id. A scheduled payment then targets the deposit; the
        mandate still targets the real recipient.
      required:
        - source_asset
        - source_network_id
        - output_asset
      properties:
        destination_id:
          type: string
          description: >-
            The REAL destination the auto-account forwards to: a crypto
            destination (⇒ swap) or a bank destination (⇒ offramp). Empty = the
            destination created in this proposal.
        source_asset:
          type: string
          description: >-
            The asset the agent deposits and the scheduled payment sends (may be
            the ANY wildcard).
        source_network_id:
          $ref: '#/components/schemas/NetworkId'
        output_asset:
          type: string
          description: >-
            The asset the recipient receives (a currency such as USD for a bank
            offramp).
        output_network_id:
          type: string
          description: >-
            The chain the PAYEE is paid on — the payout leg, and a different
            chain from `source_network_id` (the deposit the funding wallet
            pays). Crypto payouts only; a bank offramp has no chain. Optional:
            the destination's own network is used when omitted. When set it
            decides, because the network belongs to the payment and not to the
            payee — an address receives on every chain in its family, so a
            destination's saved network records what a previous payment did
            rather than restricting this one. Across chain FAMILIES the address
            does not carry at all, and that is refused.
          example: base-sepolia
        rail:
          type: string
          description: >-
            Outbound rail — REQUIRED for a bank offramp (e.g. ach, fedwire,
            swift); omit for a crypto swap.
        routing_preference:
          type: string
          enum:
            - fastest
            - cheapest
        fee_bps:
          type: integer
          format: int32
          description: Optional developer fee in basis points (0–10000).
    Address:
      type: object
      title: Address
      description: >-
        Standardized physical address format used throughout the Dakota platform
        for user and entity addresses.
      required:
        - street1
        - city
        - country
      properties:
        street1:
          type: string
          description: Primary street address line
          example: 123 Main St
        street2:
          type: string
          description: >-
            Secondary address information such as apartment, suite, or unit
            number
          example: Apt 4B
        street3:
          type: string
          description: Additional address information like building name or floor
          example: Building C
        city:
          type: string
          description: City or locality name
          example: San Francisco
        region:
          type: string
          description: Full name of state, province, or region
          example: California
        postal_code:
          type: string
          description: Postal or ZIP code
          example: '94105'
        country:
          type: string
          description: ISO 3166-1 alpha-2 country code (two-letter country code)
          example: US
          minLength: 2
          maxLength: 2
    NetworkId:
      type: string
      description: Identifier for a blockchain network
      example: ethereum-mainnet
      enum:
        - ethereum-mainnet
        - ethereum-sepolia
        - ethereum-goerli
        - ethereum-holesky
        - solana-mainnet
        - solana-devnet
        - solana-testnet
        - base-mainnet
        - base-sepolia
        - arbitrum-mainnet
        - arbitrum-sepolia
        - optimism-mainnet
        - optimism-sepolia
        - polygon-mainnet
        - polygon-amoy
      minLength: 1
      maxLength: 30
    MandateRule:
      type: object
      required:
        - target_type
        - asset
      properties:
        target_type:
          type: string
          enum:
            - any
            - recipient
            - address
        targets:
          type: array
          items:
            type: string
          description: >-
            One or more targets of the declared kind (recipient ids or
            addresses; empty for any). Max 32.
        network_id:
          type: string
          description: >-
            The network the funding wallet pays on (e.g. base-sepolia). Empty
            authorizes any network — the other dimensions still apply.
        asset:
          type: string
          description: >
            The asset the funding wallet SENDS — deposit-denominated, e.g. USDC
            — compared case-insensitively against the firing payment. Write the
            crypto deposit asset even when the recipient ultimately receives
            fiat via a bank offramp (stablecoin conversion is 1:1): a fiat
            symbol such as USD can never match a send, so the mandate would deny
            every payment.
        max_per_tx:
          type: string
          description: >-
            Per-payment cap — a decimal string in the rule's (deposit) asset.
            Empty means no per-payment cap; the window caps may still bound
            total spend.
        window:
          type: string
          enum:
            - NONE
            - DAILY
            - WEEKLY
            - MONTHLY
          description: >
            Spend-cap window shared by every window limit below (calendar, not
            rolling; all boundaries in UTC). NONE = lifetime; DAILY = calendar
            day from 00:00 UTC; WEEKLY = calendar week from Monday 00:00 UTC;
            MONTHLY = calendar month from the 1st, 00:00 UTC.
        max_amount_per_target_in_window:
          type: string
          description: >-
            Cumulative cap over the window, PER TARGET (never shared across
            targets).
        max_count_per_target_in_window:
          type: integer
          description: Up to N times PER TARGET in the window (window NONE = lifetime).
        max_amount_in_window:
          type: string
          description: >
            Cumulative cap over the window ACROSS ALL TARGETS — the ceiling on
            total spend under this mandate, whoever it pays. Use this for "the
            agent may spend up to X per month": a per-target cap alone
            MULTIPLIES by the number of targets (a 3-payee allowlist capped at
            10000 per target permits 30000). Set both and both are enforced —
            the tighter one binds. Empty means no aggregate amount ceiling.
        max_count_in_window:
          type: integer
          description: >
            Up to N payments in the window ACROSS ALL TARGETS, whoever they go
            to (window NONE = lifetime). The aggregate twin of
            max_count_per_target_in_window, which caps each target separately
            and so permits targets x N payments. Omit or 0 for no aggregate
            count ceiling.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````