Download OpenAPI specification:
Authenticate user with email/password or initiate OAuth flow
string <email> | |
| password | string |
| action | string Enum: "login" "register" |
| firstName | string |
| lastName | string |
| callbackUrl | string |
| json | boolean |
{- "url": "/dashboard",
- "ok": true
}{- "user": {
- "id": "123e4567-e89b-12d3-a456-426614174000",
- "email": "user@example.com",
- "name": "John Doe",
- "emailVerified": "2023-01-01T00:00:00Z"
}, - "expires": "2023-01-01T12:00:00Z"
}{- "credentials": {
- "id": "credentials",
- "name": "Credentials",
- "type": "credentials"
}, - "google": {
- "id": "google",
- "name": "Google",
- "type": "oauth"
}, - "apple": {
- "id": "apple",
- "name": "Apple",
- "type": "oauth"
}, - "email": {
- "id": "email",
- "name": "Email",
- "type": "email"
}
}Handle OAuth provider callback (Google, Apple)
| provider required | string Enum: "google" "apple" Example: google |
| code | string Authorization code from OAuth provider |
| state | string State parameter for CSRF protection |
| error | string Error code if authentication failed |
{- "error": "Configuration",
- "message": "There is a problem with the server configuration"
}Allows moderator to change the status of a video (approve, reject, etc.)
| id required | string <uuid> Example: 123e4567-e89b-12d3-a456-426614174000 Video ID |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| status required | string Enum: "approved" "rejected" "pending" New status for the video |
| reason | string Optional reason for status change |
{- "status": "approved",
- "reason": "Content approved after review"
}{- "success": true,
- "data": {
- "videoId": "3524e86f-1bba-489a-bf6b-386ea1abbac0",
- "status": "approved",
- "message": "Video status updated successfully"
}
}Retrieves detailed information about a specific video including available quality URLs
| id required | string <uuid> Example: 123e4567-e89b-12d3-a456-426614174000 Video ID |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "id": "123e4567-e89b-12d3-a456-426614174000",
- "uploaderId": "123e4567-e89b-12d3-a456-426614174000",
- "title": "Help needed for my situation",
- "description": "I need help with...",
- "status": "approved",
- "qualities": {
}, - "orientation": "9:16",
- "approvedAt": "2025-10-01T12:00:00Z",
- "createdAt": "2025-10-01T10:00:00Z"
}
}Donate coins to a video creator (help seeker)
| id required | string <uuid> Example: 123e4567-e89b-12d3-a456-426614174000 Video ID to donate to |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| coins required | integer >= 1 Number of coins to donate |
| message | string <= 500 characters Optional donation message |
{- "coins": 50,
- "message": "Hope this helps!"
}{- "success": true,
- "data": {
- "donationId": "123e4567-e89b-12d3-a456-426614174000",
- "message": "Donation made successfully"
}
}Retrieves paginated list of approved videos that the authenticated user hasn't seen yet
| page | integer >= 1 Default: 1 Example: page=1 Page number for pagination |
| limit | integer [ 1 .. 50 ] Default: 10 Example: limit=10 Number of videos per page |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "items": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "uploaderId": "16696ca1-e316-446e-81c4-029fea7eecc7",
- "title": "string",
- "description": "string",
- "qualities": { },
- "donations": 0
}
], - "page": 0,
- "limit": 0,
- "hasMore": true
}
}Retrieves a paginated list of approved videos sorted by approval date
| page | integer >= 1 Default: 1 Example: page=1 Page number for pagination |
| limit | integer [ 1 .. 50 ] Default: 20 Example: limit=20 Number of videos per page |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "items": [
- {
- "id": "123e4567-e89b-12d3-a456-426614174000",
- "uploaderId": "123e4567-e89b-12d3-a456-426614174000",
- "title": "Help needed for my situation",
- "description": "I need help with...",
- "qualities": {
}, - "approvedAt": "2025-10-01T12:00:00Z",
- "likes": 123,
- "commentsCount": 5
}
], - "page": 1,
- "limit": 20,
- "hasMore": true
}
}Retrieves a paginated list of all videos that have been transcoded (processed) for moderator review
| page | integer >= 1 Default: 1 Example: page=1 Page number for pagination |
| limit | integer [ 1 .. 50 ] Default: 20 Example: limit=20 Number of videos per page |
| status | string Enum: "pending" "approved" "rejected" Example: status=pending Filter by status |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "items": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "uploaderId": "16696ca1-e316-446e-81c4-029fea7eecc7",
- "title": "string",
- "description": "string",
- "status": "pending",
- "transcodingStatus": "pending",
- "qualities": { },
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "limit": 0,
- "hasMore": true
}
}Uploads a vertical video (9:16) for the platform. Each user can only have one video.
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| video required | string <binary> Video file (MP4, max 100MB) |
| title required | string Video title |
| description | string Optional video description |
{- "success": true,
- "data": {
- "videoId": "123e4567-e89b-12d3-a456-426614174000",
- "message": "Video uploaded successfully"
}
}Retrieves the current wallet balance including available and locked coins
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "coinsAvailable": 1500,
- "coinsLocked": 200,
- "coinsPending": 100,
- "totalCoins": 1800,
- "lastUpdated": "2025-10-01T12:00:00Z"
}
}Retrieves a list of available coin packages for purchase
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "packages": [
- {
- "id": "123e4567-e89b-12d3-a456-426614174000",
- "name": "Small Pack",
- "coins": 100,
- "priceCents": 999,
- "priceFormatted": "€9.99",
- "active": true,
- "description": "Perfect for small donations"
}
]
}
}Initiates a coin package purchase with payment provider
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| packageId required | string <uuid> ID of the coin package to purchase |
| provider required | string Enum: "stripe" "apple_pay" "google_pay" Payment provider |
| platform | string Enum: "ios" "android" "web" Platform for in-app purchases |
| idempotencyKey | string Idempotency key to prevent duplicate purchases |
{- "packageId": "123e4567-e89b-12d3-a456-426614174000",
- "provider": "stripe",
- "platform": "ios",
- "idempotencyKey": "purchase-123-456"
}{- "success": true,
- "data": {
- "purchaseId": "123e4567-e89b-12d3-a456-426614174000",
- "paymentIntent": {
- "clientSecret": "pi_123_secret_456",
- "amount": 999,
- "currency": "eur"
}, - "message": "Purchase initiated successfully"
}
}Retrieves paginated payout history for the authenticated user
| page | integer >= 1 Default: 1 Example: page=1 Page number for pagination |
| limit | integer [ 1 .. 50 ] Default: 20 Example: limit=20 Number of payouts per page |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "items": [
- {
- "payoutId": "123e4567-e89b-12d3-a456-426614174000",
- "createdAt": "2025-10-20T10:12:00Z",
- "status": "paid",
- "amount": 5000,
- "fee": 200,
- "netAmount": 4800,
- "method": "SEPA",
- "targetMasked": "DE**1234",
- "provider": "Stripe",
- "txRef": "pi_123",
- "events": [
- {
- "status": "pending",
- "createdAt": "2025-10-20T10:12:00Z",
- "note": "Payout request created"
}
]
}
], - "page": 1,
- "limit": 20,
- "hasMore": false
}
}Request a payout of coins to external payment method
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| amount required | integer >= 100 Amount of coins to payout (minimum 100) |
| iban required | string^[A-Z]{2}[0-9]{2}[A-Z0-9]+$ IBAN (International Bank Account Number) |
| bic required | string^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$ BIC (Bank Identifier Code) |
| bankName required | string Name of the credit institution |
| recipientName required | string Name of the payment recipient |
{- "amount": 1000,
- "iban": "DE89370400440532013000",
- "bic": "COBADEFFXXX",
- "bankName": "Commerzbank AG",
- "recipientName": "Max Mustermann"
}{- "success": true,
- "data": {
- "payoutId": "123e4567-e89b-12d3-a456-426614174000",
- "message": "Payout request created successfully"
}
}Prepares Apple In-App Purchase with product ID and validates package
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| packageId required | string <uuid> ID of the coin package to purchase |
| productId required | string Apple App Store product ID (e.g., com.spendora.coins.100) |
| idempotencyKey | string Optional idempotency key for tracking purposes |
{- "packageId": "123e4567-e89b-12d3-a456-426614174000",
- "productId": "com.spendora.coins.100",
- "idempotencyKey": "payment-123-456"
}{- "success": true,
- "data": {
- "purchaseId": "123e4567-e89b-12d3-a456-426614174000",
- "productId": "com.spendora.coins.100",
- "packageId": "471cc1d4-ec27-4504-b7c2-949af95662bc",
- "amount": 9.99,
- "coins": 100,
- "message": "Ready for Apple In-App Purchase"
}
}Verifies Apple receipt and credits coins to user
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| receipt required | string Base64-encoded receipt data from App Store |
| packageId required | string <uuid> ID of the coin package purchased |
| sandbox | boolean Default: false Use sandbox environment for testing |
{- "receipt": "MIIBkAYJKoZIhvcNAQcCoIIBgTCCAX0CAQExCzAJBgUr...",
- "packageId": "123e4567-e89b-12d3-a456-426614174000",
- "sandbox": false
}Prepares Google Play In-App Purchase with product ID and validates package
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| packageId required | string <uuid> ID of the coin package to purchase |
| productId required | string Google Play product ID (e.g., coins_100) |
| idempotencyKey | string Optional idempotency key for tracking purposes |
{- "packageId": "123e4567-e89b-12d3-a456-426614174000",
- "productId": "coins_100",
- "idempotencyKey": "payment-123-456"
}{- "success": true,
- "data": {
- "purchaseId": "123e4567-e89b-12d3-a456-426614174000",
- "productId": "coins_100",
- "packageId": "471cc1d4-ec27-4504-b7c2-949af95662bc",
- "amount": 9.99,
- "coins": 100,
- "message": "Ready for Google Play In-App Purchase"
}
}Verifies Google Play purchase token and credits coins to user
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| purchaseToken required | string Purchase token from Google Play |
| productId required | string Google Play product ID |
| packageId required | string <uuid> ID of the coin package purchased |
| packageName | string Android package name (defaults to env var) |
{- "purchaseToken": "opaque-token-up-to-1500-characters",
- "productId": "coins_100",
- "packageId": "123e4567-e89b-12d3-a456-426614174000",
- "packageName": "com.spendora.app"
}Creates a Stripe Checkout Session for coin package purchase
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| packageId required | string <uuid> ID of the coin package to purchase |
| successUrl required | string <uri> URL to redirect after successful payment |
| cancelUrl required | string <uri> URL to redirect after cancelled payment |
| idempotencyKey | string Optional idempotency key for Stripe API |
{- "packageId": "123e4567-e89b-12d3-a456-426614174000",
- "idempotencyKey": "payment-123-456"
}{- "success": true,
- "data": {
- "sessionId": "cs_test_123",
- "purchaseId": "123e4567-e89b-12d3-a456-426614174000"
}
}Registers a push notification token for the authenticated user
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| token required | string Push notification token |
| platform required | string Enum: "ios" "android" "web" Platform of the device |
{- "token": "fGhJkL123456...",
- "platform": "ios"
}{- "success": true,
- "data": {
- "tokenId": "123e4567-e89b-12d3-a456-426614174000",
- "message": "Push token registered successfully"
}
}Unregisters a push notification token for the authenticated user
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| token | string Example: token=fGhJkL123456... Token to unregister (optional, if not provided, unregisters all tokens for user) |
| platform | string Enum: "ios" "android" "web" Example: platform=ios Platform filter (optional) |
{- "success": true,
- "data": {
- "unregistered": 1,
- "message": "Push token unregistered successfully"
}
}Retrieves the current authenticated user's information including preferences
{- "success": true,
- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "firstName": "string",
- "lastName": "string",
- "role": "helper",
- "locale": "de"
}
}Allows moderator to change the status of a video (approve, reject, etc.)
| id required | string <uuid> Example: 123e4567-e89b-12d3-a456-426614174000 Video ID |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
| status required | string Enum: "approved" "rejected" "pending" New status for the video |
| reason | string Optional reason for status change |
{- "status": "approved",
- "reason": "Content approved after review"
}{- "success": true,
- "data": {
- "videoId": "3524e86f-1bba-489a-bf6b-386ea1abbac0",
- "status": "approved",
- "message": "Video status updated successfully"
}
}Retrieves a paginated list of all videos that have been transcoded (processed) for moderator review
| page | integer >= 1 Default: 1 Example: page=1 Page number for pagination |
| limit | integer [ 1 .. 50 ] Default: 20 Example: limit=20 Number of videos per page |
| status | string Enum: "pending" "approved" "rejected" Example: status=pending Filter by status |
| locale | string Enum: "de" "en" Example: locale=en Language preference for error messages |
{- "success": true,
- "data": {
- "items": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "uploaderId": "16696ca1-e316-446e-81c4-029fea7eecc7",
- "title": "string",
- "description": "string",
- "status": "pending",
- "transcodingStatus": "pending",
- "qualities": { },
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "limit": 0,
- "hasMore": true
}
}