A comprehensive Node.js wrapper for the Vereinsflieger REST API with full TypeScript-style JSDoc documentation, modern ES6+ features, and complete CRUD operations.
Vereinsflieger is a popular system in Germany to help aviation clubs with their administration. The administration ranges from the legally required documentation duties, invoicing and accounting topics, managing flight training, to the annual statistics.
Although the system itself already maps all relevant topics in the web application, a reading and writing REST-based API is offered for many tables in the database. This API can be used to solve rare, individual needs.
Because there is a worldwide tendency to develop web applications based on Node.js, this wrapper API was created for Node.js. The code is made available here to the public.
β
48+ API Methods covering all major endpoints
β
Complete JSDoc Documentation with IntelliSense support
β
Input Validation for all critical parameters
β
Modern Error Handling with descriptive error messages
β
Native Fetch API (Node.js 18+, no external dependencies for HTTP)
β
Environment Variables support via dotenv
β
Zero Security Vulnerabilities
npm installCopy the template and add your credentials:
cp muster.env .envEdit .env file:
VEREINSFLIEGER_APPKEY=your_appkey_from_vereinsflieger
VEREINSFLIEGER_USERNAME=your.email@example.com
VEREINSFLIEGER_PASSWORD=your_passwordImportant: The .env file is already in .gitignore and will not be committed to git.
The API key (appkey) must be requested from Vereinsflieger support. Note the usage restrictions:
Der fΓΌr die Anmeldung erforderliche appkey kann ΓΌber den Support
angefragt werden. Die max. Anzahl an Requests (gemeint sind alle
Aufrufe) ist auf 1000 je Tag limitiert. Die kommerzielle Nutzung der
Schnittstelle ist grundsΓ€tzlich untersagt.
require('dotenv').config();
const { VereinsfliegerAPI } = require('./vereinsflieger_nodejs_api');
const vf = new VereinsfliegerAPI(process.env.VEREINSFLIEGER_APPKEY);
async function example() {
try {
// Sign in
await vf.signIn(process.env.VEREINSFLIEGER_USERNAME, process.env.VEREINSFLIEGER_PASSWORD);
// Get user info
const user = await vf.getUser();
console.log(`Logged in as: ${user.firstname} ${user.lastname}`);
// Get today's flights
const flights = await vf.getFlightListToday();
console.log('Today\'s flights:', flights);
// Sign out
await vf.signOut();
} catch (error) {
console.error('Error:', error.message);
}
}
example();The project includes comprehensive test suites for validating API functionality.
1. Complete API Test Suite (all documented endpoints):
npm run test:all
# or
node test-api-complete.jsTests all documented API endpoints (44 endpoints per API spec dated 17.08.2026). This test suite excludes non-documented endpoints marked with
2. Reservation Test Suite:
npm run test:reservation
# or
node test-reservation.jsFocused tests for reservation endpoints with detailed CRUD operation validation.
3. Legacy Test File:
npm test
# or
node test.jsFull API Test Suite:
node test-api-complete.jsReservation Tests (with selective execution):
# Run all reservation tests
node test-reservation.js
# Run specific tests
node test-reservation.js --test list add edit
# Available test names: list, add, get, edit, delete, errorsAdd the test aircraft callsign to your .env file:
TEST_AIRCRAFT_CALLSIGN=D-KXXX # Replace with a valid callsign from your clubβ
Automated Setup & Cleanup - Automatically logs in, creates test data, and cleans up
β
Comprehensive Coverage - Tests all CRUD operations for reservations
β
Error Handling Tests - Validates input validation and error cases
β
Detailed Reporting - Color-coded output with pass/fail statistics
β
Extensible Architecture - Easy to add tests for other API endpoints
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Vereinsflieger API - Reservierungs-Test-Suite β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
========== Test Setup ==========
[β] Setup: Authentifizierung erfolgreich
========== Test 1: Reservierungsliste ==========
[β] getReservationList: 5 Reservierungen gefunden
========== Test 2: Reservierung erstellen ==========
[β] addReservation: Reservierung erfolgreich erstellt
... (more tests) ...
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TEST REPORT β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Gesamt: 15
β Bestanden: 15
β Fehler: 0
β Γbersprungen: 0
Dauer: 3.45s
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Ergebnis: β ALLE TESTS BESTANDEN
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The test suite is designed to be easily extensible. To add tests for other endpoints:
- Create a new test class based on
ReservationTestSuite - Implement test methods for your endpoint
- Add to the
runAllTests()method
Example structure:
class FlightTestSuite extends ReservationTestSuite {
async testAddFlight() {
// Your test implementation
}
async runAllTests() {
await this.setup();
await this.testAddFlight();
// ... more tests
await this.teardown();
return this.generateReport();
}
}signIn(username, password)- Sign in usersignOut()- Sign out current usergetUser()- Get current user infosetAccessToken()- Get access token (called automatically)
addFlight(callsign, options)- Add new flight (with new fields: uidWinch, uidFi, flightTime, blockTime)editFlight(flightId, options)- Edit existing flightdeleteFlight(flightId)- Delete flightjoinTowFlights(flid, flidtow)- NEW Connect two flights to form F-SchleppgetFlight(flightId)- Get flight detailsgetFlightListToday()- Today's flightsgetFlightListDate(date)- Flights for specific dategetFlightListDaterange(from, to)- Flights in date rangegetLastFlightsPlane(callsign, count)- Last N flights of aircraftgetLastFlightsUser(count)- Last N flights of current usergetLastFlightsPilot(uid, count)- Last N flights of pilotgetLastModifiedFlights(days)- Recently modified flights
getMaintenanceData(callsign)- Get maintenance data
getPersonList()- List all users/members
getReservationList()- List active reservations
getCalendarPublic(hpaccessCode)- Get public calendar (no auth)getCalendarUser()- Get user's calendargetCalendarList(from, to)- Get appointments for date rangeaddCalendarAppointment(title, from, to, options)- Add appointmenteditCalendarAppointment(apoid, from, to, options)- Edit appointmentdeleteCalendarAppointment(apoid)- Delete appointment
accountAddTransaction(date, value, tax, debit, credit, ..., options)- Add transaction (with new fields: costtype, spid)editAccountTransaction(transactionId, options)- Edit transaction (with new fields: costtype, spid)getAccountTransaction(transactionId)- Get transaction detailsgetAccountTransactionsToday()- Today's transactionsgetAccountListYear(year)- Transactions for yeargetAccountTransactionsDaterange(from, to)- Transactions in range
workhoursAdd(uid, date, text, hours, category, options)- Add work hoursgetWorkhoursDaterange(from, to)- Work hours in rangegetWorkhoursCategories()- Get available categories
getArticles()- List all articlesaddSale(date, articleId, options)- Add sale transaction (with new fields: costtype, caid2, spid, paymentmode)getSaleListDaterange(from, to)- Sales in date rangegetSaleListModified(days)- Recently modified salesgetSaleListDate(date)- Sales for specific dategetSaleListToday()- Today's sales
getBackupZip()- Retrieve backup zip file
getVoucherList()- List all vouchersaddVoucher(voucherId, title, value, insertNewUser, lastname, options)- Add voucherchangeVoucherStatus(voucherId, status)- Change voucher status
require('dotenv').config();
const express = require('express');
const router = express.Router();
const { VereinsfliegerAPI } = require('../../vereinsflieger_api/vereinsflieger_nodejs_api');
const vf = new VereinsfliegerAPI(process.env.VEREINSFLIEGER_APPKEY);
async function vereinsfliegerLogin(req, res, next) {
try {
await vf.signIn(req.body.username, req.body.password);
return next();
} catch (error) {
return res.status(401).json({ error: error.message });
}
}
async function setUserdata(req, res, next) {
try {
req.session.userdata = await vf.getUser();
return next();
} catch (error) {
return res.status(500).json({ error: error.message });
}
}
function render(req, res) {
res.render('resulting_displayfile', {
title: 'Vereinsflieger-Benutzerdaten darstellen',
userdata: req.session.userdata
});
}
router.post('/login', vereinsfliegerLogin, setUserdata, render);
module.exports = router;Data returned from the API are often nested JavaScript objects. Here's how to convert them to arrays:
require('dotenv').config();
const express = require('express');
const { VereinsfliegerAPI } = require('../../vereinsflieger_api/vereinsflieger_nodejs_api');
const router = express.Router();
const vf = new VereinsfliegerAPI(process.env.VEREINSFLIEGER_APPKEY);
async function fillCashTransactions(req, res, next) {
try {
const transactions_json = await vf.getAccountListYear(new Date().getFullYear());
// Convert nested object to array
const transaction_array = Object.values(transactions_json);
// Filter transactions
const filteredTransactions = transaction_array.filter(el => el.creditaccount == 100000);
req.filteredTransactions = filteredTransactions;
return next();
} catch (error) {
return res.status(500).json({ error: error.message });
}
}
router.get('/transactions', fillCashTransactions, (req, res) => {
res.json(req.filteredTransactions);
});
module.exports = router;All methods throw descriptive errors that can be caught:
try {
await vf.addFlight('D-ECQH', {
pilotName: 'John Doe',
departureTime: '2024-01-01 10:00',
arrivalTime: '2024-01-01 12:00'
});
} catch (error) {
if (error.message.includes('Not signed in')) {
console.error('Please sign in first');
} else if (error.message.includes('Callsign is required')) {
console.error('Missing required parameter');
} else {
console.error('API Error:', error);
}
}All methods have complete JSDoc documentation. Your IDE will show:
- Parameter types and descriptions
- Return types
- Required vs optional parameters
- Error conditions
Simply start typing vf. and see all available methods with descriptions!
- Node.js 18+ (for native fetch API support)
- Valid Vereinsflieger API key
dotenv- Environment variable managementcrypto- MD5 hashing for passwords (built-in)- Native
fetchAPI (Node.js 18+)
You can use the code, but I do not guarantee the results and take no responsibility for the code. You have to get an individual App-Key from vereinsflieger.de. In this context you have to comply with the terms of use of vereinsflieger.de.
MIT License - See file header for details
Contributions are welcome! Please ensure:
- All new methods have JSDoc documentation
- Input validation for required parameters
- Proper error handling
- Test your changes
- π CRITICAL BUG FIX: GET requests now correctly append parameters as query string
- Fixed
getCalendarList()- was returning HTTP 401 Unauthorized - Fixed
getCalendarUser()- accesstoken was not sent - Fixed
getBackupZip()- accesstoken was not sent
- Fixed
- β
NEW: Comprehensive test suite
test-api-complete.jsfor all documented endpoints - β
NEW: API coverage documentation
API-COVERAGE.md- complete mapping of API endpoints to Node.js methods - π§ͺ Test Coverage: 25 of 44 endpoints (57%) now covered by automated tests
- π¦ npm script:
npm run test:allfor complete API test suite - ποΈ REMOVED: 12 non-documented methods for cleaner API surface (getAircraftList, getAircraft, getUserDetails, reservation CRUD, deleteAccountTransaction, workhour edit/delete/get, getFlightStatistics)
- π Bug Fix: Fixed URL typo in
getReservationList(actice β active) - β
NEW Calendar CRUD operations (4 new methods):
getCalendarList()- Get appointments for date rangeaddCalendarAppointment()- Add new appointmenteditCalendarAppointment()- Edit existing appointmentdeleteCalendarAppointment()- Delete appointment
- β
NEW F-Schlepp connection:
joinTowFlights()- Connect glider and tow flights - β
NEW Sales list endpoints (4 new methods):
getSaleListDaterange()- Sales in date rangegetSaleListModified()- Recently modified salesgetSaleListDate()- Sales for specific dategetSaleListToday()- Today's sales
- β
NEW Backup endpoint:
getBackupZip()- Download backup file - β
NEW Voucher management (3 new methods):
getVoucherList()- List all vouchersaddVoucher()- Create new voucherchangeVoucherStatus()- Update voucher status
- β
Enhanced Flight methods with new fields:
uidWinch- Winch operator user IDuidFi- Flight instructor user ID (for flight assignments)flightTime- Manual flight time overrideblockTime- Manual block time override
- β
Enhanced Sale method with new fields:
costtype- Cost type / fee areacaid2- Credit account IDspid- Sphere IDpaymentmode- Payment mode for cashbook
- β
Enhanced Accounting methods with new fields:
costtype- Cost type / fee areaspid- Sphere ID
- π Updated to match API specification dated 17.08.2026
- π Critical Fix: Rekursive Endlosschleife in
_validateAccessToken()behoben - π Total: 44 documented API endpoints fully implemented
- β Added 23 new API endpoints (48+ total methods)
- β Complete JSDoc documentation
- β Modern error handling with descriptive messages
- β Input validation for all methods
- β Migrated to native fetch API (no node-fetch dependency)
- β Environment variable support with dotenv
- β Fixed all security vulnerabilities
- β Improved code quality and consistency
- Initial release with basic API coverage