Bank Statement

The Bank Statement API lets you request and download a monthly bank statement (PDF) for a Virtual Bank Account (VBA). Statements are generated asynchronously: you request a statement for a given month, poll for its status, and download the PDF once it is ready. You can also subscribe to a webhook to be notified automatically when a statement has been generated.

A typical use case is sharing a VBA bank statement with a third party (for example, a marketplace such as Amazon) to verify your bank account.

Authorization

OAuth2 token is required in the Authorization header.

📘

Headers

Three headers are required to use this endpoint.

Required Headers
     <th style={{ textAlign: "left" }}>
       Type
     </th>

     <th style={{ textAlign: "left" }}>
       Required
     </th>

     <th style={{ textAlign: "left" }}>
       Description
     </th>
   </tr>
 </thead>

 <tbody>
   <tr>
     <td style={{ textAlign: "left" }}>
       `Authorization`
     </td>

     <td style={{ textAlign: "left" }}>
       `string`
     </td>

     <td style={{ textAlign: "left" }}>
       Yes
     </td>

     <td style={{ textAlign: "left" }}>
       Bearer token (OAuth 2.0)
       This header holds the bearer token required to use Veem's public API, and **belongs to the owner account**. Failure to use a valid bearer token will result in a 404 (Not Found) status code in the response. An example of a valid header value is as follows:
       `Bearer c047594b-082c-4da1-be89-08fe3770f4b3`

       See [Get Access Token section](https://developer.veem.com/docs/oauth#1---get-access-token)  to generate your Bearer token
     </td>
   </tr>

   <tr>
     <td style={{ textAlign: "left" }}>
       `X-Request-Id`
     </td>

     <td style={{ textAlign: "left" }}>
       `string`
     </td>

     <td style={{ textAlign: "left" }}>
       Yes
     </td>

     <td style={{ textAlign: "left" }}>
       This is a unique string that identifies the current API request, and should follow the UUID format. Reusing this header without changing the value will result in a 409 (Conflict) status code in the response. An example X-request-id is as follows:\
       `48855846-628d-4177-b071-80332a116f0a`
     </td>
   </tr>

   <tr>
     <td style={{ textAlign: "left" }}>
       `Content-Type`
     </td>

     <td style={{ textAlign: "left" }}>
       `string`
     </td>

     <td style={{ textAlign: "left" }}>
       Yes
     </td>

     <td style={{ textAlign: "left" }}>
       The content type of the request. Must be `application/json`
     </td>
   </tr>
 </tbody>

Bank Statement Endpoints

Use the following base URL to access the endpoints in the sandbox environment.

https://sandbox-api.veem.com/veem/
ActionEndpoint
Request a bank statementPOST /v1.2/virtual-bank-account/statements
Get a bank statementGET /v1.2/virtual-bank-account/statements/{statementRequestId}

Request a Bank Statement

Requests the generation of a bank statement for a Virtual Bank Account for a given year and month. Generation is asynchronous, so the response is returned immediately with status set to IN_PROGRESS and no download URL yet. Poll the Get a Bank Statement endpoint (or subscribe to the Bank Statement Webhook) to know when the PDF is ready.

POST /v1.2/virtual-bank-account/statements

Partner Notes:

  • A partner account can be configured to make this API request on behalf of their customers. This requires internal configuration for the partner account by Veem. Once the internal configuration is enabled, the API request can be made using the partner account bearer token.
  • onBehalfAccountId is an optional parameter, this needs to be included in the request body in case of a partner making an API request on behalf of their customer. This is the customer Veem account ID.

Request Payload

{
    "fundingMethodId": 55073,
    "year": 2026,
    "month": 4,
    "onBehalfAccountId": 123456
}

Request Parameters

ParameterMandatory?Format/ValuesSize/Type
fundingMethodIdYesThe funding method ID of the Virtual Bank Account the statement is requested for. Use List Funding Methods to retrieve it.Long
yearYesThe statement year. Must be between 2000 and 2999.Integer
monthYesThe statement month. Must be between 1 (January) and 12 (December).Integer
onBehalfAccountIdNoThe customer Veem account ID. Include only when a partner makes the request on behalf of their customer.Long

Response Payload

Once a valid request has been sent, a response payload of this format should be expected:

{
    "statementRequestId": 4821,
    "resourceType": "VBA",
    "fundingMethodId": 55073,
    "year": 2026,
    "month": 4,
    "status": "IN_PROGRESS",
    "createdAt": 1746057600000,
    "updatedAt": 1746057600000
}

Response Parameters

ParameterTypeDescription
statementRequestIdintegerUnique identifier of the statement request. Use it to poll status and download the statement.
resourceTypestringThe resource the statement was requested for. Currently always VBA.
fundingMethodIdintegerFunding method ID of the Virtual Bank Account the statement was requested for.
yearintegerThe statement year.
monthintegerThe statement month (112).
statusstringCurrent status of the statement request. See Statement Statuses.
createdAtintegerTimestamp when the statement request was created, in Java epoch format (milliseconds).
updatedAtintegerTimestamp when the statement request was last updated, in Java epoch format (milliseconds).
downloadUrlstringPre-signed URL to download the statement PDF. Only present when status is COMPLETED.
expiresAtintegerTimestamp when downloadUrl expires, in Java epoch format (milliseconds). Only present when status is COMPLETED.
generatedAtintegerTimestamp when the statement PDF was generated, in Java epoch format (milliseconds). Present once generation has finished.
failureReasonstringDescription of the failure. Only present when status is FAILED.
📘

Idempotency

Requesting a statement for the same Virtual Bank Account and the same year/month returns the existing statementRequestId instead of creating a duplicate. A statement that previously ended in FAILED is automatically reset to IN_PROGRESS and re-generated.

Get a Bank Statement

Retrieves the current status of a statement request. When the statement is ready (status = COMPLETED), the response also includes a downloadUrl that you can use to download the statement PDF.

// Example request: GET /v1.2/virtual-bank-account/statements/4821
GET /v1.2/virtual-bank-account/statements/{statementRequestId}

Path Parameters

ParameterTypeRequiredDescription
statementRequestIdintegerYesThe ID returned by the Request a Bank Statement endpoint.

Query String Parameters

ParameterTypeRequiredDescription
onBehalfAccountIdintegerNoThe customer Veem account ID. Include only when a partner makes the request on behalf of their customer.

Response Payload (Completed)

When the statement is ready, the response includes the downloadUrl and its expiration:

{
    "statementRequestId": 4821,
    "resourceType": "VBA",
    "fundingMethodId": 55073,
    "year": 2026,
    "month": 4,
    "status": "COMPLETED",
    "downloadUrl": "https://veem-generated-docs.s3.amazonaws.com/statements/4821.pdf?X-Amz-Signature=...",
    "expiresAt": 1746057900000,
    "createdAt": 1746057600000,
    "updatedAt": 1746057650000,
    "generatedAt": 1746057650000
}

Response Payload (In Progress)

While the statement is still being generated, no download URL is returned:

{
    "statementRequestId": 4821,
    "resourceType": "VBA",
    "fundingMethodId": 55073,
    "year": 2026,
    "month": 4,
    "status": "IN_PROGRESS",
    "createdAt": 1746057600000,
    "updatedAt": 1746057600000
}

Response Payload (Empty)

When there are no transactions for the requested period, the request completes with status EMPTY and no PDF is produced:

{
    "statementRequestId": 4821,
    "resourceType": "VBA",
    "fundingMethodId": 55073,
    "year": 2026,
    "month": 4,
    "status": "EMPTY",
    "createdAt": 1746057600000,
    "updatedAt": 1746057650000,
    "generatedAt": 1746057650000
}

Response Payload (Failed)

When generation fails, the request carries status FAILED and a failureReason. Re-submitting the same request (same VBA + year/month) retries the generation:

{
    "statementRequestId": 4821,
    "resourceType": "VBA",
    "fundingMethodId": 55073,
    "year": 2026,
    "month": 4,
    "status": "FAILED",
    "failureReason": "Unable to generate statement document",
    "createdAt": 1746057600000,
    "updatedAt": 1746057650000
}
📘

Download URL expiration

The downloadUrl is a short-lived pre-signed URL (valid for approximately 5 minutes). Download the PDF before expiresAt. If the link has expired, simply call this endpoint again to obtain a fresh downloadUrl.

Statement Statuses

StatusDescription
IN_PROGRESSThe statement request has been accepted and the PDF is being generated. No download URL yet.
COMPLETEDThe statement PDF has been generated and is ready to download via downloadUrl.
EMPTYThe request completed successfully, but there were no transactions for the period, so no PDF was generated.
FAILEDStatement generation failed. See failureReason. Re-submit the request to retry.

Error Responses

HTTP StatusCodeDescription
400302Invalid payload. Returned when a mandatory field (fundingMethodId, year, month) is missing or out of range. The message field lists the offending fields.
40020009148INVALID_STATEMENT_PERIOD — the requested period is in the future, is the current month, or is before the Virtual Bank Account creation date (UTC). Statements are only available for fully elapsed months.
401Unauthorized. Full authentication is required to access this resource.
404Invalid bearer token.
40420009147STATEMENT_REQUEST_NOT_FOUND — no statement request matches the supplied statementRequestId for the account.
40420009149STATEMENT_RESOURCE_NOT_FOUND — the Virtual Bank Account referenced by fundingMethodId was not found for the account.
409Conflict. Returned when the X-Request-Id header value is reused.

Example validation error (400):

{
    "error": "Invalid payload",
    "message": "year: must not be null; month: must not be null",
    "code": 302
}

Example period error (400):

{
    "message": "Invalid statement period: year=2026, month=6. Period must not be in the future and must be after the resource creation date.",
    "code": 20009148
}

Example not-found error (404):

{
    "message": "Statement request 4821 not found for account 943802",
    "code": 20009147
}

Bank Statement Webhook

Instead of polling, you can subscribe to the BANK_STATEMENT_CREATED webhook to be notified automatically when a statement has finished generating (for both COMPLETED and EMPTY outcomes).

For creating a webhook to be notified when a bank statement event occurs, use the following endpoint.

POST /v1.2/webhooks
EventDescription
BANK_STATEMENT_CREATEDNotifies you when a bank statement has been generated for a Virtual Bank Account.

To subscribe to this webhook notification, use the following request:

{
    "callbackURL": "https://webhook-test.com/958892dcc2b3076fffd136adb127ac55",
    "event": "BANK_STATEMENT_CREATED"
}
{
    "id": 104,
    "event": "BANK_STATEMENT_CREATED",
    "callbackUrl": "https://webhook-test.com/958892dcc2b3076fffd136adb127ac55",
    "status": "Active"
}

Once subscribed, when a bank statement is generated you will get a notification in the following format. The event information is contained in the data field in a stringified JSON format.

{
  "type": "BANK_STATEMENT_CREATED",
  "data": "{\"statementRequestId\":4821,\"accountId\":943802,\"resourceType\":\"VBA\",\"resourceId\":\"55073\",\"periodYear\":2026,\"periodMonth\":4,\"period\":\"2026-04-01\",\"status\":\"COMPLETED\",\"documentId\":98231,\"createdAt\":\"2026-05-01T00:00:50Z\"}"
}

The data field, parsed, has the following shape:

{
    "statementRequestId": 4821,
    "accountId": 943802,
    "resourceType": "VBA",
    "resourceId": "55073",
    "periodYear": 2026,
    "periodMonth": 4,
    "period": "2026-04-01",
    "status": "COMPLETED",
    "documentId": 98231,
    "createdAt": "2026-05-01T00:00:50Z"
}
FieldDescription
statementRequestIdUnique identifier of the statement request. Use it with Get a Bank Statement to retrieve the download URL.
accountIdAccount ID that owns the statement.
resourceTypeThe resource the statement was generated for. Currently always VBA.
resourceIdThe Virtual Bank Account funding method ID, as a string.
periodYearThe statement year.
periodMonthThe statement month (112).
periodThe statement period as a date (first day of the month). Format: YYYY-MM-DD.
statusFinal status of the statement. Possible values: COMPLETED, EMPTY, FAILED.
documentIdIdentifier of the generated statement document. Present when a PDF was produced.
failureReasonDescription of the failure. Present only when status is FAILED.
createdAtTimestamp when the statement was generated (ISO 8601).
📘

Retrieving the statement from a webhook

The webhook payload does not include the downloadUrl. Use the statementRequestId from the payload to call Get a Bank Statement and obtain a fresh, short-lived downloadUrl.

In addition to this event, refer to the Webhook Notification page for general webhook setup, and the Virtual Bank Account page for other VBA-related events.