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

# SDK — read one proposal, including the intent to sign

> Returns the stored intent verbatim. An approver signs THESE bytes: a
re-derived intent would carry a different `intentId` and `createdAt`, and
every approval already collected would stop verifying.




## OpenAPI

````yaml https://app.dynamic.xyz/api-docs/public-api.yaml get /sdk/{environmentId}/businessAccounts/{businessAccountId}/proposals/{proposalId}
openapi: 3.0.1
info:
  title: Dashboard API
  description: Dashboard API documentation
  version: 1.0.0
servers:
  - url: https://app.dynamicauth.com/api/v0
  - url: https://app.dynamic.xyz/api/v0
  - url: http://localhost:3333/api/v0
security: []
tags:
  - name: Analytics
    description: Query usage analytics and event counts for your environment.
  - name: SDK
    description: SDK-facing endpoints consumed by embedded Dynamic clients.
  - name: Server
    description: Server-side SDK endpoints authenticated by environment API tokens.
  - name: Organizations
    description: >-
      Manage organizations — the top-level container for all environments and
      projects.
  - name: Projects
    description: Manage projects that group related environments under an organization.
  - name: Environments
    description: >-
      Manage environments (live and sandbox) where your authentication
      configuration lives.
  - name: Users
    description: List, search, and manage authenticated users within an environment.
  - name: Invites
    description: >-
      Manage invitation links that grant specific external users access to your
      environment.
  - name: Tokens
    description: >-
      Create and manage API tokens used to authenticate requests to the Dynamic
      API.
  - name: Origins
    description: >-
      Configure allowed origins (CORS) for SDK and API access to your
      environment.
  - name: Allowlists
    description: >-
      Manage allowlists to control which wallet addresses or email addresses can
      access your environment.
  - name: Wallets
    description: View and manage wallets linked to users in your environment.
  - name: Members
    description: Manage team members and their roles within an organization.
  - name: Sessions
    description: View and revoke active user sessions within an environment.
  - name: Settings
    description: Read and update environment-level configuration settings.
  - name: Exchanges
    description: >-
      Configure exchange integrations (Coinbase, Binance, etc.) for fiat on-ramp
      within your environment.
  - name: Yield
    description: List yield vaults registered for your environment.
  - name: Providers
    description: >-
      List, enable, disable, and configure authentication providers (OAuth,
      email, wallet, SMS, etc.) for your environment.
  - name: Captcha
    description: >-
      Configure captcha verification (provider, site key, secret key) for your
      environment.
  - name: Gates
    description: >-
      Define access gates that restrict environment entry to users who meet
      specific criteria.
  - name: Chains
    description: >-
      Manage the blockchain networks available for wallet connection in your
      environment.
  - name: Exports
    description: Export user and wallet data from your environment as downloadable files.
  - name: Events
    description: Browse the event log of actions performed within your environment.
  - name: Webhooks
    description: >-
      Create and manage webhooks to receive real-time events (user.created,
      wallet.linked, etc.) at your endpoint.
  - name: Custom Fields
    description: >-
      Define and manage custom metadata fields collected from users at sign-up
      or login.
  - name: MfaSettings
    description: >-
      Configure multi-factor authentication (MFA) policies for your
      organization.
  - name: Mfa
    description: Manage MFA enrollment and verification for individual users.
  - name: CustomHostnames
    description: >-
      Configure custom hostnames for white-labeling the Dynamic authentication
      experience.
  - name: TestAccount
    description: >-
      Manage test accounts used for automated testing and QA within an
      environment.
  - name: NameServices
    description: >-
      Configure name service integrations (ENS, Unstoppable Domains, etc.) for
      human-readable wallet addresses.
  - name: GlobalWallets
    description: >-
      Manage global wallets shared across multiple environments in an
      organization.
  - name: GlobalWalletConnections
    description: Configure which environments can access and use global wallets.
  - name: GlobalWalletAccessControl
    description: Control which users and roles can access and operate global wallets.
  - name: UserApiTokens
    description: >-
      Create and manage user-scoped API tokens for programmatic access on behalf
      of a user.
  - name: Waas
    description: Wallet-as-a-Service endpoints for creating and managing embedded wallets.
  - name: WalletConnect
    description: Configure WalletConnect integration settings for your environment.
  - name: Checkout
    description: >-
      Accept crypto payments and deposits from any wallet. Settle in any token
      you choose.
  - name: Flow
    description: >-
      Accept crypto payments, deposits, and withdrawals. Amount and destination
      are fixed server-side at create; the post-create lifecycle is driven with
      a capability session token.
  - name: FlowAnalytics
    description: >-
      Query aggregated analytics and paginated transaction lists for the Flow
      product.
  - name: Gasless
    description: >-
      Query billing summaries and paginated transaction lists for sponsored
      (gasless) transactions.
  - name: Custom Networks
    description: >-
      Add and manage custom EVM-compatible networks beyond the built-in chain
      list.
  - name: Chainalysis
    description: >-
      Configure Chainalysis integration for blockchain address screening and
      risk assessment.
  - name: Visits
    description: Track and query user visit activity within your environment.
  - name: ExternalJwt
    description: >-
      Configure external JWT providers so existing auth tokens can be used with
      Dynamic.
  - name: SDK Views
    description: >-
      Manage SDK view configurations that customize the appearance of Dynamic
      modals and flows.
  - name: DeeplinkUrls
    description: Configure deep link URLs for mobile app integration with the Dynamic SDK.
  - name: OrganizationSettings
    description: >-
      Read and update organization-level settings such as approval workflow
      configuration.
  - name: AdminActions
    description: >-
      Manage admin action requests that require approval from another
      administrator.
  - name: ClientGrant
    description: |
      OAuth 2.0 Device Authorization Grant flow (RFC 8628) used by first-party
      Dynamic clients (CLI, MCP server, demo apps, IDE plugins) to obtain a
      revocable, 30-day client JWT without ever seeing the user's dashboard
      session token.
  - name: AuthorizedClients
    description: |
      Manage first-party clients (CLI / MCP / demo / IDE plugins) authorized
      to act as a dashboard user. Surfaced under Profile → Authorized Clients.
  - name: Kyb
    description: >-
      Verify a business's identity via AI Prise passthrough and check KYB tier
      status.
  - name: BusinessAccounts
    description: >-
      Administer the business accounts (multi-operator wallet containers) that
      end users create in an environment.
  - name: ScreeningPolicies
    description: |
      Author per-vendor address screening policies that map TRM and Chainalysis
      signals to block, alert, or allow, plus per-address exceptions. The
      sanctions floor sits underneath every policy and is not configurable.
paths:
  /sdk/{environmentId}/businessAccounts/{businessAccountId}/proposals/{proposalId}:
    get:
      tags:
        - SDK
      summary: SDK — read one proposal, including the intent to sign
      description: >
        Returns the stored intent verbatim. An approver signs THESE bytes: a

        re-derived intent would carry a different `intentId` and `createdAt`,
        and

        every approval already collected would stop verifying.
      operationId: sdkGetBusinessAccountProposal
      parameters:
        - $ref: '#/components/parameters/environmentId'
        - $ref: '#/components/parameters/businessAccountId'
        - $ref: '#/components/parameters/businessAccountProposalId'
      responses:
        '200':
          description: The proposal
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessAccountProposal'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/BusinessAccountForbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - bearerAuth: []
components:
  parameters:
    environmentId:
      in: path
      name: environmentId
      required: true
      description: ID of the environment
      schema:
        $ref: '#/components/schemas/uuid'
    businessAccountId:
      in: path
      name: businessAccountId
      required: true
      description: ID of the business account
      schema:
        $ref: '#/components/schemas/uuid'
    businessAccountProposalId:
      in: path
      name: proposalId
      required: true
      description: ID of the business account proposal
      schema:
        $ref: '#/components/schemas/uuid'
  schemas:
    BusinessAccountProposal:
      type: object
      description: >
        A governed mutation waiting on consent. Untrusted workflow state: it
        records what was proposed and who has signed, and the enclave verifies
        every signature when the proposal is executed. The signature is over
        `intent` as stored, so an approver must sign these exact bytes —
        re-deriving the intent would produce a different `intentId` and
        invalidate the approvals already collected.
      required:
        - actionType
        - approvals
        - businessAccountId
        - completeBy
        - createdAt
        - id
        - initiatorUserId
        - intent
        - status
      properties:
        id:
          type: string
          format: uuid
        businessAccountId:
          type: string
          format: uuid
        actionType:
          $ref: '#/components/schemas/BusinessAccountGovernedAction'
        status:
          $ref: '#/components/schemas/BusinessAccountProposalStatus'
        initiatorUserId:
          type: string
          format: uuid
          description: >
            Who proposed it. They can never approve their own intent, so they
            are never counted toward a requirement.
        intent:
          $ref: '#/components/schemas/BusinessAccountMutationIntent'
        completeBy:
          type: string
          format: date-time
          description: >
            The one deadline for the whole proposal, derived from the signed
            intent's `createdAt`. Past it the proposal accepts no further
            approvals AND can no longer be executed.
        consumedAt:
          type: string
          format: date-time
          nullable: true
          description: When it left `pending`; null while still open.
        createdAt:
          type: string
          format: date-time
        approvals:
          type: array
          items:
            $ref: '#/components/schemas/BusinessAccountProposalApprovalRecord'
        autoExecute:
          type: boolean
          description: >
            Whether this applies as soon as its quorum is met, or waits for an
            explicit execute. A copy of the flag inside the signed intent, which
            is the authority. An approver needs this to know whether their
            approval is the one that lands the change.
        subjects:
          type: array
          description: >
            The users this change is about, resolved for display — the member
            being added, the signer being removed, the new owner. Empty for a
            change that names no user, such as `setGovernance`.
          items:
            $ref: '#/components/schemas/BusinessAccountProposalSubject'
        approvalRequirements:
          type: array
          description: >
            Every governance rule matching this proposal, with how close each
            is. Do NOT derive progress from `approvals` — that counts rows,
            including approvers outside a rule's pool and approvers demoted
            since they signed.

            Absent means the tally is unknown (not fetched, or no longer
            pending); an empty array means nothing is outstanding. Treat the two
            differently.
          items:
            $ref: '#/components/schemas/BusinessAccountApprovalRequirementStatus'
    uuid:
      type: string
      pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
      minLength: 36
      maxLength: 36
      example: 95b11417-f18f-457f-8804-68e361f9164f
    BusinessAccountGovernedAction:
      type: string
      description: A business-account mutation that an approval requirement can gate.
      enum:
        - addMember
        - removeMember
        - updateMemberRole
        - transferOwnership
        - createWallet
        - linkWallet
        - removeWallet
        - addSignerToWallet
        - removeSignerFromWallet
        - setGovernance
        - defineRole
        - deleteRole
    BusinessAccountProposalStatus:
      type: string
      description: >
        Lifecycle of a governed mutation awaiting approvals. Only `pending`
        accepts approvals; the other three are terminal.
      enum:
        - pending
        - executed
        - vetoed
        - expired
    BusinessAccountMutationIntent:
      type: object
      description: >
        The initiator's proposal, signed with their session key. Built by the
        API, not the client — sign these exact bytes verbatim, because
        re-serializing can change them and invalidate the signature.

        `autoExecute` is inside the signed bytes, so an approver consents to it
        and nothing can flip it afterwards.
      additionalProperties: true
    BusinessAccountProposalApprovalRecord:
      type: object
      description: >
        One approver's recorded consent. Withdrawing sets `revokedAt` rather
        than deleting the row, so a change of mind stays auditable — a revoked
        approval is not forwarded to the enclave and does not count toward a
        requirement.
      required:
        - approvedAt
        - approverUserId
      properties:
        approverUserId:
          type: string
          format: uuid
        approvedAt:
          type: string
          format: date-time
          description: The approver's own signed timestamp, stored as given.
        revokedAt:
          type: string
          format: date-time
          nullable: true
          description: Set when the approver withdrew; null while the consent counts.
    BusinessAccountProposalSubject:
      type: object
      description: >
        A user the proposed change is about, resolved for display. An approver
        is consenting to a change that names people by id, so without this they
        cannot see who they are approving. Derived at read time, never signed —
        the authority for what will be applied is `intent`.
      required:
        - userId
      properties:
        userId:
          type: string
          format: uuid
        email:
          type: string
          nullable: true
          description: >
            Their oldest verified email, null when they have none or are not yet
            a member of this environment.
    BusinessAccountApprovalRequirementStatus:
      type: object
      description: >
        One governance requirement and how close it is to being met. Every
        matching requirement is reported, not only the unmet ones, so a client
        can show per-rule progress rather than a rule appearing only once it is
        short.

        Computed inside the enclave: eligibility resolves from the signed
        document, so whether a given approval counts depends on roles that are
        not readable outside it. A client cannot derive these numbers from the
        approval list.
      required:
        - action
        - approved
        - required
        - requirementId
        - satisfied
      properties:
        action:
          type: string
          description: >
            The change type this rule governs. Requirement ids are unique per
            action only, so a change set spanning two actions can report the
            same id twice.
          example: addMember
        requirementId:
          type: string
        required:
          type: integer
        approved:
          type: integer
          description: >
            Approvals that COUNT toward this requirement — not the raw approval
            count. An approver outside the eligible pool, or one demoted since
            they approved, is not included.
        satisfied:
          type: boolean
          description: >
            Authoritative. `approved >= required` is not sufficient: a mandatory
            approver role with nobody's approval leaves this false with the
            count already met.
        unmetMandatoryRoles:
          type: array
          description: >
            Mandatory approver roles still lacking an approval, present only
            when they are what is holding the requirement back.
          items:
            type: string
    BadRequest:
      type: object
      properties:
        error:
          description: Human-readable error message
          type: string
    Unauthorized:
      type: object
      properties:
        error:
          description: Human-readable error message describing the authentication failure
          type: string
          example: No jwt provided!
    BusinessAccountForbidden:
      allOf:
        - $ref: '#/components/schemas/Forbidden'
        - type: object
          description: >
            Carries the requirement tallies when the caller is authorized but
            consent is outstanding, which is a different thing from being
            refused outright.
          properties:
            approvalRequirements:
              type: array
              items:
                $ref: '#/components/schemas/BusinessAccountApprovalRequirementStatus'
    NotFound:
      type: object
      required:
        - error
        - code
      properties:
        error:
          description: Human-readable error message
          type: string
          example: Not Found
        code:
          description: Machine-readable error code
          type: string
          example: not_found
    InternalServerError:
      type: object
      properties:
        error:
          description: Human-readable error message
          type: string
          example: Internal Server Error
    Forbidden:
      type: object
      properties:
        error:
          description: Human-readable error message
          type: string
          example: Access Forbidden
  responses:
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BadRequest'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Unauthorized'
    BusinessAccountForbidden:
      description: >
        Forbidden. Carries the outstanding approval requirements when the caller
        is authorized but consent is incomplete.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BusinessAccountForbidden'
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/NotFound'
    InternalServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InternalServerError'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````