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

# Verify wallet allowances

> Activate a self-custody wallet from the allowances it has already granted on-chain.

**Requires scope:** `manage:accounts` — see [Required scopes](/getting-started/authentication#required-scopes-finance-api).

Activates a self-custody account wallet by reading the allowances it has already granted on-chain, instead of going through the permit flow.

This is the route for a **smart-contract wallet** — a Safe, for example. A contract wallet is controlled by its owners rather than a single key, so it cannot produce the one signature a permit needs. It grants the same permission with a plain `approve(spender, amount)` transaction instead.

The allowance *is* the consent: only the wallet's controller could have granted it. So this endpoint reads public chain state and takes **no request body and no proof**.

## What happens when you call it

<Steps>
  <Step title="Allowances are read synchronously">
    Every asset covered by a sufficient allowance is marked confirmed.
  </Step>

  <Step title="All assets covered → ACTIVE">
    The wallet is usable immediately.
  </Step>

  <Step title="Some assets missing → VERIFYING_ALLOWANCE">
    You get a `verificationExpiresAt`. Venly keeps re-checking until then, so granting the remaining allowances is enough — you don't have to call again.
  </Step>
</Steps>

<Warning>
  `VERIFYING_ALLOWANCE` is a waiting room, not a usable state. Every check that requires an active wallet treats it exactly like `PENDING`, so don't offer the wallet to an end-user until it reads `ACTIVE`.

  If the window closes with assets still uncovered, the wallet falls back to `PENDING` and you start again.
</Warning>

Read `assets[]` to see exactly which allowances are still missing — `allowanceSufficient` is per asset.

Both activation routes end in the same place: a wallet is `ACTIVE` once every supported asset is covered. See [Permits and allowances](/guides/finance/permits-and-allowances).

## Errors

The codes this endpoint can return, in addition to the [standard errors](/guides/finance/errors#standard-errors). Branch on `code`, never the message.

| HTTP  | `code`                  | When                                                                                     |
| ----- | ----------------------- | ---------------------------------------------------------------------------------------- |
| `400` | `wallet-not-verifiable` | the wallet cannot enter verification: it is already `ACTIVE`, or it is `FROZEN`/`CLOSED` |
| `400` | `invalid-request`       | the wallet is Venly-managed, so it activates through the permit flow instead             |


## OpenAPI

````yaml api-reference/Finance-API-Specs.yaml POST /accounts/{accountId}/wallets/{walletId}/allowance-verification
openapi: 3.1.0
info:
  title: Venly Finance API
  description: >
    REST API for the Venly Finance platform:

    - Party management (Individuals & Organisations)

    - Identity verification — hosted KYC/KYB links and Sumsub share-token
    forwarding

    - Account management with party association

    - Wallet balances & token allowances on supported chains

    - Virtual bank accounts for global pay-in (EUR SEPA, USD ACH/WIRE/RTP/SWIFT)

    - Fiat-to-crypto payment sessions (pay-in)

    - Bank pay-outs — beneficiary allow-listing, routes, and PULL/PUSH pay-outs

    - Account-to-account fiat & crypto transfers

    - EIP-2612 permits and allowances

    - Webhook registration for asynchronous event delivery


    ## Authentication


    All endpoints use OAuth2 client credentials. Obtain a token first, then
    include it in every request:


    **Step 1 — Get a token:**

    ```bash

    curl -X POST
    https://login.venly.io/auth/realms/VenlyFinance/protocol/openid-connect/token
    \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=client_credentials&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}"
    ```


    **Step 2 — Use the token:**

    ```

    Authorization: Bearer {access_token}

    ```


    Tokens expire after **5 minutes**. Implement refresh logic in your client.
  version: 1.5.0
  contact:
    name: Venly Support
    email: support@venly.io
    url: https://docs.venlyfinance.com
  license:
    name: Proprietary
  x-logo:
    url: https://venlyfinance.com/logo.png
  x-security-contact: security@venly.io
servers:
  - url: https://api.venlyfinance.com/v1
    description: Production
  - url: https://api-staging.venlyfinance.com/v1
    description: Staging
security:
  - OAuth2: []
tags:
  - name: Parties
    description: Party management (Individuals & Organisations)
  - name: Accounts
    description: Account management, party-role associations
  - name: Wallets
    description: Blockchain wallet balances
  - name: Virtual Bank Accounts
    description: Virtual bank account payment references for global payments
  - name: Fiat-to-crypto Payment Sessions
    description: Fiat-to-crypto payment session creation
  - name: Payout Bank Accounts
    description: Allow-listing beneficiary bank accounts as pay-out destinations
  - name: Payout Routes
    description: >-
      Account-scoped routes pairing a beneficiary bank account with a crypto
      deposit asset
  - name: Payouts
    description: Crypto-to-fiat pay-outs over a registered route
  - name: Transfers
    description: Fiat and crypto transfer operations between accounts
  - name: Permits
    description: EIP-712 permit signature management for token approvals
  - name: Supported Assets
    description: >-
      Discover which chains and assets your tenant can settle in, and whether an
      account can use them yet.
  - name: Allowances
    description: Token allowance management for wallets
  - name: Webhooks
    description: Webhook registration and delivery testing
paths:
  /accounts/{accountId}/wallets/{walletId}/allowance-verification:
    post:
      tags:
        - Allowances
      summary: Activate a wallet from its on-chain allowances
      description: >
        **Requires scope:** `manage:accounts`


        Activates a self-custody account wallet by reading the allowances it has
        already granted

        on-chain, instead of going through the permit flow.


        This is the route for a **smart-contract wallet** (for example a Safe).
        A contract wallet is

        controlled by its owners rather than a single key, so it cannot produce
        the one signature a

        permit needs — it grants the same permission with a plain
        `approve(spender, amount)`

        transaction. The allowance itself is the consent: only the wallet's
        controller could have

        granted it, so this endpoint reads public chain state and takes **no
        request body and no

        proof**.


        Both routes end in the same place: the wallet becomes `ACTIVE` once
        every supported asset is

        covered. See [Permits and
        allowances](/guides/finance/permits-and-allowances).


        **What happens when you call it**


        The wallet's allowances are read synchronously and every covered asset
        is marked confirmed.

        If all assets are covered the wallet returns `ACTIVE` immediately. If
        some are not, it

        returns `VERIFYING_ALLOWANCE` with a `verificationExpiresAt`, and Venly
        keeps re-checking

        until that deadline. Grant the missing allowances before it passes, or
        the wallet falls back

        to `PENDING` and you start again.


        <Note>

        `VERIFYING_ALLOWANCE` is a waiting room, not a usable state — every
        check that requires an

        active wallet treats it exactly like `PENDING`. Don't offer the wallet
        to an end-user until

        it reads `ACTIVE`.

        </Note>
      operationId: verifyWalletAllowances
      parameters:
        - $ref: '#/components/parameters/AccountId'
        - $ref: '#/components/parameters/WalletId'
      responses:
        '200':
          description: Verification outcome and the wallet's resulting status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SingleAllowanceVerificationResponse'
              example:
                success: true
                result:
                  walletId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  status: VERIFYING_ALLOWANCE
                  verificationExpiresAt: '2026-08-20T15:04:05Z'
                  assets:
                    - supportedAssetId: 5d4c5b99-2ce8-40a1-bc1d-173dd400fa89
                      asset: USDC
                      contractAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
                      allowanceSufficient: true
                      permitStatus: CONFIRMED
                    - supportedAssetId: 352fa5ad-ca00-4701-905f-744b867f6d5d
                      asset: EURC
                      contractAddress: '0x808456652fdb597867f38412077a9182bf77359f'
                      allowanceSufficient: false
                      permitStatus: PENDING
        '400':
          description: >
            Bad request. Notable codes:

            - `wallet-not-verifiable` — the wallet cannot enter verification: it
            is already `ACTIVE`, or it is `FROZEN`/`CLOSED`

            - `invalid-request` — the wallet is Venly-managed, so it activates
            through the permit flow instead
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    AccountId:
      name: accountId
      in: path
      required: true
      description: Unique account identifier
      schema:
        type: string
        format: uuid
      example: b2a1f0e9-8c7d-4e3a-9f21-0a1b2c3d4e5f
    WalletId:
      name: walletId
      in: path
      required: true
      description: Unique wallet identifier
      schema:
        type: string
        format: uuid
      example: 9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f
  schemas:
    SingleAllowanceVerificationResponse:
      allOf:
        - $ref: '#/components/schemas/BaseResponse'
        - type: object
          properties:
            result:
              $ref: '#/components/schemas/AllowanceVerificationResult'
    ErrorResponse:
      type: object
      description: Error response wrapper
      properties:
        success:
          type: boolean
          description: Always false for error responses
          example: false
        errors:
          type: array
          description: List of errors that occurred
          items:
            $ref: '#/components/schemas/ErrorBody'
        result:
          type: object
          nullable: true
          description: Null or omitted when success is false
    BaseResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indicates whether the request was successful
    AllowanceVerificationResult:
      type: object
      properties:
        walletId:
          type: string
          format: uuid
        status:
          $ref: '#/components/schemas/WalletStatus'
        verificationExpiresAt:
          type: string
          format: date-time
          nullable: true
          description: >
            When the verification window closes. Present while `status` is
            `VERIFYING_ALLOWANCE`.

            Grant the missing allowances before this passes, or the wallet
            reverts to `PENDING` and

            you have to start again. Null once the wallet is `ACTIVE`.
        assets:
          type: array
          description: >-
            Per-asset outcome, so you can see exactly which allowances are still
            missing
          items:
            $ref: '#/components/schemas/AllowanceVerificationAsset'
    ErrorBody:
      type: object
      description: Individual error details
      properties:
        code:
          type: string
          description: Machine-readable error code
          example: invalid-request
        message:
          type: string
          description: Human-readable error message
          example: The request contains invalid parameters.
    WalletStatus:
      type: string
      description: >
        Lifecycle of an account or escrow wallet. Only `ACTIVE` wallets can move
        funds.


        - `PENDING` — created; no usable allowance yet

        - `ACTIVE` — usable

        - `VERIFYING_ALLOWANCE` — on-chain allowances are being verified so the
        wallet can activate
          without a permit. A waiting room, **not** a usable state: every check that requires an
          active wallet treats it exactly like `PENDING`. Reached only by self-custody account
          wallets, and only via
          [Activate a wallet from its on-chain allowances](/api-reference/Finance-API/allowances/verify-wallet-allowances).
        - `FROZEN` — administratively blocked

        - `CLOSED` — no longer in use
      enum:
        - PENDING
        - ACTIVE
        - VERIFYING_ALLOWANCE
        - FROZEN
        - CLOSED
    AllowanceVerificationAsset:
      type: object
      properties:
        supportedAssetId:
          type: string
          format: uuid
        asset:
          type: string
          example: USDC
        contractAddress:
          type: string
        allowanceSufficient:
          type: boolean
          description: >-
            Whether the on-chain allowance for this asset covers what settlement
            needs
        permitStatus:
          $ref: '#/components/schemas/PermitStatus'
    PermitStatus:
      type: string
      description: Status of an EIP-712 permit
      enum:
        - PENDING
        - SUBMITTED
        - CONFIRMED
        - FAILED
  responses:
    Unauthorized:
      description: Authentication required or failed (401)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            errors:
              - code: unauthenticated
                message: Please authenticate to perform this action.
    Forbidden:
      description: Caller lacks the required authority/role (403)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            errors:
              - code: forbidden
                message: You do not have permission to access this resource.
    NotFound:
      description: Resource not found (404)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            errors:
              - code: account-not-found
                message: The requested resource was not found.
    InternalServerError:
      description: Unexpected server error (500)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            errors:
              - code: internal-error
                message: An unexpected error occurred. Please try again later.
  securitySchemes:
    OAuth2:
      type: oauth2
      description: >
        OAuth2 client credentials flow. Token endpoints:

        - Staging:
        https://login-staging.venly.io/auth/realms/VenlyFinance/protocol/openid-connect/token

        - Production:
        https://login.venly.io/auth/realms/VenlyFinance/protocol/openid-connect/token
      flows:
        clientCredentials:
          tokenUrl: >-
            https://login-staging.venly.io/auth/realms/VenlyFinance/protocol/openid-connect/token
          scopes: {}

````