Bank Statement Conversion API
Add bank statement conversion to your own software with a focused upload, status, and download workflow.
Overview
The Bank Statement Conversion API is for developers who want to add conversion to their own app. It documents the public conversion workflow: optionally check account capacity, upload files, poll the job status, then download completed outputs with the returned token.
This reference is intentionally limited to the public conversion workflow.
https://bank-statement-conversion.com/apiQuickstart
Create an API token
Generate a token in your dashboard and send it as Authorization: Bearer YOUR_API_TOKEN.
Upload a file
POST to /api/upload with statement[], format, and optional conversion settings.
Poll job status
Use the returned jobId with /api/conversion-status/{jobId} until a preview includes download_token.
Download output
GET /api/download/{downloadToken} and save the binary response as the converted file.
Authentication
API Token Authentication
All API requests must include an API token for authentication. Tokens can be generated in your account dashboard under the API Tokens section.
How to Generate an API Token
- Log in to your account
- Navigate to the API Tokens section in your dashboard
- Click "Create New Token" and provide a name for your token
- Copy and securely store the generated token. It will only be shown once.
Using Your API Token
Include your API token in the Authorization header of your requests:
Authorization: Bearer YOUR_API_TOKENAI Agents
Use the API with AI agents
AI tools can integrate with the same public conversion workflow as developers. Use the OpenAPI schema, LLM discovery files, or MCP endpoint so agents know which conversion endpoints to call and which actions need confirmation.
Agent discovery
/api/openapi.json/llms.txt/llms-full.txt/mcp/bank-statement-conversion- Use
/api/openapi.jsonfor schema-aware tools such as ChatGPT Actions or custom agent builders. - Use
/llms.txtand/llms-full.txtto give agents canonical product and API context. - Use
/mcp/bank-statement-conversionfor MCP-compatible agent clients that support remote MCP servers.
One-time token setup
- Log in once and create an API token in the dashboard.
- Keep all conversion abilities enabled unless you want a restricted token.
- Set the token as BSC_API_TOKEN in the MCP client environment.
- Revoke the token from the dashboard whenever agent access should stop.
Connect Codex, Claude, Cursor, and other AI clients
All MCP-compatible AI clients use the same remote endpoint and bearer token. Keep the token in an environment variable, not inside prompts or source code.
https://bank-statement-conversion.com/mcp/bank-statement-conversionAuthorization: Bearer YOUR_API_TOKENCodex setup
Add this server entry to your Codex config.
[mcp_servers.bank_statement_conversion]
url = "https://bank-statement-conversion.com/mcp/bank-statement-conversion"
bearer_token_env_var = "BSC_API_TOKEN"Set the token in your shell or system environment, then restart the AI client.
export BSC_API_TOKEN="YOUR_API_TOKEN_HERE"Other AI clients
- Claude, Cursor, and other MCP clients should use the same endpoint URL and Authorization bearer token.
- ChatGPT Actions and custom agent builders should use /api/openapi.json instead of MCP when they need an OpenAPI schema.
- Use /llms.txt and /llms-full.txt as product context for agents that support knowledge files.
Scoped token abilities
Workflow Endpoints
These are the only endpoints needed to add document conversion to your application.
| Endpoint | Method | Description |
|---|---|---|
/api/user-status | GET | Optional preflight check for credits, page allowance, and subscription plan |
/api/upload | POST | Upload bank statements for conversion |
/api/conversion-status/{jobId} | GET | Check the status of a conversion job |
/api/download/{downloadToken} | GET | Download a completed conversion using a token returned in the status response |
Account Status Endpoint
GET /api/user-status
Use this optional endpoint before uploading when your app needs to confirm whether the API token has available credits, page allowance, or paid-plan access.
Useful Response Fields
| Field | Type | Description |
|---|---|---|
remaining_credits | integer | Credits available for credit-based conversions. |
remaining_daily_pages | integer | Daily page allowance remaining for the authenticated user. |
remaining_premium_pages | integer | Monthly premium page allowance remaining for the effective plan. |
plan_type | string | The effective subscription plan for the API token. |
Example Response
{
"success": true,
"remaining_credits": 42,
"remaining_daily_pages": 100,
"remaining_premium_pages": 950,
"plan_type": "premium"
}Upload Endpoint
POST /api/upload
This endpoint allows you to upload bank statements for conversion. The conversion process is asynchronous, and you'll receive a job ID to check the status later.
Supported Input Formats
| Use Case | Formats | Extensions | Notes |
|---|---|---|---|
| Standard conversions | PDF, JPG/JPEG, PNG, TIFF/TIF, CSV, XLS/XLSX, OFX, QBO, QFX, 940, STA, MT940, MT940X, XML, CAMT.053 | .pdf, .jpg, .jpeg, .png, .tiff, .tif, .csv, .xls, .xlsx, .ofx, .qbo, .qfx, .940, .sta, .mt940, .mt940x, .xml, .camt053 | Use for bank statement, invoice, and receipt conversions. |
| CSV Cleaner | CSV, XLS, XLSX | .csv, .xls, .xlsx | Use only when format is csv_clean. |
| Payment file generation | CSV, XLS, XLSX | .csv, .xls, .xlsx | Use for CSV or Excel payment rows that generate bank-ready ACH/NACHA, CPA005, SEPA XML, BACS, ABA, or NZ payment files. |
Supported Output Formats
document_type | Document | Allowed format values |
|---|---|---|
bank_statement | Bank statement | csvexceljsonqb_onlineqb_desktopxeroofxofx_legacyqfxmt940mt940_moneybirdcamt053camt053_legacycamt053_moneybirdcamt053_netsuitecamt053_sap_v2camt053_sap_v8camt053_business_centralcamt053_datevcamt053_afascamt053_twinfieldtally_xmlbai2bai2_netsuitebai2_sapbai2_bank_xsagesage_cloudsage_intacctmyobdatevdatev_accountingcsv_clean |
invoice | Invoice | csvexceljsonqb_onlineqb_desktopubl_xmlubl_peppolxrechnung_ublzugferd_pdffactur_x_pdf |
receipt | Receipt | csvexceljson |
payment_file | Bank payment file | payment_nachapayment_cpa005payment_sepa_pain001payment_bacspayment_abapayment_nz |
Use document_type=payment_file with payment_nacha, payment_cpa005, payment_sepa_pain001, payment_bacs, payment_aba, or payment_nz. Upload CSV, XLS, or XLSX as statement[]; generation uses the existing credits, history, and download-token workflow.
Open payment file generatorUse document_type=positive_pay_file with format=positive_pay. Upload CSV, XLS, or XLSX check-register rows as statement[] and pass positive_pay_settings for Chase, TD, generic CSV, or fixed-width profiles.
Open Positive Pay file generatorRequest Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | Yes | Output format. Use one of the allowed format values listed above for the selected document_type. |
document_type | string | No | Document category: bank_statement, invoice, receipt, payment_file, or positive_pay_file. Defaults to bank_statement. |
statement | file array | Yes | Files to convert. Send one or more files as statement[]. |
conversion_mode | string | No | Conversion mode: precision or fast. Defaults to precision. |
separate_debit_credit | boolean | No | Whether to separate debit and credit columns. Default: false. |
combine_files | boolean | No | Whether to combine multiple files into a single output. Default: false. |
Example Response
{
"stage": "pending",
"jobId": "5f3a7d8c-8a91-4a2e-9d3b-4c84f0636c12"
}Status Endpoint
GET /api/conversion-status/{jobId}
This endpoint allows you to check the status of a conversion job. You should poll this endpoint until the job is completed.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId | string | The job ID returned from the upload endpoint |
Example Pending Response
{
"stage": "processing",
"success": false,
"previews": []
}Example Completed Response
{
"success": true,
"previews": [
{
"file_name": "bank_statement.pdf",
"format": "CSV",
"download_token": "Y8Jm7qVf9sR2kP6nL4xA0bT3cD5eF1gH",
"partial_conversion": false,
"credits_used": 1
}
],
"failed_files": [],
"remaining_credits": 41,
"remaining_premium_pages": 949,
"remaining_daily_pages": 99
}Example Failed Response
{
"stage": "complete",
"success": false,
"error": "An error occurred during the conversion process.",
"message": "The uploaded file could not be processed.",
"previews": []
}Download Endpoint
GET /api/download/{downloadToken}
Use the download_token returned inside a completed status response. Do not construct download tokens yourself.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
downloadToken | string | The download_token returned for a converted file in the status response. |
Example Request
curl -L \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-o converted_statement.csv \
"https://bank-statement-conversion.com/api/download/Y8Jm7qVf9sR2kP6nL4xA0bT3cD5eF1gH"Example Response
200 OKExample Response Headers
HTTP/1.1 200 OK
Content-Type: text/csv
Content-Disposition: attachment; filename="bank-statement.csv"
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
}Error Handling
The API uses standard HTTP status codes to indicate the success or failure of requests.
| Status Code | Description |
|---|---|
| 200 OK | The request was successful |
| 400 Bad Request | The request was invalid or missing required parameters |
| 401 Unauthorized | Authentication failed or token is invalid |
| 403 Forbidden | The authenticated user doesn't have permission to access the resource |
| 422 Unprocessable Entity | Validation errors occurred |
| 500 Internal Server Error | An error occurred on the server |
Example Error Responses
{
"message": "Unauthenticated."
}{
"message": "The given data was invalid.",
"errors": {
"statement": [
"The statement field is required."
],
"format": [
"The selected format is invalid."
]
}
}{
"success": false,
"error": "Insufficient credits or page allowance for this conversion."
}Rate Limits
To ensure fair usage of the API, rate limits are applied based on your subscription plan:
- Premium users: 100 requests per minute
- Maximum file size: 100MB per file
- Maximum files per request: 5 files
Code Examples
End-to-end samples for the conversion workflow: upload, poll, then download.
npm install axios form-dataPython: pip install requestsPHP: PHP cURL extension enabledcURL: curl and jq installedGo: Go 1.20+Ruby: gem install multipart-postC#: .NET 7+npm install axios form-data1// Upload a bank statement file
2const axios = require('axios');
3const FormData = require('form-data');
4const fs = require('fs');
5
6// Your API token from the dashboard
7const API_TOKEN = 'your_api_token_here';
8
9// Create a form data object
10const formData = new FormData();
11formData.append('document_type', 'bank_statement');
12formData.append('format', 'csv');
13formData.append('statement[]', fs.createReadStream('bank_statement.pdf'));
14formData.append('separate_debit_credit', 'true');
15formData.append('combine_files', 'false');
16
17// Make the API request
18const BASE_URL = 'https://bank-statement-conversion.com/api';
19
20axios.post(`${BASE_URL}/upload`, formData, {
21 headers: {
22 'Authorization': `Bearer ${API_TOKEN}`,
23 ...formData.getHeaders()
24 }
25})
26.then(response => {
27 const jobId = response.data.jobId;
28 console.log(`Conversion job started with ID: ${jobId}`);
29
30 // Poll for job status
31 checkJobStatus(jobId);
32})
33.catch(error => {
34 console.error('Error uploading file:', error.response ? error.response.data : error.message);
35});
36
37// Function to check job status
38function checkJobStatus(jobId) {
39 axios.get(`${BASE_URL}/conversion-status/${jobId}`, {
40 headers: {
41 'Authorization': `Bearer ${API_TOKEN}`
42 }
43 })
44 .then(response => {
45 const data = response.data;
46 console.log('Job stage:', data.stage);
47
48 if (data.success && data.previews && data.previews.length > 0) {
49 const downloadToken = data.previews[0].download_token;
50 downloadFile(`${BASE_URL}/download/${downloadToken}`);
51 } else if (data.stage === 'pending' || data.stage === 'processing') {
52 // Check again after 5 seconds
53 setTimeout(() => checkJobStatus(jobId), 5000);
54 } else {
55 console.error('Conversion failed:', data.error || data.message || data);
56 }
57 })
58 .catch(error => {
59 console.error('Error checking job status:', error.response ? error.response.data : error.message);
60 });
61}
62
63// Function to download the converted file
64function downloadFile(url) {
65 const outputPath = 'converted_statement.csv';
66
67 axios({
68 method: 'get',
69 url: url,
70 responseType: 'stream',
71 headers: {
72 'Authorization': `Bearer ${API_TOKEN}`
73 }
74 })
75 .then(response => {
76 response.data.pipe(fs.createWriteStream(outputPath));
77 console.log(`File downloaded to ${outputPath}`);
78 })
79 .catch(error => {
80 console.error('Error downloading file:', error.message);
81 });
82}