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

# Create Virtual Account

> Opens a new virtual bank account. Virtual accounts are real Nigerian bank
accounts (with valid account numbers) that sit under your master account.

**Two types:**
- **STATIC**: Permanent account. Stays open until you close it. Good for assigning one account per customer.
- **DYNAMIC**: Temporary account with an expiry time (in hours). After expiry, it is automatically closed. Good for one-time payment links.

Funds received into virtual accounts show up in your dashboard and trigger webhook notifications.




## OpenAPI

````yaml POST /api/v1/accounts
openapi: 3.0.3
info:
  title: Union Bank BaaS API
  version: '1.0'
  description: >
    **Union Bank Nigeria, Banking as a Service (BaaS) Platform**


    Build financial products on top of Union Bank's core banking infrastructure.

    This API gives your application the ability to open virtual accounts,
    initiate

    payments, collect money, verify identities, and manage webhooks, all in one
    place.


    ## Before You Start


    You must complete the **partner onboarding journey** before your API keys
    work:

    1. Register at [ubn-ui.onecluster.co](https://ubn-ui.onecluster.co)

    2. Verify your business email

    3. Upload your business documents (KYB)

    4. Pass identity verification (KYC)

    5. Receive your sandbox API key


    ## Base URLs


    | Environment | Base URL |

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

    | Sandbox (for testing) | `https://api-partner.onecluster.co` |

    | Production (for live apps) | `https://api.onecluster.co` |


    ## How to Authenticate


    Add your API key to every request as a header:


    ```

    Authorization: ApiKey ubn_sb_your_key_here

    ```


    For payments, you also need to attach a **digital signature** (HMAC-SHA256)
    and an

    **mTLS client certificate**. See the [Authentication
    Guide](/api-reference/authentication) for details.


    ## Standard Request Headers


    | Header | Required | Description |

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

    | `Authorization` | Yes | Your API key. Format: `ApiKey ubn_sb_xxx` |

    | `X-Correlation-ID` | No | A UUID you choose, used to trace this request in
    logs. We generate one if you omit it. |

    | `X-Idempotency-Key` | Yes (write ops) | A UUID you choose. If you send the
    same request twice with the same key, we return the original result, not a
    duplicate. |

    | `X-Signature` | Yes (payments, KYC) | HMAC-SHA256 signature of the request
    body. See Authentication guide. |


    ## Standard Response Headers


    | Header | Description |

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

    | `X-Correlation-ID` | The trace ID for this request (echoed from your
    request or generated by us) |

    | `X-Quota-Remaining` | How many API calls you have left in this billing
    period |

    | `X-Quota-Limit` | Your total API call quota for this billing period |

    | `X-Quota-Reset` | When your quota resets (Nigeria time, WAT +01:00) |

    | `X-Circuit-Breaker-Open` | Present and `true` if our system is temporarily
    pausing requests to protect stability |

    | `X-Key-Rotation-Warning` | Present when your API key is about to expire
    (within 72 hours of rotation) |
  contact:
    name: UBN BaaS Support
    email: baas-support@unionbank.ng
    url: https://dash.onecluster.co/resources/support
  license:
    name: Proprietary
    url: https://unionbank.ng/terms
servers:
  - url: https://api-partner.onecluster.co
    description: Sandbox - use this for testing. No real money moves.
  - url: https://api.onecluster.co
    description: Production - live environment. Real transactions.
security:
  - ApiKeyAuth: []
tags:
  - name: Accounts
    description: Open and manage virtual bank accounts
  - name: Payments
    description: Send money to any Nigerian bank account
  - name: Collections
    description: Receive money into virtual collection accounts
  - name: KYC
    description: Verify customer identities (BVN, NIN, CAC)
  - name: Health
    description: Check if the API is up and running
paths:
  /api/v1/accounts:
    post:
      tags:
        - Accounts
      summary: Create a virtual account
      description: >
        Opens a new virtual bank account. Virtual accounts are real Nigerian
        bank

        accounts (with valid account numbers) that sit under your master
        account.


        **Two types:**

        - **STATIC**: Permanent account. Stays open until you close it. Good for
        assigning one account per customer.

        - **DYNAMIC**: Temporary account with an expiry time (in hours). After
        expiry, it is automatically closed. Good for one-time payment links.


        Funds received into virtual accounts show up in your dashboard and
        trigger webhook notifications.
      operationId: createAccount
      parameters:
        - $ref: '#/components/parameters/CorrelationId'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAccountRequest'
            examples:
              static:
                summary: Create a permanent account
                value:
                  partnerId: 9a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d
                  accountType: STATIC
              dynamic:
                summary: Create a 24-hour temporary account
                value:
                  partnerId: 9a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d
                  accountType: DYNAMIC
                  expiryHours: 24
      responses:
        '201':
          description: Virtual account created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                success: true
                responseCode: '00'
                message: Account created
                data:
                  accountNumber: '0123456789'
                  bankCode: '032'
                  bankName: Union Bank of Nigeria
                  accountType: STATIC
                  currency: NGN
                  createdAt: '2026-03-25T10:00:00+01:00'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/QuotaExhausted'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    CorrelationId:
      name: X-Correlation-ID
      in: header
      required: false
      description: >
        A UUID v4 you generate to trace this request through our systems.

        If you don't provide one, we generate it for you.

        Always include it in support requests, it helps us find your request in
        logs.
      schema:
        type: string
        format: uuid
        example: 7f3a9c21-4e8b-4a12-b6d1-3c8a7f2e1b09
    IdempotencyKey:
      name: X-Idempotency-Key
      in: header
      required: true
      description: >
        A UUID you generate. If you send the same request twice with the same
        key

        (within 24 hours), we return the original response, not a duplicate
        action.

        Generate a new UUID for every new operation.
      schema:
        type: string
        format: uuid
        example: 550e8400-e29b-41d4-a716-446655440000
  schemas:
    CreateAccountRequest:
      type: object
      required:
        - partnerId
        - accountType
      properties:
        partnerId:
          type: string
          format: uuid
          description: Your Partner ID
        accountType:
          type: string
          enum:
            - STATIC
            - DYNAMIC
          description: |
            - `STATIC`: Permanent account (stays open until you close it)
            - `DYNAMIC`: Temporary account that auto-closes after `expiryHours`
        expiryHours:
          type: integer
          description: >-
            How many hours until this account closes. Required when
            `accountType` is `DYNAMIC`.
          minimum: 1
          maximum: 720
          example: 24
    SuccessEnvelope:
      type: object
      description: Standard response wrapper for all successful API calls
      required:
        - success
        - responseCode
        - message
        - data
      properties:
        success:
          type: boolean
          description: Always `true` for successful responses
          example: true
        responseCode:
          type: string
          description: '`00` means success'
          example: '00'
        message:
          type: string
          description: Human-readable description of the result
          example: Request processed successfully
        data:
          type: object
          description: The actual response data (varies by endpoint)
    ProblemDetails:
      type: object
      description: >
        Standard error response following [RFC
        7807](https://tools.ietf.org/html/rfc7807).

        All errors use this format.
      required:
        - type
        - title
        - status
        - detail
      properties:
        type:
          type: string
          format: uri
          description: A link to the specific error type documentation
          example: https://api.onecluster.co/errors/insufficient-funds
        title:
          type: string
          description: Short, human-readable error name
          example: Insufficient Funds
        status:
          type: integer
          description: HTTP status code
          example: 422
        detail:
          type: string
          description: Full explanation of what went wrong and how to fix it
          example: >-
            The account balance is ₦0.00. You need at least ₦50,000.00 to
            complete this transfer.
        instance:
          type: string
          format: uri
          description: The API path where the error occurred
          example: /api/v1/payments/transfer
        correlationId:
          type: string
          format: uuid
          description: The trace ID, include this when contacting support
        code:
          type: string
          description: Machine-readable error code
          example: INSUFFICIENT_FUNDS
  responses:
    BadRequest:
      description: Bad request, check your request body against the schema
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Unauthorized:
      description: >
        Authentication failed. Check that your `Authorization` header is
        correct.

        Format: `ApiKey ubn_sb_your_key_here`
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    QuotaExhausted:
      description: >
        You have used all your API calls for this billing period.

        Check `X-Quota-Reset` in the response header to see when your quota
        resets.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    UnprocessableEntity:
      description: Request structure is valid but the data fails business rules
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    RateLimited:
      description: |
        Too many requests in a short time. Wait before retrying.
        Check `Retry-After` header for how many seconds to wait.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: |
        Your API key, formatted as: `ApiKey ubn_sb_your_key_here`

        - Sandbox keys start with `ubn_sb_`
        - Production keys start with `ubn_pk_`
        - Never use production keys during testing, they will charge real money

````