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

# Get Virtual Account Status (User)

> Returns everything you need to decide whether to request a virtual account for a user: whether they already have one, whether a request would be accepted right now, the state of their latest onboarding, and any identity data still missing. Safe to poll while an onboarding is in flight.

Returns everything you need to decide whether to request a **named virtual account** for a user: whether they already have one, whether a request would be accepted right now, the state of their latest onboarding, and whether their KYB is still outstanding. See the [Virtual Accounts guide](/docs/virtual-accounts) for the full flow.

Currently available for the **United States (`US`)** only. `country` is required — any other value is rejected with `400`.

This endpoint is read-only and safe to poll while an onboarding is in flight.

***

## Reading the Response

| Field                 | Description                                                                                                                                                                                                                      |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hasVirtualAccount`   | The user already has an active virtual account in this country.                                                                                                                                                                  |
| `canRequest`          | A [request](/reference/bankingonboardingpartnerv2controller_requestonboarding) right now would be accepted — KYB complete, no existing virtual account, and no onboarding in flight. Use this to gate a "Get an account" button. |
| `status`              | State of the user's most recent onboarding for this country.                                                                                                                                                                     |
| `missingRequirements` | What is still outstanding on the user's KYB. Empty once KYB is complete.                                                                                                                                                         |

### Status Values

| `status`      | Meaning                                                                                                                                            |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NOT_STARTED` | No onboarding has ever been created for this user and country.                                                                                     |
| `IN_PROGRESS` | Submitted to the banking provider, awaiting a decision. Keep polling.                                                                              |
| `COMPLETED`   | Approved and provisioned. The account is available from [List Bank Accounts](/reference/userbankinfopartnerv2controller_getuserbankinfosbyuserid). |
| `FAILED`      | The onboarding did not complete. `canRequest` returns to `true`, so it can be retried.                                                             |

<Note>
  `status: "COMPLETED"` and `hasVirtualAccount: true` are related but not identical. `status` reflects the onboarding record; `hasVirtualAccount` reflects whether an active account actually exists for the user today. Gate your UI on `canRequest`, and fetch the account details once `hasVirtualAccount` is `true`.
</Note>

### Polling

There is no webhook for virtual account onboarding. After a `SUBMITTED` response, poll this endpoint until `status` is `COMPLETED` or `FAILED`. Provider approval typically takes minutes to hours, so poll every few minutes rather than every few seconds.

***

## Error Codes

### Common Errors

| HTTP Status | Code                   | Message                            |
| ----------- | ---------------------- | ---------------------------------- |
| 401         | `UNAUTHORIZED`         | "API Key is missing"               |
| 401         | `UNAUTHORIZED`         | "Invalid API Key format"           |
| 401         | `UNAUTHORIZED`         | "Invalid API Key"                  |
| 403         | `INVALID_PARTNER_FLOW` | "The partner has an invalid flow." |

### User Ownership Errors

| HTTP Status | Code           | Message                                              |
| ----------- | -------------- | ---------------------------------------------------- |
| 401         | `UNAUTHORIZED` | "Partner information is required for this operation" |
| 401         | `UNAUTHORIZED` | "User is not associated with the partner"            |

### Endpoint-Specific Errors

| HTTP Status | Code                       | Message                                                                                |
| ----------- | -------------------------- | -------------------------------------------------------------------------------------- |
| 400         | `INVALID_USER_INPUT_ERROR` | "Invalid User Input" — `country` is missing, not `US`, or `userId` is not a valid UUID |
| 404         | `NOT_FOUND_ERROR`          | "User {userId} not found"                                                              |


## OpenAPI

````yaml reference/openapi/BankingOnboardingPartnerV2Controller_getOnboardingStatus.json GET /api/partner/v2/banks/users/{userId}/banking-onboarding
openapi: 3.0.0
info:
  title: Capa Partner API - V2
  description: >-
    Partner API for integrating cryptocurrency on-ramp and off-ramp services
    using Capa's infrastructure. Enable your users to seamlessly convert between
    fiat and crypto.
  version: v2
  contact: {}
servers:
  - url: https://api.sandbox.capa.fi
  - url: https://production-api.capa.fi
security: []
paths:
  /api/partner/v2/banks/users/{userId}/banking-onboarding:
    get:
      tags:
        - banks
      summary: Get virtual account onboarding status for a user
      description: >-
        Returns everything you need to decide whether to request a virtual
        account for a user: whether they already have one, whether a request
        would be accepted right now, the state of their latest onboarding, and
        any identity data still missing. Safe to poll while an onboarding is in
        flight.
      operationId: BankingOnboardingPartnerV2Controller_getOnboardingStatus
      parameters:
        - name: userId
          required: true
          in: path
          description: >-
            The ID of the user to check. Must belong to the authenticated
            partner.
          schema:
            example: 8374f327-38bd-4b0b-b8a7-2524599eb903
            type: string
        - name: country
          required: true
          in: query
          description: >-
            The country whose banking onboarding to check. Only `US` is
            currently supported.
          schema:
            enum:
              - US
            type: string
            example: US
      responses:
        '200':
          description: >-
            Current onboarding eligibility and status for the user in the given
            country.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      hasVirtualAccount:
                        type: boolean
                        description: >-
                          Whether the user already has an active virtual account
                          in this country.
                      canRequest:
                        type: boolean
                        description: >-
                          Whether a request right now would be accepted: KYB
                          complete, no existing virtual account, and no
                          onboarding in flight.
                      status:
                        description: >-
                          State of the user's most recent onboarding for this
                          country. `NOT_STARTED` means no onboarding has ever
                          been created.
                        enum:
                          - NOT_STARTED
                          - IN_PROGRESS
                          - COMPLETED
                          - FAILED
                        type: string
                      missingRequirements:
                        description: >-
                          What is still outstanding on the user's KYB. Surfaced
                          so you can show a reason in your UI — you do not need
                          to collect these fields yourself; completing KYB
                          satisfies them. Empty once KYB is complete.
                        type: array
                        items:
                          type: object
                          properties:
                            field:
                              type: string
                              description: >-
                                Path into the user's identity that is still
                                outstanding, e.g. `taxId`, `documents.TAX_ID`.
                            message:
                              type: string
                              description: >-
                                Human-readable description of what is
                                outstanding.
                          required:
                            - field
                            - message
                    required:
                      - hasVirtualAccount
                      - canRequest
                      - status
                      - missingRequirements
              examples:
                READY:
                  summary: Ready to request
                  value:
                    success: true
                    data:
                      hasVirtualAccount: false
                      canRequest: true
                      status: NOT_STARTED
                      missingRequirements: []
                REQUIREMENTS_MISSING:
                  summary: KYB not complete
                  value:
                    success: true
                    data:
                      hasVirtualAccount: false
                      canRequest: false
                      status: NOT_STARTED
                      missingRequirements:
                        - field: taxId
                          message: Tax ID is required for business onboarding
                IN_PROGRESS:
                  summary: Onboarding in flight
                  value:
                    success: true
                    data:
                      hasVirtualAccount: false
                      canRequest: false
                      status: IN_PROGRESS
                      missingRequirements: []
                COMPLETED:
                  summary: Virtual account provisioned
                  value:
                    success: true
                    data:
                      hasVirtualAccount: true
                      canRequest: false
                      status: COMPLETED
                      missingRequirements: []
                FAILED:
                  summary: Onboarding failed — retryable
                  value:
                    success: true
                    data:
                      hasVirtualAccount: false
                      canRequest: true
                      status: FAILED
                      missingRequirements: []
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                code: INVALID_USER_INPUT_ERROR
                message: Invalid User Input
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                UNAUTHORIZED:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: API Key is missing
                UNAUTHORIZED_2:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: Invalid API Key format
                UNAUTHORIZED_3:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: Invalid API Key
                UNAUTHORIZED_4:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: User is not associated with the partner
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                code: INVALID_PARTNER_FLOW
                message: The partner has an invalid flow.
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                code: NOT_FOUND_ERROR
                message: User 8374f327-38bd-4b0b-b8a7-2524599eb903 not found
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                code: INTERNAL_SERVER_ERROR
                message: Internal server error
      security:
        - PartnerApiKey: []
components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        code:
          type: string
          description: Machine-readable error code.
        message:
          type: string
          description: Human-readable error message.
        errors:
          type: array
          description: Optional per-field validation details.
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string
      required:
        - success
        - code
        - message
  securitySchemes:
    PartnerApiKey:
      type: apiKey
      in: header
      name: partner-api-key
      description: API key for the affiliated partner performing the request.

````