Skip to main content
Version: 0.0.2

API Overview

DockWallet provides a REST API that exposes all backend functionality programmatically — from authentication to pass management.

Base URL: https://<your-server>:8080/api
Version: 0.0.2
Auth: Bearer Token (JWT), valid for 7 days


Authentication

All protected endpoints require a JWT token in the Authorization header:

Authorization: Bearer <token>

The token is returned upon successful login.


Health & Version

GET /api/health

Returns the current backend status.

Response

{
"status": "ok",
"version": "0.0.2"
}

GET /api/version

Detailed version information.

Response

{
"version": "0.0.2",
"name": "dockwallet-backend",
"nodeVersion": "v20.x.x",
"uptime": 3600
}

GET /api/dockerhub/latest

Returns the latest published versions of backend and frontend on Docker Hub. Used for update checks in the admin interface.

Response

{
"backend": "0.0.2",
"frontend": "0.0.2"
}

Auth – /api/auth

GET /api/auth/config

Returns whether public registration is enabled.

Response

{
"registrationEnabled": true
}

POST /api/auth/register

Registers a new user. Requires USER_REGISTRATION=true in the configuration. A verification email is sent after registration.

Request Body

{
"username": "string",
"email": "string",
"password": "string (min. 8 characters)"
}

Response 201

{
"message": "Registration successful. Please confirm your email."
}

Errors

StatusDescription
400Required fields missing or password too short
403Registration is disabled
409Email or username already taken

GET /api/auth/verify-email?token=<token>

Confirms the email address using the token sent by mail. The account is activated upon success.

Query Parameter

  • token – Verification token from the email

Response 200

{
"message": "Email confirmed. You can now log in."
}

POST /api/auth/login

Logs in a user. Accepts either username or email in the username field. If MFA is enabled, the MFA code must be included in a second step.

Request Body

{
"username": "string (username or email)",
"password": "string",
"mfaToken": "string (optional, 6 digits)"
}

Response 200 – Without MFA or after successful MFA

{
"token": "eyJ...",
"user": {
"id": 1,
"email": "user@example.com",
"username": "alice",
"is_admin": false
}
}

Response 200 – MFA required (no token provided)

{
"mfaRequired": true
}

Errors

StatusDescription
400Required fields missing
401Invalid credentials or MFA code
403Account not active

GET /api/auth/me

Returns the profile of the currently logged-in user.

Response

{
"id": 1,
"username": "alice",
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com",
"is_admin": false,
"is_active": true,
"mfa_enabled": false,
"created_at": "2024-01-01T00:00:00.000Z"
}

PUT /api/auth/profile

Updates the current user's profile.

Request Body

{
"username": "string",
"email": "string",
"first_name": "string (optional)",
"last_name": "string (optional)"
}

Response – Updated user profile

Errors

StatusDescription
400Required fields missing
409Email or username already taken

POST /api/auth/forgot-password

Initiates the password reset flow. Sends an email with a reset link (token valid for 15 minutes). The response is intentionally generic to prevent user enumeration.

Request Body

{
"email": "string"
}

Response

{
"message": "If the email exists, a message has been sent."
}

POST /api/auth/reset-password

Resets the password using a valid reset token.

Request Body

{
"token": "string",
"password": "string (min. 8 characters)"
}

Response

{
"message": "Password changed successfully."
}

MFA (TOTP) – /api/auth/mfa

POST /api/auth/mfa/setup

Generates a new TOTP secret and returns a QR code that can be scanned with an authenticator app (e.g. Google Authenticator).

Response

{
"secret": "JBSWY3DPEHPK3PXP",
"qrCode": "data:image/png;base64,..."
}

POST /api/auth/mfa/enable

Enables MFA for the account. Must be called with a valid TOTP code after setup.

Request Body

{
"token": "string (6-digit TOTP code)"
}

Response

{
"message": "MFA enabled"
}

POST /api/auth/mfa/disable

Disables MFA and deletes the stored secret. Requires one final confirmation via TOTP code.

Request Body

{
"token": "string (6-digit TOTP code)"
}

Response

{
"message": "MFA disabled"
}

GET /api/auth/mfa/smtp-status

Returns whether the SMTP server is configured (required for MFA via email).

Response

{
"smtpConfigured": true
}

POST /api/auth/mfa/send-code

Sends the current TOTP code via email. Only available if SMTP is configured.

Response

{
"message": "Code sent"
}

Passkeys (WebAuthn) – /api/auth/passkey

Passkeys enable passwordless login using biometric methods or hardware keys.

POST /api/auth/passkey/register/options

Starts the passkey registration. Returns WebAuthn options for the browser.

Response – WebAuthn PublicKeyCredentialCreationOptions


POST /api/auth/passkey/register/verify

Verifies and saves the newly registered passkey.

Request Body

{
"credential": { "...": "WebAuthn AuthenticatorAttestationResponse" },
"deviceName": "string (optional, e.g. 'MacBook Pro')"
}

Response

{
"message": "Passkey registered"
}

POST /api/auth/passkey/login/options

Returns WebAuthn authentication options. No token required.

Response – WebAuthn PublicKeyCredentialRequestOptions


POST /api/auth/passkey/login/verify

Verifies the WebAuthn response and returns a JWT token on success.

Request Body

{
"credential": { "...": "WebAuthn AuthenticatorAssertionResponse" }
}

Response

{
"token": "eyJ...",
"user": {
"id": 1,
"username": "alice",
"email": "alice@example.com",
"is_admin": false
}
}

GET /api/auth/passkeys

Lists all registered passkeys for the logged-in user.

Response

[
{
"id": 1,
"device_name": "MacBook Pro",
"created_at": "2024-01-01T00:00:00.000Z"
}
]

DELETE /api/auth/passkeys/:id

Deletes a passkey by its ID.

Response

{
"message": "Passkey deleted"
}

Delete Account – /api/auth/delete-account

POST /api/auth/delete-account/request

Sends a confirmation email to delete the account. Admin accounts cannot be deleted.

Response

{
"message": "Confirmation email has been sent."
}

GET /api/auth/delete-account/confirm?token=<token>

Permanently deletes the account. All associated passes are also deleted.

Query Parameter

  • token – Token from the confirmation email

Response

{
"message": "Account deleted."
}

Passes – /api/passes

All endpoints require authentication. Users can only access their own passes.

GET /api/passes

Returns all passes belonging to the logged-in user.

Response

[
{
"id": 1,
"user_id": 1,
"type": "boardingPass",
"description": "LH 123 · FRA → JFK",
"airline": "Lufthansa",
"flight_number": "LH123",
"origin": "FRA",
"destination": "JFK",
"barcode_value": "M1MUSTERMANN/MAX ABCDEF FRAJFKLH 0123 123Y00B00000 100",
"barcode_format": "PKBarcodeFormatAztec",
"background_color": "#003366",
"label_color": "#ffffff",
"foreground_color": "#ffffff",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-01T00:00:00.000Z"
}
]

POST /api/passes

Creates a pass manually (without a file).

Request Body – Pass fields directly as JSON

Response 201 – The created pass


POST /api/passes/upload

Imports a pass from a .pkpass file (as a Base64-encoded string). The file is unpacked and parsed server-side.

Request Body

{
"file": "string (Base64-encoded content of the .pkpass file)"
}

Response 201 – The imported pass

Errors

StatusDescription
400No file provided or parsing error

POST /api/passes/import-url

Downloads a .pkpass file from a URL and imports it. Useful for reading QR code links.

Request Body

{
"url": "https://example.com/ticket.pkpass"
}

Response 201 – The imported pass

Errors

StatusDescription
400No URL, invalid URL, or download failed

DELETE /api/passes/:id

Deletes a pass belonging to the logged-in user.

Response

{
"success": true
}

Errors

StatusDescription
404Pass not found or belongs to another user

Admin – /api/admin

All admin endpoints require a valid JWT token and is_admin: true.

GET /api/admin/users

Lists all registered users with statistics.

Response

[
{
"id": 1,
"username": "alice",
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com",
"is_admin": true,
"is_active": true,
"mfa_enabled": false,
"created_at": "2024-01-01T00:00:00.000Z",
"pass_count": 5,
"passkey_count": 1,
"has_mfa_secret": false
}
]

GET /api/admin/users/:id

Returns a single user.


POST /api/admin/users

Creates a new user directly (email confirmation can be skipped by setting is_active: true).

Request Body

{
"username": "string",
"email": "string",
"password": "string (min. 8 characters)",
"first_name": "string (optional)",
"last_name": "string (optional)",
"is_admin": false,
"is_active": true
}

Response 201 – The created user


PUT /api/admin/users/:id

Updates a user's profile, roles, and status.

Request Body

{
"username": "string",
"email": "string",
"first_name": "string (optional)",
"last_name": "string (optional)",
"is_admin": false,
"is_active": true
}

POST /api/admin/users/:id/reset-password

Resets a user's password.

Request Body

{
"password": "string (min. 8 characters)"
}

Response

{
"message": "Password reset"
}

POST /api/admin/users/:id/reset-mfa

Resets a user's MFA (deletes the secret and disables MFA).

Response

{
"message": "MFA reset"
}

DELETE /api/admin/users/:id/passkeys

Deletes all passkeys for a user.

Response

{
"message": "All passkeys deleted"
}

DELETE /api/admin/users/:id

Deletes a user and all their passes (CASCADE). Admins cannot delete themselves.

Response

{
"message": "User deleted"
}

Errors

StatusDescription
400Cannot delete own account
404User not found