REST API v1

FinSheet AI API

Upload a bank statement PDF and get back clean, structured transaction data — in JSON, CSV, or Excel. Supports 50+ banks worldwide.

Base URL https://www.finsheetai.com/api/v1
50+
Supported banks
JSON / CSV / Excel
Output formats
Bearer Token
Auth method
< 30 s
Typical response
All requests must be made over HTTPS. Plain-HTTP requests are rejected.
Security

Authentication

Two auth methods are used depending on the operation you're performing.

API Key — Conversions & Usage

Use your fsk_live_… key for /convert and /usage. Pass it as the X-API-Key header or as Authorization: Bearer <key>.

JWT — Key Management

Use your dashboard JWT for creating, listing and revoking API keys. Pass it as Authorization: Bearer <jwt>.

POST /api/v1/convert Quick-start example
curl -X POST https://www.finsheetai.com/api/v1/convert \
  -H "X-API-Key: fsk_live_your_key_here" \
  -H "Accept: application/json" \
  -F "[email protected]" \
  -F "format=json"
import requests

res = requests.post(
    "https://www.finsheetai.com/api/v1/convert",
    headers={"X-API-Key": "fsk_live_your_key_here"},
    files={"file": open("statement.pdf", "rb")},
    data={"format": "json"}
)
transactions = res.json()["transactions"]
const FormData = require('form-data');
const fs = require('fs'), axios = require('axios');

const form = new FormData();
form.append('file', fs.createReadStream('statement.pdf'));
form.append('format', 'json');

const { data } = await axios.post(
  'https://www.finsheetai.com/api/v1/convert', form,
  { headers: { 'X-API-Key': 'fsk_live_your_key_here', ...form.getHeaders() } }
);
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => 'https://www.finsheetai.com/api/v1/convert',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['X-API-Key: fsk_live_your_key_here'],
    CURLOPT_POSTFIELDS     => [
        'file'   => new CURLFile('statement.pdf'),
        'format' => 'json',
    ],
]);
$resp = json_decode(curl_exec($curl), true);
Rate Limits

Plans & Limits

Counters reset on the 1st of each month. Exceeding your quota returns HTTP 429.

Free
30
calls / month
Max file: 5 MB JSON & CSV output
Pro ★
1,000
calls / month
Max file: 50 MB JSON, CSV & Excel
Enterprise
Unlimited
 
Max file: 100 MB JSON, CSV & Excel
Once your monthly limit is reached, all conversion requests return 429 Too Many Requests until the counter resets.
Endpoints

Convert PDF

The core endpoint. Upload a bank statement PDF and receive structured transaction data.

POST /api/v1/convert Convert a bank statement
Accepts multipart/form-data. Auth via X-API-Key or Authorization: Bearer <api_key>.
Request Body — multipart/form-data
file*
file (PDF)
Bank statement PDF. Max size is plan-dependent (5–100 MB).
format
string
Output format: json (default), csv, or excel.
bank_id
string
Optional bank hint (e.g. chase, wells_fargo). Auto-detected if omitted.
curl -X POST https://www.finsheetai.com/api/v1/convert \
  -H "X-API-Key: fsk_live_your_key_here" \
  -F "file=@chase_jan.pdf" \
  -F "format=json"
res = requests.post(
    "https://www.finsheetai.com/api/v1/convert",
    headers={"X-API-Key": "fsk_live_your_key_here"},
    files={"file": ("statement.pdf", open("statement.pdf","rb"), "application/pdf")},
    data={"format": "json"}
)
const form = new FormData();
form.append('file', fs.createReadStream('statement.pdf'), 'statement.pdf');
form.append('format', 'json');
const res = await fetch('https://www.finsheetai.com/api/v1/convert',
  { method:'POST', headers:{'X-API-Key':'fsk_live_your_key_here'}, body:form });
curl_setopt_array($curl, [
    CURLOPT_URL        => 'https://www.finsheetai.com/api/v1/convert',
    CURLOPT_POST       => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: fsk_live_your_key_here'],
    CURLOPT_POSTFIELDS => [
        'file'   => new CURLFile('statement.pdf','application/pdf'),
        'format' => 'json'
    ],
]);
200 JSON response
{
  "success": true,
  "request_id": "a1b2c3d4",
  "bank_name": "Chase Bank",
  "account_holder": "John Doe",
  "statement_period": { "from": "2024-01-01", "to": "2024-01-31" },
  "currency": "USD",
  "balances": { "opening": 5000.00, "closing": 4823.47 },
  "summary": { "total_transactions": 42, "total_credits": 3500.00, "total_debits": 3676.53 },
  "transactions": [
    {
      "date": "2024-01-03",
      "description": "Amazon Prime",
      "debit_amount": 14.99,
      "credit_amount": null,
      "balance": 4985.01
    }
  ],
  "processing_time_ms": 4230,
  "api_usage": { "calls_this_month": 5, "monthly_limit": 1000 }
}
API Key Management

Manage API Keys

Create and manage API keys programmatically. All key management endpoints require your JWT token from the dashboard.

Get your JWT from your dashboard. It's the same token used when you log in.
GET /api/v1/keys List all API keys
Returns all keys (active and revoked) linked to your account. Auth: Authorization: Bearer <jwt>.
curl https://www.finsheetai.com/api/v1/keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
res = requests.get(
    "https://www.finsheetai.com/api/v1/keys",
    headers={"Authorization": "Bearer YOUR_JWT_TOKEN"}
)
keys = res.json()["keys"]
200 Response
{ "keys": [{ "id": 1, "name": "My Integration", "key_prefix": "fsk_live_SP5x",
    "plan": "pro", "monthly_limit": 1000, "calls_this_month": 47,
    "calls_total": 312, "is_active": true, "created_at": "2024-01-15T10:30:00" }],
  "total": 1, "active": 1 }
POST /api/v1/keys Create a new API key
The full key is shown only once — save it securely. The plan is auto-set from your subscription. Auth: JWT.
Request Body — application/json
name*
string
Label for the key. 1–100 characters.
curl -X POST https://www.finsheetai.com/api/v1/keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Production Key"}'
res = requests.post(
    "https://www.finsheetai.com/api/v1/keys",
    headers={"Authorization": "Bearer YOUR_JWT_TOKEN"},
    json={"name": "Production Key"}
)
# Save api_key — won't be shown again!
api_key = res.json()["api_key"]
201 Created
{ "success": true, "api_key": "fsk_live_AbCdEfGhIjKlMn...",
  "id": 2, "name": "Production Key", "plan": "pro",
  "monthly_limit": 1000, "created_at": "2024-02-01T09:00:00" }
DELETE /api/v1/keys/{key_id} Revoke an API key
Permanently revokes a key. Revoked keys cannot be reactivated. Auth: JWT.
Path Parameters
key_id*
integer
ID from the list endpoint.
curl -X DELETE https://www.finsheetai.com/api/v1/keys/2 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
PATCH /api/v1/keys/{key_id} Rename an API key
Updates the display name of an API key. Auth: JWT.
Path Parameters
key_id*
integer
ID of the key to rename.
Request Body — application/json
name*
string
New display name. 1–100 characters.
curl -X PATCH https://www.finsheetai.com/api/v1/keys/2 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Staging Key"}'
Monitoring
GET /api/v1/usage Monthly usage for the current API key
Returns monthly and lifetime usage counters. Auth: X-API-Key.
curl https://www.finsheetai.com/api/v1/usage \
  -H "X-API-Key: fsk_live_your_key_here"
200 Response
{ "key_prefix": "fsk_live_SP5x", "plan": "pro",
  "monthly_limit": 1000, "calls_this_month": 47,
  "remaining_this_month": 953, "calls_total": 312,
  "last_used_at": "2024-02-01T08:45:00", "resets_at": "2024-03-01" }
GET /api/v1/health Public health check — no auth required
Returns API status. No authentication needed. Useful for uptime monitoring.
curl https://www.finsheetai.com/api/v1/health
200 Response
{ "status": "ok", "version": "1.0" }
Reference

Error Codes

All errors return a JSON body with an error field and a human-readable message.

{
  "error": "rate_limit_exceeded",
  "message": "Monthly limit of 1000 calls reached. Resets on the 1st of next month.",
  "calls_this_month": 1000,
  "monthly_limit": 1000
}
HTTPError CodeDescription
400invalid_formatUnsupported output format. Use json, csv, or excel.
400file_too_largeFile exceeds the plan's max size limit.
400key_limit_reachedMaximum of 10 active API keys already reached.
401missing_api_keyNo API key or JWT provided.
401invalid_api_keyAPI key does not exist.
401invalid_tokenJWT is missing, expired, or invalid.
403revoked_api_keyKey has been revoked and can no longer be used.
404not_foundRequested resource not found.
415invalid_file_typeUploaded file is not a valid PDF.
422validation_errorRequest body failed schema validation.
429rate_limit_exceededMonthly call limit reached. Resets on the 1st of next month.
500conversion_failedAI extraction failed. Retry or contact support.
Need help? Email [email protected] or visit our Help Center.