> ## 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.

# Enable card settlement on a wallet

> Executes the card-settlement enablement ceremony for the wallet from a
customer-endorsed `EnableCardSettlementIntent`. The settlement
destination is not part of the intent: Dakota supplies it from its own
configuration; `settlement_destination` is not part of the intent, and
an intent containing it is rejected with a 400. Idempotent: replaying
the call on an active enablement is a no-op. While the enablement is
still attaching, recovery depends on why the previous attempt did not
complete: after a transient failure (the service was briefly
unavailable) replay the SAME intent WITH THE SAME SIGNATURES to resume
— the signatures are part of what the idempotent replay is keyed on,
so re-signing the same intent is rejected as a conflicting replay
rather than resumed. After a rejected endorsement, replaying that
request replays the cached rejection — submit a CORRECTED intent under
a fresh `idempotency_key`, with fresh signatures, instead. If the
configured settlement destination has changed since the enablement was
recorded, the call returns a `#card-enablement-conflict` problem — an
enablement is never silently re-pointed.
The `signatures` array is capped at 16 entries, each at most 8192
bytes.


<Warning>**Sandbox only.** This endpoint is available in sandbox only while we finish development. It is not available in production yet, and its request and response shapes may change before release.</Warning>


## OpenAPI

````yaml /openapi.yaml post /wallets/{wallet_id}/card_enablement
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 insight: a deterministic report over a customer's agentic
      activity (funding balances, upcoming obligations, failures, mandate
      headroom and expiry), or — via `GET /insights` — over the whole client's
      book, with portfolio KPIs, daily series and a per-customer roll-up. 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: Cards
    description: >-
      Issue and manage cardholders and cards, and follow card transactions.
      Every change is also delivered as a webhook event.


      **Prerequisites:** Customer must be onboarded and the cards capability
      must be available.

      **Related:** Customers, Wallets, Events


      ### Webhook event catalog (v1)


      Every card-family event a client can subscribe to, in one place:


      | Event | Fires when |

      | -- | -- |

      | `cardholder.created` | A cardholder is created. |

      | `cardholder.updated` | Any cardholder change, including every
      review-status transition and deletion (`status: closed`). |

      | `cardholder.information_requested` | A reviewer asks for more
      information; the payload lists the open requirements. Not yet emitted; the
      review pipeline that opens a request for information is still to land. |

      | `card.created` | A card is created. |

      | `card.updated` | Any card change: status, spend limit, last4, freeze
      sources. A close arrives here with `status: closed`. |

      | `card_transaction.created` | The first event for a transaction, normally
      an authorization (`status: authorized`) placing a hold. A declined
      authorization also arrives here, with `status: declined`. |

      | `card_transaction.updated` | Every later change to the same transaction
      (see below). |

      | `wallet.card_enablement.completed` | A wallet's card-settlement
      enablement became active. |


      **Card event ordering.** `card.created` and `card.updated` carry the card
      as it stands after

      the change, including `version` and `freeze_sources` (always an array,
      empty when nothing

      holds the card). `version` is strictly increasing per card and matches the
      `version` on the

      card resource. Deliveries can arrive out of order, so keep the highest
      `version` you have

      applied for each card and drop any event whose `version` is not greater
      than it.


      **One transaction stream.** Holds, releases, partial clearings,
      settlement, returns,

      disputes and force posts are not separate event types. They are `status`
      transitions on

      the transaction, delivered as `card_transaction.updated` with the same
      payload shape as

      `card_transaction.created`:


      | What happened | `status` on the event |

      | -- | -- |

      | Transaction known before its first authorization event | `pending` (on
      `card_transaction.created`) |

      | Hold placed (authorization) | `authorized` (on
      `card_transaction.created`, or `card_transaction.updated` after a
      `pending` start) |

      | Hold released without clearing (merchant, issuer or network reversal) |
      `auth_reversed` |

      | Hold expired unused | `expired` |

      | Part of the hold settled | `partially_cleared` (with the new
      `cleared_amount`) |

      | Fully settled | `cleared` |

      | Settled with no prior hold | `force_posted` |

      | Merchant refund | `returned`, on a new card transaction for the refund;
      the original purchase stays `cleared`. The network returned the money;
      read `refund_state` for whether it reached the customer's wallet
      (`pending` then `paid`). `returned` alone is not proof of payout. |

      | Chargeback opened | `disputed` (reserved; not emitted yet) |

      | Authorization refused | `declined` (on `card_transaction.created`, or
      `card_transaction.updated` when the transaction already exists). Moves no
      money; read `decline_reason` and `decline_code` for why. |


      `outstanding_amount` is the part of `cleared_amount` that no authorization
      covered, less any refunds: non-zero after a force post or an over-capture.


      **Naming.** A dotted segment names a sub-resource of the resource before
      it, so

      `wallet.card_enablement.*` is a wallet's card enablement.
      `card_transaction.*` carries an

      underscore because the resource is `card_transactions`, a top-level
      resource, not a

      sub-resource of a card. It is not a typo, and there is no
      `card.transaction.*` family, and

      no separate settlement event: settlement is a `status` on
      `card_transaction.updated`.
  - 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: RD Marketing Fee
    description: >-
      Everything behind your RD marketing fee: read what a month came to,
      declare the wallets you hold outside Dakota so the RD in them counts, and
      say where the fee should be sent.


      **Prerequisites:** Client must be in the RD marketing-fee programme. A
      month is readable once it has closed.

      **Related:** Wallets, Events
  - name: Self Serve
    description: >-
      Buy and track prepaid credits, and read the tiers and pricing they are
      sold at.


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

      **Related:** Billing
  - 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:
  /wallets/{wallet_id}/card_enablement:
    parameters:
      - name: wallet_id
        in: path
        required: true
        description: Wallet ID
        schema:
          $ref: '#/components/schemas/KSUID'
    post:
      tags:
        - Cards
      summary: Enable card settlement on a wallet
      description: |
        Executes the card-settlement enablement ceremony for the wallet from a
        customer-endorsed `EnableCardSettlementIntent`. The settlement
        destination is not part of the intent: Dakota supplies it from its own
        configuration; `settlement_destination` is not part of the intent, and
        an intent containing it is rejected with a 400. Idempotent: replaying
        the call on an active enablement is a no-op. While the enablement is
        still attaching, recovery depends on why the previous attempt did not
        complete: after a transient failure (the service was briefly
        unavailable) replay the SAME intent WITH THE SAME SIGNATURES to resume
        — the signatures are part of what the idempotent replay is keyed on,
        so re-signing the same intent is rejected as a conflicting replay
        rather than resumed. After a rejected endorsement, replaying that
        request replays the cached rejection — submit a CORRECTED intent under
        a fresh `idempotency_key`, with fresh signatures, instead. If the
        configured settlement destination has changed since the enablement was
        recorded, the call returns a `#card-enablement-conflict` problem — an
        enablement is never silently re-pointed.
        The `signatures` array is capped at 16 entries, each at most 8192
        bytes.
      operationId: enableWalletCardSettlement
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EndorsedRequest'
            example:
              signatures:
                - LS0tLS1CRUdJ...0tLS0tCg==
              intent:
                type: enable_card_settlement
                wallet_id: 1NFHrqBHb3cTfLVkFSGmHZqdDPi
                idempotency_key: 7d3f6c2e-9a41-4f3b-bd1c-2e5a8f0c4b19
      responses:
        '200':
          description: The wallet's card enablement after the call
          content:
            application/json:
              example:
                state: attaching
                settlement_destination: '0x1111111111111111111111111111111111111111'
              schema:
                $ref: '#/components/schemas/CardEnablement'
        '400':
          description: Invalid request
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '401':
          description: Unauthorized
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '403':
          description: >
            Forbidden — the cards capability is not available for this customer,
            gating a new

            or still-attaching enablement exactly like card creation (an
            already-active

            enablement keeps replaying its 200 regardless of capability). The
            `type` is

            `#cards-capability-unavailable` in the general case (not in rollout,
            or more than

            the Cards ToS outstanding), or the more specific
            `#cards-tos-not-accepted` when the

            sole unmet requirement is the Cards ToS `terms_acceptance`. Either
            way the

            outstanding requirements ride in `errors`.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
              example:
                type: >-
                  https://docs.dakota.xyz/api-reference/errors#cards-capability-unavailable
                title: Cards Capability Unavailable
                status: 403
                detail: The cards capability is not available for this customer.
                errors:
                  - field: cards_tos
                    message: >-
                      Cards Terms of Service must be accepted before enabling
                      card settlement.
                    code: terms_acceptance
        '404':
          description: Not found
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '409':
          description: >
            A conflict on the enablement itself. The `type` is

            `#card-enablement-conflict` for a replay that disagrees with what

            is already recorded for this wallet (for example a different

            settlement destination), or `#card-enablement-precondition` when

            a named precondition of the ceremony was not met — a settlement

            signer group, or a customer or settlement policy the wallet needs,

            missing or not uniquely resolvable. A `409` can also come back as

            the generic `#conflict` for a failed precondition outside the

            table below. Replaying a request that was already refused may

            likewise return the generic `#conflict` rather than the original

            type, because the refusal's reason is not stored with the cached

            outcome. Only `#card-enablement-precondition` carries

            `errors[0].code` — `#card-enablement-conflict` and `#conflict` do

            not, so a client must switch on `type` before looking for a code.


            | `errors[0].code` | Meaning | Resolved by |

            |---|---|---|

            | `no_customer_policy` | The wallet has no customer policy attached.
            | The client, via the policies API |

            | `customer_policy_ambiguous` | The wallet has more than one
            customer policy attached; card settlement needs exactly one. | The
            client, via the policies API |

            | `customer_policy_shared` | The wallet's customer policy is also
            attached to another wallet; enablement needs one attached only to
            this wallet. | The client, via the policies API |

            | `settlement_group_not_provisioned` | The settlement signer group
            for the caller's account has not been provisioned. | Dakota —
            contact support |

            | `settlement_group_ambiguous` | The settlement signer group for the
            caller's account is ambiguous. | Dakota — contact support |

            | `settlement_policy_ambiguous` | The wallet has more than one
            settlement policy. | Dakota — contact support |


            The three customer-policy conditions are properties of the named

            wallet and self-serve: attach, detach, or replace the wallet's

            customer policy through the policies API and retry. The

            settlement-group conditions are properties of the caller's

            account rather than any one wallet, and along with

            `settlement_policy_ambiguous` can only be resolved by Dakota.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
              examples:
                enablement_conflict:
                  summary: Replay disagrees with the recorded enablement
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-conflict
                    title: Card Enablement Conflict
                    status: 409
                    detail: >-
                      the wallet's card enablement was recorded for a different
                      settlement destination than is now configured
                settlement_group_not_provisioned:
                  summary: >-
                    The settlement signer group for the caller's account has not
                    been provisioned
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-precondition
                    title: Card Enablement Precondition Not Met
                    status: 409
                    detail: >-
                      The settlement signer group for your account has not been
                      provisioned. This must be resolved by Dakota — contact
                      support.
                    errors:
                      - field: client
                        message: >-
                          The settlement signer group for your account has not
                          been provisioned. This must be resolved by Dakota —
                          contact support.
                        code: settlement_group_not_provisioned
                settlement_group_ambiguous:
                  summary: >-
                    The settlement signer group for the caller's account is
                    ambiguous
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-precondition
                    title: Card Enablement Precondition Not Met
                    status: 409
                    detail: >-
                      The settlement signer group for your account is ambiguous.
                      This must be resolved by Dakota — contact support.
                    errors:
                      - field: client
                        message: >-
                          The settlement signer group for your account is
                          ambiguous. This must be resolved by Dakota — contact
                          support.
                        code: settlement_group_ambiguous
                no_customer_policy:
                  summary: The wallet has no customer policy attached
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-precondition
                    title: Card Enablement Precondition Not Met
                    status: 409
                    detail: >-
                      The wallet needs a customer policy attached before it can
                      be enabled for card settlement. Attach one via the
                      policies API and retry.
                    errors:
                      - field: wallet_id
                        message: >-
                          The wallet needs a customer policy attached before it
                          can be enabled for card settlement. Attach one via the
                          policies API and retry.
                        code: no_customer_policy
                customer_policy_ambiguous:
                  summary: The wallet has more than one customer policy attached
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-precondition
                    title: Card Enablement Precondition Not Met
                    status: 409
                    detail: >-
                      The wallet has more than one customer policy attached.
                      Card settlement needs exactly one; detach the extras and
                      retry.
                    errors:
                      - field: wallet_id
                        message: >-
                          The wallet has more than one customer policy attached.
                          Card settlement needs exactly one; detach the extras
                          and retry.
                        code: customer_policy_ambiguous
                customer_policy_shared:
                  summary: >-
                    The wallet's customer policy is also attached to another
                    wallet
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-precondition
                    title: Card Enablement Precondition Not Met
                    status: 409
                    detail: >-
                      The wallet's customer policy is also attached to another
                      wallet. Enablement needs a customer policy attached only
                      to this wallet; create and attach a dedicated one and
                      retry.
                    errors:
                      - field: wallet_id
                        message: >-
                          The wallet's customer policy is also attached to
                          another wallet. Enablement needs a customer policy
                          attached only to this wallet; create and attach a
                          dedicated one and retry.
                        code: customer_policy_shared
                settlement_policy_ambiguous:
                  summary: The wallet has more than one settlement policy
                  value:
                    type: >-
                      https://docs.dakota.xyz/api-reference/errors#card-enablement-precondition
                    title: Card Enablement Precondition Not Met
                    status: 409
                    detail: >-
                      The wallet has more than one settlement policy. This must
                      be resolved by Dakota — contact support.
                    errors:
                      - field: wallet_id
                        message: >-
                          The wallet has more than one settlement policy. This
                          must be resolved by Dakota — contact support.
                        code: settlement_policy_ambiguous
        '422':
          description: |
            `#wallet-family-not-supported`: the wallet's chain family is
            known but is not one cards support (cards support EVM wallets
            only).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '500':
          description: Unexpected error
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '503':
          description: A required backing service is unavailable
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
      servers:
        - url: https://api.platform.sandbox.dakota.xyz
          description: Sandbox
components:
  schemas:
    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
    EndorsedRequest:
      type: object
      required:
        - signatures
        - intent
      properties:
        signatures:
          type: array
          description: List of signatures over the intent
          items:
            type: string
            description: |
              Cryptographic signature over the intent, base64-encoded. For an
              ES256 signer this is the ASN.1 DER ECDSA signature over the
              SHA-256 of the canonical intent. For a WEBAUTHN signer this is
              the base64 of the WebAuthn assertion JSON (id, rawId, type, and
              response.authenticatorData / clientDataJSON / signature). See
              the WebAuthn & Passkey Signing guide.
            example: LS0tLS1CRUdJ...0tLS0tCg==
        intent:
          oneOf:
            - $ref: '#/components/schemas/SendTransactionIntent'
            - $ref: '#/components/schemas/AttachGroupToWalletIntent'
            - $ref: '#/components/schemas/DetachGroupFromWalletIntent'
            - $ref: '#/components/schemas/AttachPolicyToWalletIntent'
            - $ref: '#/components/schemas/DetachPolicyFromWalletIntent'
            - $ref: '#/components/schemas/AddPolicyRuleIntent'
            - $ref: '#/components/schemas/RemovePolicyRuleIntent'
            - $ref: '#/components/schemas/UpdatePolicyRuleIntent'
            - $ref: '#/components/schemas/DeletePolicyIntent'
            - $ref: '#/components/schemas/EnableCardSettlementIntent'
          description: The intent being endorsed
    CardEnablement:
      type: object
      description: The card-settlement enablement state of a wallet.
      required:
        - state
        - settlement_destination
      properties:
        state:
          type: string
          description: |
            Enablement lifecycle state. `not_enabled` — no enablement exists;
            `attaching` — the ceremony is endorsed but not fully in force
            (see the enablement endpoint for how to recover: a transient
            failure resumes by replaying the same intent with the same
            signatures, a rejected endorsement requires a corrected intent
            under a fresh `idempotency_key`);
            `active` — cards can be issued against the wallet;
            `detach_requested` / `detached` — offboarding states.
          enum:
            - not_enabled
            - attaching
            - active
            - detach_requested
            - detached
        settlement_destination:
          type: string
          description: |
            The settlement destination address. For a `not_enabled` wallet,
            the Dakota-configured destination the enablement will pin;
            otherwise the destination recorded for the wallet. Informational:
            it is not part of the intent and is not signed by the client.
    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.
    SendTransactionIntent:
      type: object
      required:
        - wallet_id
        - caip2
        - operation
        - idempotency_key
      properties:
        wallet_id:
          type: string
          description: Unique identifier for the wallet
        caip2:
          type: string
          description: CAIP-2 chain identifier for the target blockchain network
        operation:
          $ref: '#/components/schemas/TransactionOperation'
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
        context_digest:
          type: string
          description: |
            Optional opaque SHA-256d digest (base64-encoded) of an upstream
            operator-meaningful context envelope produced by the originating
            service (e.g. financial-account).

            Neither platform nor policy-engine interprets the semantic
            content. Policy-engine includes the field in canonical hashing
            so the WebAuthn signature commits to it; beyond that the digest
            is never read, validated, or logged. The pre-image is persisted
            upstream and exists for forensic / non-repudiation purposes
            (see ENG-1962).

            Intents predating this field validate as today (empty / omitted).
    AttachGroupToWalletIntent:
      type: object
      required:
        - type
        - wallet_id
        - group_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - attach_group_to_wallet
          example: attach_group_to_wallet
        wallet_id:
          type: string
          description: Unique identifier for the wallet
        group_id:
          type: string
          description: The signer group id to be attached to the wallet
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
    DetachGroupFromWalletIntent:
      type: object
      required:
        - type
        - wallet_id
        - group_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - detach_group_from_wallet
          example: detach_group_from_wallet
        wallet_id:
          type: string
          description: Unique identifier for the wallet
        group_id:
          type: string
          description: The signer group id to be detached from the wallet
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
    AttachPolicyToWalletIntent:
      type: object
      required:
        - type
        - wallet_id
        - policy_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - attach_policy_to_wallet
          example: attach_policy_to_wallet
        wallet_id:
          type: string
          description: Unique identifier for the wallet
          example: wal_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        policy_id:
          type: string
          description: The policy id to be attached to the wallet
          example: pol_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
          example: idem_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
    DetachPolicyFromWalletIntent:
      type: object
      required:
        - type
        - wallet_id
        - policy_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - detach_policy_from_wallet
          example: detach_policy_from_wallet
        wallet_id:
          type: string
          description: Unique identifier for the wallet
          example: wal_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        policy_id:
          type: string
          description: The policy id to be detached from the wallet
          example: pol_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
          example: idem_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
    AddPolicyRuleIntent:
      type: object
      required:
        - type
        - policy_id
        - rule_type
        - action
        - definition
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - add_policy_rule
          example: add_policy_rule
        policy_id:
          type: string
          description: The policy id to which the rule will be added
          example: pol_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        rule_type:
          type: string
          description: Type of rule to add
          enum:
            - approval_threshold
            - amount_threshold
            - address_list
          example: approval_threshold
        action:
          type: string
          description: Action to take when rule matches
          enum:
            - allow
            - deny
          example: deny
        definition:
          type: object
          description: |
            Rule-specific configuration. When a policy is created or a rule is
            added, the accepted keys depend on `rule_type`. A key that is not
            listed below is rejected with `400`, and the response names it.
            - `amount_threshold`: `min_amount` (integer, 0 or greater,
              required), `threshold` (integer, 1 or greater, required), and
              `asset` (object, required) with `id` - the asset symbol, one of
              `USDC`, `USDT`, or `RD`, stored upper case; optionally
              `name`, a display label that plays no part in matching. Any other
              key inside `asset` is rejected. There is no way to omit the
              asset: a missing asset, or an `asset.id` that is empty or `any`,
              is rejected with `400`. The rule governs transactions in that
              asset on every network, unless the stored asset names one.
              `min_amount` is an amount of that asset in its smallest unit -
              USDC has 6 decimals, so 10000000000 is 10,000 USDC - and
              `threshold` is the number of authorized endorsements required
              once a transaction reaches `min_amount`.
            - `approval_threshold`: `threshold` (integer, 1 or greater,
              required), `description` (string, optional).
            - `address_list`: `addresses` (array of one or more strings,
              required).
            Every integer must be whole. The server rejects a fractional value
            instead of truncating it.
            Updating an existing rule is validated more strictly - see
            `updated_definition`.
          example:
            threshold: 2
            description: Require 2 approvals
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
          example: idem_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
    RemovePolicyRuleIntent:
      type: object
      required:
        - type
        - policy_id
        - rule_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - remove_policy_rule
          example: remove_policy_rule
        policy_id:
          type: string
          description: The policy id from which the rule will be removed
          example: pol_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        rule_id:
          type: string
          description: The id of the rule to be removed from the policy
          example: rule_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
          example: idem_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
    UpdatePolicyRuleIntent:
      type: object
      required:
        - type
        - policy_id
        - rule_id
        - updated_definition
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - update_policy_rule
          example: update_policy_rule
        policy_id:
          type: string
          description: The policy id from which the rule will be updated
          example: pol_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        rule_id:
          type: string
          description: The id of the rule to be updated
          example: rule_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        updated_definition:
          type: string
          description: >-
            The updated rule definition as a JSON string. It replaces the
            existing definition, so it must be complete and must match the
            schema of the rule's type; any key outside that schema is rejected.
            An `amount_threshold` definition requires `asset.id`, a `threshold`
            greater than zero and a `min_amount` of zero or more. The remaining
            asset fields are optional — whatever the stored rule already records
            for the same asset is kept.
          example: '{"min_amount": 100, "threshold": 1, "asset": {"id": "USDC"}}'
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
          example: idem_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
    DeletePolicyIntent:
      type: object
      required:
        - type
        - policy_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - delete_policy
          example: delete_policy
        policy_id:
          type: string
          description: The policy id to be deleted
          example: pol_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
        idempotency_key:
          type: string
          description: A unique key to ensure idempotency of the request
          example: idem_2N4YkKpKu7M3mKpGYmF8kcJ8oZT
    EnableCardSettlementIntent:
      type: object
      description: |
        Intent to enable card settlement on a wallet. The settlement
        destination is not part of the intent: Dakota supplies it from its own
        configuration and pins it in the wallet's settlement policy. The
        intent is semantic and client-constructible; it never names internal
        policy or group ids.
      required:
        - type
        - wallet_id
        - idempotency_key
      properties:
        type:
          type: string
          enum:
            - enable_card_settlement
          example: enable_card_settlement
        wallet_id:
          type: string
          description: The wallet to enable card settlement on
        idempotency_key:
          type: string
          description: |
            A unique key to ensure idempotency of the request. Must be a UUID:
            this key is part of the endorsed intent, which requires that form,
            so anything else is rejected with a 400.
          example: 7d3f6c2e-9a41-4f3b-bd1c-2e5a8f0c4b19
    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
    TransactionOperation:
      type: object
      required:
        - kind
        - from
        - to
        - asset_id
      properties:
        kind:
          type: string
          description: 'Transaction type: transfer or contract call'
        from:
          type: string
          description: The wallet address initiating the transaction
        to:
          type: string
          description: The recipient address of the transaction
        amount:
          type: string
          description: >
            Amount to be transferred as a non-negative decimal string. Required
            for

            transfer operations; optional for contract calls (defaults to zero).

            Leading zeros, signs, commas, and non-finite values are rejected.

            For transfer operations the handler additionally requires the value
            to be greater than zero.
          pattern: ^(0|[1-9][0-9]*)(\.[0-9]+)?$
          minLength: 1
        asset_id:
          type: string
          description: Crypto asset symbol for the transfer or contract call.
          example: USDC
        method:
          type: string
          description: The method name to be invoked on the contract
        args:
          type: array
          description: Arguments for the contract method call
          items:
            type: string
        data:
          type: string
          description: The calldata payload for the contract call
  parameters:
    IdempotencyKeyHeader:
      name: x-idempotency-key
      in: header
      required: true
      description: >-
        Unique key to ensure request idempotency. If the same key is used within
        a certain time window, the original response will be returned instead of
        executing the request again.
      schema:
        type: string
        format: uuid
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````