POST /v1/imports

Import a Ledger CSV v1 file for one account. Format in docs/import-format.md.

The whole file is validated before anything is written; any invalid row rejects the file. Duplicates (same account, date and amount) are skipped. Send the file as the request body with Content-Type text/csv, up to 1 MB.

Auth. Send the token in the X-Ledger-Token header.

Parameters

NameInTypeRequiredDescription
account_idquerystringrequired
dry_runquerybooleanoptionalWhen true, classify and count without writing
filenamequerystringoptional
Idempotency-KeyheaderstringoptionalSend a unique key per logical import. A retry with the same key returns the first response. Keys are kept for a day.

Request body

text/csv: string

Responses

StatusMeaningBody
201ImportedImportResult
200Dry run; nothing was writtenImportResult
400The file was rejected. Nothing was imported. Every bad row is listed.object
415Request rejectedError
429Too many requests from this client address. Wait the number of seconds in Retry-After, then try again.Error

Example response

{
  "dry_run": true,
  "import_id": 0,
  "rows_total": 0,
  "rows_new": 0,
  "rows_duplicate": 0,
  "uncategorized": 0,
  "categorized_by_you": 0,
  "categorized_by_rule": 0
}

Code samples

Set KEY to your own token first.

curl

curl \
  -X POST \
  -H X-Ledger-Token:$KEY \
  -H "Content-Type: text/csv" --data-binary @file \
  "https://api.sasek.org/ledger/v1/imports?account_id=string"

JavaScript

const res = await fetch("https://api.sasek.org/ledger/v1/imports?account_id=string", {
  method: "POST",
  headers: { "X-Ledger-Token": KEY },
});
const data = await res.json();

Python

import json
import os
import urllib.request

request = urllib.request.Request(
    "https://api.sasek.org/ledger/v1/imports?account_id=string",
    method="POST",
    headers={
        "X-Ledger-Token": os.environ["KEY"],
        "Content-Type": "text/csv",
    },
    data=open("file.csv", "rb").read(),
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))